Вывод типа Typescript из параметров типа - PullRequest
0 голосов
/ 23 ноября 2018

Я не понимаю, почему Typescript не может правильно вывести типы в следующем случае, который включает вывод из параметров типа.(Этот вопрос похож на Проблема вывода типа TypeScript , но это несколько другой случай. Однако ответ может быть таким же, что мне просто не повезло!)

// A base class for a dialog taking parameter of type P
// and returning result of type R.
class BaseDialog<P, R> { p: P; r: R; }

class ValueDialog extends BaseDialog<string, number> {}

// A function that shows the dialog
show<T extends BaseDialog<P, R>, P, R>(dlg: Type<T>, param: P): Promise<R> {}

Примечание: Чтобы упростить сигнатуру метода, я использую Angular Type:

export interface Type<T> extends Function {
  new (...args: any[]): T;
}

Теперь, когда я вызываю метод show, как показано ниже, тип R не выводится правильно:

show(ValueDialog, "name").then(r => console.log(r));

Компилятор выводит:

T = ValueDialog
P = string
R = {}

Поскольку T правильно выведен, вы можете подумать, что компилятор может вывести P и R из ValueDialogЭто определение, но оно не так.

Конечно, я могу это исправить, указав типы вручную, но это довольно уродливо.Я также могу исправить это, сделав P и R одинаковыми, но это не та функциональность, которую я хочу.

Как я могу определить show(), чтобы она правильно выводила R?

1 Ответ

0 голосов
/ 23 ноября 2018

Вы можете использовать условный тип для извлечения параметра типа R из базового типа.Вам нужно будет каким-то образом использовать тип R, чтобы это работало:

export interface Type<T> extends Function {
    new (...args: any[]): T;
}
class BaseDialog<P, R> {
    value: R //we need to use R in some  way for the parameter to make a difference
}

class ValueDialog extends BaseDialog<string, number> {}


type ExtractResult<T extends BaseDialog<any, any>> = T extends BaseDialog<any, infer R> ? R : never; 
// A function that shows the dialog
declare function show<T extends BaseDialog<P, any>, P>(dlg: Type<T>, param: P): Promise<ExtractResult<T>>;

show(ValueDialog, "name").then(r => console.log(r)); // r is now string
...