Объединения параметров функции вывода Typescript - PullRequest
0 голосов
/ 22 мая 2018

В настоящее время у меня есть интерфейс с перегруженными функциями, например:

export interface IEvents {
  method(): boolean;
  on(name: 'eventName1', listener: (obj: SomeType) => void): void;
  on(name: 'eventName2', listener: (obj: SomeType) => void): void;
  on(name: 'eventName3', listener: (obj: SomeType) => void): void;
  on(name: 'eventName4', listener: (obj: SomeType) => void): void;
  on(name: 'eventName5', listener: (obj: SomeType) => void): void;
  on(name: 'eventName6', listener: () => void): void;
  on(name: 'eventName7', listener: (obj: SomeType) => void): void;
  on(name: 'eventName8', listener: (obj: SomeType) => void): void;
}

Я пытаюсь получить объединенный тип имен событий, например, так:

eventName1 |eventName2 |...

Я пробовал следующее, но когда я делаю вывод о типе, кажется, что выбирается только одно из значений имени, а не объединение всех из них.

export type TEventExtension<T extends IEvents> {
  [K in keyof T]: K extends 'on' ? TEventListenerName<T[K]> : never;
}[keyof T];
export type TEventListenerName<T> = T extends (name: infer N, listener: (obj?: infer E) => void) => void ? N : never;
const ext: TEventExtension<IEvents> = void 0 as any; // Type: 'eventName8'

Я также пытался использовать тип аккумулятора для отслеживания союзов, но Typescript не допускает рекурсивных обобщений.

Любые идеи о том, как мне это сделать?

Редактировать: Интерфейс сперегруженные определения существуют во внешнем модуле.Я пытаюсь избежать c + ping от внешних определений до моих определений, и вместо этого он автоматически создает тип.

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Это не должен быть отдельный ответ, но это трудно получить в комментарии: перегрузки не работают так, как вы хотите, с выводом типа в условных типах :

При выводе из типа с несколькими сигнатурами вызовов (например, типа перегруженной функции) выводы делаются из последней сигнатуры (что, по-видимому, является наиболее допустимым универсальным случаем).Невозможно выполнить разрешение перегрузки на основе списка типов аргументов.

declare function foo(x: string): number;
declare function foo(x: number): string;
declare function foo(x: string | number): string | number;
type T30 = ReturnType<typeof foo>;  // string | number

Если вы не можете превратить перегрузки в одну функцию с объединением параметров (используя условные типы дляполучите listener для "eventName6" правильно), тогда я не знаю способа сделать это программно.

0 голосов
/ 22 мая 2018

Не думаю, что ты можешь.Используя type infer в этом примере:

interface SomeType {

}

export interface IEvents {
  method(): boolean;
  on(name: "eventName1", listener: (obj: SomeType) => void): 13;
  on(name: "eventName2", listener: (obj: SomeType) => void): void;
  on(name: "eventName3", listener: (obj: SomeType) => void): undefined;
  on(name: "eventName4", listener: (obj: SomeType) => void): 14;
  on(name: "eventName5", listener: (obj: SomeType) => void): 10;
  on(name: "eventName6", listener: () => void): "hola";
  on(name: "eventName8", listener: (obj: SomeType) => void): 200;
  on(name: "eventName7", listener: (obj: SomeType) => void): void;
}

const x: ReturnType<IEvents["on"]> = 200;

Он обвиняет насчет x не в void, но один из возможных ReturnType в IEvents - 200. Похоже, он пытается только с последним.

Так что я предполагаю, что если вы попытаетесь сделать что-то похожее с первым аргументом функции, он получит только последний.

Здесь у вас есть определение ReturnType:

https://github.com/Microsoft/TypeScript/blob/release-2.8/lib/lib.d.ts#L1386

...