Как я могу получить тип приложения функции в TypeScript? - PullRequest
2 голосов
/ 04 марта 2020

Как я могу получить тип универсальной c функции, применяемой к параметру в TypeScript?

Например, как я могу определить Apply ниже?

declare function f<T>(t: T): T extends number ? boolean : object;

type ResForNumArg = Apply<typeof f, number>;    // should be boolean
type ResForStringArg = Apply<typeof f, object>; // should be object

ссылка на игровую площадку

Если нет способа сделать это, можно обойти проблему для определенных c случаев, создав псевдоним типа, который является версией функции на уровне типа, как F ниже:

declare function f<T>(t: T): T extends number ? boolean : object;
type ApplyF<T> = T extends number ? boolean : object;

type ResForNumArg = ApplyF<number>;    // boolean
type ResForStringArg = ApplyF<object>; // object

Но ApplyF может не совпадать с c с f и раздражает при наборе. Есть ли лучший способ?

Обновление: похоже, это связано с https://github.com/microsoft/TypeScript/issues/29043

1 Ответ

1 голос
/ 04 марта 2020

Как вы правильно обнаружили, невозможно использовать объявление функции в качестве типа generi c, невозможно применить generi c без выполнения функции. Мы можем применять generi c только во время вызова функции (или получим из аргумента):

const r1 = f<number>(1) //  boolean
const r2 = f(1) // boolean

Хорошо, поэтому мы понимаем, что это невозможно. Теперь обходной путь, чтобы он работал без потери связи с оригинальным объявлением, я предлагаю дополнительный шаблон c type FType. Рассмотрим:

type FType<T> = (t: T) => T extends number ? boolean : object;
// join function declaration with FType:
declare function f<T>(...t: Parameters<FType<T>>): ReturnType<FType<T>>

type ResForNumArg =  ReturnType<FType<number>>;    // bool 
type ResForStringArg = ReturnType<FType<object>>;  // object

Используя типы утилит Parameters и ReturnType, я связал FType с объявлением функции f. Это многословно, но мы наконец получаем то, что хотим, и FType можно применять стандартным способом.

Playground link

...