Typescript: Forzar que el tipo genérico por defecto sea `any` en lugar de `{}`
Tengo una función a que debería devolver any si no se proporciona un tipo genérico, T en caso contrario.
var a = function<T>() : T {
return null;
}
var b = a<number>(); //number
var c = a(); //c is {}. Not what I want... I want c to be any.
var d; //any
var e = a<typeof d>(); //any
¿Es posible? (Obviamente sin cambiar las llamadas a funciones. Es decir, sin a<any>().)
Respuesta #1
¿Es posible? (Obviamente sin cambiar las llamadas a funciones. Es decir, sin a().)
Sí.
Creo que en tu caso lo harías
var a = function<T = any>() : T {
return null;
}
Los valores predeterminados genéricos fueron introducidos en TS 2.3.
Los tipos predeterminados para los parámetros de tipo genérico tienen la siguiente sintaxis:
TypeParameter :
BindingIdentifier Constraint? DefaultType?
DefaultType :
`=` Type
Por ejemplo:
class Generic<T = string> {
private readonly list: T[] = []
add(t: T) {
this.list.push(t)
}
log() {
console.log(this.list)
}
}
const generic = new Generic()
generic.add('hello world') // Works
generic.add(4) // Error: Argument of type '4' is not assignable to parameter of type 'string'
generic.add({t: 33}) // Error: Argument of type '{ t: number; }' is not assignable to parameter of type 'string'
generic.log()
const genericAny = new Generic<any>()
// All of the following compile successfully
genericAny.add('hello world')
genericAny.add(4)
genericAny.add({t: 33})
genericAny.log()
Vea https://github.com/Microsoft/TypeScript/wiki/Roadmap#23-april-2017 y https://github.com/Microsoft/TypeScript/pull/13487
Respuesta #2
Llevando esto un poco más lejos para una aplicación ligeramente diferente, también puedes establecer por defecto los argumentos de tipo a otro argumento de tipo.
Por ejemplo, tomemos:
class Foo<T1 = any, T2 = T1> {
prop1: T1;
prop2: T2;
}
y así:
const foo1 = new Foo();
typeof foo1.prop1 // any
typeof foo1.prop1 // any
const foo2 = new Foo<string>();
typeof foo2.prop1 // string
typeof foo2.prop2 // string
const foo3 = new Foo<string, number>();
typeof foo3.prop1 // string
typeof foo3.prop1 // number
