Búsqueda de sitios web

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

Artículos relacionados