Pesquisa de site

genéricos - Como posso obter o tipo de uma aplicação de função em TypeScript?


Como posso obter o tipo de uma função genérica aplicada a um parâmetro em TypeScript?

Por exemplo, como eu poderia definir Apply abaixo?

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

link do playground

Se não houver maneira de fazer isso, pode-se contornar o problema para casos específicos criando um alias de tipo que seja uma versão em nível de tipo da função, como F abaixo:

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

Mas ApplyF pode ficar fora de sincronia com f e é chato de digitar. Existe uma maneira melhor?

Atualização: isso parece estar relacionado a https://github.com/microsoft/TypeScript/issues/29043

Resposta #1

Como você corretamente descobriu, não é possível usar a declaração de função como tipo genérico, não é possível aplicar o genérico sem a execução da função. Só podemos aplicar o genérico durante a chamada da função (ou será inferido a partir do argumento):

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

Ok, então entendemos que não é possível. Agora, a solução alternativa, para fazê-lo funcionar sem perder a conexão com a declaração original, eu proponho um tipo genérico adicional FType. Considere:

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

Usando os tipos utilitários Parameters e ReturnType, eu conectei FType com a declaração da função f. É detalhado, mas finalmente conseguimos o que queremos e FType pode ser aplicado da maneira padrão.

Link do playground

Artigos relacionados