Estoy tratando de crear una firma de función relativamente simple como la siguiente:
function<U>(...args:U[]):U {/* body */}Quiero que TypeScript combine los tipos de argumentos pasados a una unión en lugar de simplemente inferir U como el tipo del primer argumento. Por favor, ¿cómo voy a hacer esto?
El problema que tienes es que el siguiente código produce un error de compilación:
function f<U>(...args: U[]): U { return args[Math.floor(Math.random() * args.length)] } const a = f("string", 123, true); // error! // ~~~ <-- error! 123 is not a string // U inferred as string // const a: stringLas heurísticas del compilador evitan inferir una unión aquí porque a menudo la gente quiere que ocurra ese error. Consulte ¿Por qué el argumento de tipo no se infiere como un tipo de unión? para más información.
Hay una solicitud de función abierta en microsoft/TypeScript#44312 que solicita alguna forma de decirle al compilador que desea una unión en lugar de un error. Por ahora esto no es posible, por lo que si desea un comportamiento similar, debe utilizar soluciones alternativas.
Una solución común es cambiar la función para que sea genérica no en el tipo U de los elementos de args , sino en el tipo de matriz T de args en sí . A partir de ahí, puede indexar ese tipo con number para obtener el tipo de elemento. Es decir, si T es un tipo tipo matriz, entonces T[number] es el tipo de elemento (ya que ese es el tipo que obtienes cuando indexas la matriz con un number ):
function f<T extends any[]>(...args: T): T[number] { return args[Math.floor(Math.random() * args.length)] } const a = f("string", 123, true); // T inferred as [string, number, boolean] // const a: string | number | boolean Ahora no hay ningún error, y el tipo de a es la unión que querías.