typescript - Argumento predeterminado que determina el tipo de método genérico
Definí un método genérico cuyo tipo genérico está determinado por uno de los argumentos:
myMethod<T>(param1: number, param2: T): T {
return param2;
}
Ahora, me gustaría tener un valor predeterminado para el parámetro, y T entonces se determinaría por el tipo del valor predeterminado:
myMethod<T>(param1: number, param2: T = 'myDefaultString'): T {
return param2;
}
Pero eso no compila, porque espera que "string" coincida con T en lugar de determinar que T es 'string'.
Una solución sería escribir:
myMethod<T>(param1: number, param2: T = <any>'myDefaultString'): T {
return param2;
}
Pero entonces necesito especificar el tipo explícitamente en el sitio de llamada:
const val: string = this.myMethod<string>();
Otra solución que consideré fue escribir una segunda función, sin el argumento por defecto:
myMethod<T>(param1: number, param2: T): T {
return param2;
}
myMethodDefault(param1: number): string {
return myMethod(param1, 'myDefaultString');
}
Pero entonces necesito un nombre diferente para ello, y eso me molesta.
¿Hay una mejor manera de hacer esto?
Respuesta #1
La parte del tipo puede cumplirse con un parámetro de tipo genérico por defecto (desde TypeScript 2.3):
class Hey {
myMethod<T = string>(arg1: number, arg2?: T): T {
if (arg2 === undefined)
// have to handle default parameter manually
return "myDefaultString" as any as T;
return arg2;
}
}
const h = new Hey();
// n1: string;
const n1 = h.myMethod(1);
// n2: typeof "mm"
const n2 = h.myMethod(2, "mm");
// n3: { a: number }
const n3 = h.myMethod(3, { a: 1 });
Respuesta #2
myMethod<T>(param1: number, param2: T = 'myDefaultString'): T {
return param2;
}
El código anterior es efectivamente inválido, porque la expresión inst.myMethod<number>(23) tendría el tipo number, mientras que en tiempo de ejecución seguiría siendo un string.
Puedes evitar esto usando sobrecargas de firma:
// with only one param, the return type is a string:
myMethod(param1: number): string
// with two params, use a type parameter:
myMethod<T>(param1: number, param2: T): T
myMethod(param1: number, param2: any = 'myDefaultString') {
return param2;
}
Esta versión hace que inst.myMethod<number>(23) sea inválido, porque la firma con un parámetro de tipo requiere un segundo parámetro.
