Typescript no está resolviendo el tipo de parámetro correcto:
functionBuilder toma un parámetro arg y, dependiendo de ese parámetro, devuelve un objeto que contiene una propiedad de función. Esa función toma un parámetro de string si arg === 'a' , de lo contrario toma un parámetro number .
const functionBuilder = (arg: string) => { if(arg === 'a'){ return { f: (val: string) => {} } } return { f: (val: number) => {} } } const f1 = functionBuilder('a'); El problema es que llamar a esa función f en f1 espera un argumento de tipo never en lugar de string
Descubrí que el tipo de functionBuilder se detectó como
const functionBuilder: (arg: string) => { f: (val: string) => void; } | { f: (val: number) => void; }que es el tipo esperado. ¿No es tipo lo que quieres? Como, ¿quieres un trato especial para "a"?
De todos modos, considere lo siguiente (el tipo de f1.f es el mismo que Type3):
type Type1 = ( (val:string) => void ) ; type Type2 = ( (val:number) => void ) ; type Type3 = Type1 | Type2 ; let TestVar: Type3; TestVar(3); //Error: Argument of type 'number' is not assignable to parameter of type 'never'.Puede parecer extraño al principio, pero ¿no es exactamente lo que "|" se supone que debe hacer? "|" significa que TestVar puede ser Type1 o Type2. Las únicas operaciones que son seguras son aquellas que satisfacen AMBOS requisitos de Tipo 1 y Tipo 2. El número 3 no cumple con el requisito de Tipo 1, mientras que la cadena '3' no cumple con el requisito de Tipo 2. De hecho, ningún argumento puede cumplir tanto el Tipo 1 como el Tipo 2. Así que es realmente "nunca".
@qrsngky da en el clavo: no hay ningún valor al que pueda pasar con seguridad ((val: string) => void) | ((val: number) => void) sin saber cuál de las dos funciones es. Para resolver esto, puede convertir el resultado de la llamada de functionBuilder al que espera:
const f1 = functionBuilder('a') as { f(val: string): void }; f1.f('…');(podría ser útil declarar un tipo de ayudante genérico para esto, como aquí )
Lo probé. Parece compilarse una vez que agrega el tipo de retorno como cualquiera.
const functionBuilder = (arg: string) : any => { if(arg === 'a'){ return { f: (val: string) => { console.log(val)} } } return { f: (val: number) => {} } }El código a ejecutar:
const f1 = functionBuilder('a'); f1.f("a");La consola emitirá el valor 'a'.