【发布时间】:2019-12-29 17:36:19
【问题描述】:
我想创建一个核心对话框类,以便在添加新对话框时,TS 将根据给定的输入自动解析对话框类型(及其返回类型)。我能够实现大部分目标,但在返回值方面我失败了。
每个对话框都返回一个Promise,promise 结果应该基于传递的dialog 类型,例如。
- 当
T是PromptDialogOptions时返回Promise<string | number>, - 当
T为ConfirmDialogOptions时返回Promise<boolean>, - 而当
T是MessageDialogOptions然后返回Promise<void>。
我创建对话框的实际代码(由于篇幅原因,我已经标记了产生错误的行并在下面解释它们):
let dialogs: DialogOptions[] = [];
newDialog<T extends DialogOptions, R extends InnerDialogType<T>>(dialog: T) : Promise<R> => {
const promise = new Promise<R>(res => {
// Set dialog resolver
dialog.resolver = res; // error #1 (see below)
});
// Create dialog close handler
dialog.closeHandler = (result: R) => { // error #2 (see below)
// Resolve a promise
dialog.resolver(result);
// Close the dialog
// this.closeDialog(dialog);
};
// Store dialog
dialogs = [...dialogs, dialog];
return promise;
}
此代码产生两个错误:
-
#1线dialog.resolver = res;
Type '(value?: R | PromiseLike | undefined) => void' 不是 可分配给类型 '((value?: void | undefined) => void) | ((价值?: 字符串 |号码 |未定义)=> 无效)| ((值?:布尔值|未定义) => 无效)|不明确的'。类型 '(value?: R | PromiseLike | undefined) => void' 不可分配给类型 '(value?: void | undefined) => void'。
-
#2线dialog.closeHandler = (result: R) => {
类型 '(result: R) => void' 不可分配给类型 '((result: void) => 无效)| ((结果:字符串|数字)=> void)| ((result: boolean) => void)'.
BaseDialog 中用于处理结果的错误类型显然存在问题。
问题
如何使BaseDialog.resolver 和BaseDialog.closeHandler 接受R 的泛型类型,这取决于传递的对话框result 类型?
我想要实现的一些例子:
const confirmDialog : ConfirmDialogOptions = {
title: "Hello",
message: "I'm stuck. Will you help?",
type: DialogType.DIALOG_CONFIRM
};
newDialog(confirmDialog);
- 预期结果:
Promise<boolean>
const dialog = {
title: "Invalid",
message: "Invalid dialog is bad!",
type: DialogType.DIALOG_MESSAGE
}
newDialog(dialog);
- 预期结果:错误,因为对话框不继承自
BaseDialog
const promptDialog : PromptDialogOptions = {
title: "Hello",
message: "Say hello",
maxLength: 10,
type: DialogType.DIALOG_PROMPT
};
newDialog(promptDialog);
- 预期结果:
Promise<string | number>
使用的所有类型
export const enum DialogType {
DIALOG_MESSAGE,
DIALOG_CONFIRM,
DIALOG_PROMPT
}
export interface BaseDialog<T> {
title: string;
message: string;
type: DialogType;
resolver?: (value?: T) => void;
}
export interface MessageDialogOptions extends BaseDialog<void> { }
export interface ConfirmDialogOptions extends BaseDialog<boolean> { }
export interface PromptDialogOptions extends BaseDialog<string | number> {
maxLength: number;
}
// Union dialogs
export type DialogOptions = MessageDialogOptions | PromptDialogOptions | ConfirmDialogOptions;
【问题讨论】:
标签: javascript typescript generics types