Búsqueda de sitios web

tipos - ¿Hay una manera de referirse a los argumentos de función en las definiciones de TypeScript?


Tengo un mapa a de {string: Function}:

const a: A = {
    foo: (x: string) => 8,
    bar: (y: number, z: boolean) => 6,
}

Luego lo transformo de manera que cada función mapeada tenga un tipo diferente de valor de retorno:

const b: B = {
    foo: (x: string) => (8).toString(),
    bar: (y: number, z: boolean) => (6).toString(),
}

En TypeScript, ¿hay alguna manera de describir el tipo B como derivado de A? En mi mundo de sueños, me gustaría poder hacer:

type A = {
    foo: (string) => number
    bar: (number, boolean) => number
}
type B = {
    [K in keyof A]: (E in argsof A[K]) => string
}

Respuesta #1

Los sueños se hacen realidad en Typescript :)

Puedes lograr esto en Typescript 3.0 usando tipos condicionales y Tuplas en parámetros rest y expresiones spread:

type A = {
    foo: (s: string) => number
    bar: (n: number, b: boolean) => number
}


type ArgumentTypes<T extends (...a: any[]) => any> = T extends (...a: infer A) => any ? A : []; 
type B = {
    [K in keyof A]:  (...a:ArgumentTypes<A[K]>) => string 
}

let b: B;
b.foo("") // works
b.foo(1) // error

Respuesta #2

Puedes lograr esto usando el tipo integrado Parameters<T> a partir de TypeScript 3.1:

type B = {
  [K in keyof A]:  (...a: Parameters<A[K]>) => string
}

Esto no está documentado explícitamente en los documentos de Typescript sobre tipos condicionales, pero tipos condicionales similares sí lo están, como ReturnType<T>, puedes verlos todos en el código fuente.

Con esto en mente, podríamos dar un paso más y relacionar B con el tipo de retorno de nuestra función de transformación usando ReturnType<T>:

const transformingFunction: (n: number) => string = (n: number) => n.toString();

type B = {
  [K in keyof A]:  (...a: Parameters<A[K]>) => ReturnType<typeof transformingFunction>
}

Así que ahora, si queremos cambiar el tipo de retorno de nuestra función de transformación, se puede hacer en un solo lugar, es decir, en la propia función sin romper la firma de B.

Artículos relacionados