Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

238
Views
TypeScript: ¿Es posible definir una función variádica que acepte diferentes tipos de argumentos?

Quiero escribir una función genérica que acepte un número variable de argumentos que pueden tener diferentes tipos y devuelva una tupla basada en esos argumentos.

Aquí hay un ejemplo en JavaScript:

 function evaluate (...fns) { return fns.map(fn => fn()) } evaluate( () => 10 ) // [ 10 ] evaluate( () => 10, () => 'f', () => null ) // [ 10, 'f', null ]

Y en TypeScript necesito convertir de alguna manera la tupla del argumento extendido en una resultante:

 function evaluate<T1, T2 ... Tn> ( ...fns: [() => T1, () => T2 ... () => Tn] ): [T1, T2 ... Tn] { return fns.map(fn => fn()) as [T1, T2 ... Tn] } evaluate( () => 10 ) // [ 10 ]: [number] evaluate( () => 10, () => 'f', () => null ) // [ 10, 'f', null ]: [number, string, null]

Probé un enfoque ingenuo de crear una sobrecarga para todas las longitudes razonables de tupla:

 function evaluate<T1> ( fn1: () => T1 ): [T1] function evaluate<T1, T2> ( fn1: () => T1, fn2: () => T2 ): [T1, T2] function evaluate<T1, T2, T3> ( fn1: () => T1, fn2: () => T2, fn3: () => T3 ): [T1, T2, T3] function evaluate<T1, T2, T3> ( ...fns: Array<(() => T1) | (() => T2) | (() => T3)> ): [T1] | [T1, T2] | [T1, T2, T3] { return fns.map(fn => fn()) as [T1] | [T1, T2] | [T1, T2, T3] }

Pero se ve horrible, no escala bien y causa problemas con un cuerpo funcional más complejo.

¿Hay alguna manera de que esto se pueda hacer dinámicamente? ¡Gracias!

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

La forma más fácil de implementar esto es hacer que la evaluate() sea genérica en su tipo de salida tipo matriz T (que pretende ser un tipo de tupla ) y luego representar el parámetro rest de fns como un tipo asignado en T , teniendo en cuenta que los tipos de matriz/tupla asignados son también tipos de matriz/tupla :

 function evaluate<T extends any[]>( ...fns: { [I in keyof T]: () => T[I] } ) { return fns.map(fn => fn()) as T; }

Tenga en cuenta que la aserción de tipo as T es necesaria porque el compilador no puede ver que fns.map(fn => fn()) tendrá el efecto de convertir una matriz/tupla de tipos de funciones en la matriz/tupla de tipos de devolución correspondientes. Consulte Asignación de valores con tipo de tupla a diferentes valores con tipo de tupla sin conversiones para obtener más información.

Debido a que {[I in keyof T]: () => T[I]} es un tipo mapeado homomórfico donde estamos mapeando directamente sobre keyof T (consulte ¿Qué significa "tipo mapeado homomórfico"? para obtener más información), el compilador es capaz de inferir T de él (la página vinculada está en desuso, pero aún es precisa y no existe una nueva página 🤷‍♂️).

Veámoslo en acción:

 const x = evaluate(() => 10); // const x: [number] const y = evaluate( () => 10, () => 'f', () => null ) // const y: [number, string, null]

Se ve bien. El compilador ve que x es de tipo [number] e y es de tipo [number, string, null] . También se comporta razonablemente en los casos en los que pasa un argumento de reposo de orden/longitud desconocidos:

 const fs = [() => "a", () => 3]; // const fs: ((() => string) | (() => number))[] const z = evaluate(...fs); // const z: (string | number)[]

Aquí fs es del tipo Array<(()=>string) | (()=>number)> , por lo que z es del tipo análogo Array<string | number> .

Enlace del patio de recreo al código

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!