Valores predeterminados de la interfaz mecanografiada
Tengo la siguiente interfaz en TypeScript:
interface IX {
a: string,
b: any,
c: AnotherType
}
Declaro una variable de ese tipo e inicializo todas las propiedades
let x: IX = {
a: 'abc',
b: null,
c: null
}
Luego les asigno valores reales en una función de inicio más tarde.
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
Pero no me gusta tener que especificar un montón de valores nulos predeterminados para cada propiedad al declarar el objeto cuando luego se establecerán en valores reales. ¿Puedo decirle a la interfaz que de forma predeterminada las propiedades que no proporciono sean nulas? ¿Qué me permitiría hacer esto?
let x: IX = {
a: 'abc'
}
sin recibir un error del compilador. Ahora mismo me dice
TS2322: El tipo '{}' no se puede asignar al tipo 'IX'. Falta la propiedad 'b' en el tipo '{}'.
¿Puedo decirle a la interfaz que de forma predeterminada las propiedades que no proporciono sean nulas? ¿Qué me dejaría hacer esto?
No. No puede proporcionar valores predeterminados para interfaces o alias de tipo, ya que son solo en tiempo de compilación y los valores predeterminados necesitan soporte en tiempo de ejecución.
Alternativa
Pero los valores que no se especifican de forma predeterminada undefined
en los tiempos de ejecución de JavaScript. Para que puedas marcarlos como opcionales:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
Y ahora, cuando lo crees, solo necesitas proporcionar a
:
let x: IX = {
a: 'abc'
};
Puede proporcionar los valores según sea necesario:
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
No puede establecer valores predeterminados en una interfaz, pero puede lograr lo que desea utilizando propiedades opcionales :
Simplemente cambie la interfaz a:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
Luego puedes hacer:
let x: IX = {
a: 'abc'
}
Y use su función init para asignar valores predeterminados x.b
y x.c
si esas propiedades no están configuradas.
Si bien la respuesta de @Timar funciona perfectamente para null
los valores predeterminados (lo que se solicitó), aquí hay otra solución fácil que permite otros valores predeterminados: defina una interfaz de opción, así como una constante correspondiente que contenga los valores predeterminados; en el constructor use el operador de extensión para establecer la options
variable miembro
interface IXOptions {
a?: string,
b?: any,
c?: number
}
const XDefaults: IXOptions = {
a: "default",
b: null,
c: 1
}
export class ClassX {
private options: IXOptions;
constructor(XOptions: IXOptions) {
this.options = { ...XDefaults, ...XOptions };
}
public printOptions(): void {
console.log(this.options.a);
console.log(this.options.b);
console.log(this.options.c);
}
}
Ahora puedes usar la clase así:
const x = new ClassX({ a: "set" });
x.printOptions();
Producción:
set
null
1
Puedes implementar la interfaz con una clase, luego puedes ocuparte de inicializar los miembros en el constructor:
class IXClass implements IX {
a: string;
b: any;
c: AnotherType;
constructor(obj: IX);
constructor(a: string, b: any, c: AnotherType);
constructor() {
if (arguments.length == 1) {
this.a = arguments[0].a;
this.b = arguments[0].b;
this.c = arguments[0].c;
} else {
this.a = arguments[0];
this.b = arguments[1];
this.c = arguments[2];
}
}
}
Otro enfoque es utilizar una función de fábrica:
function ixFactory(a: string, b: any, c: AnotherType): IX {
return {
a: a,
b: b,
c: c
}
}
Entonces puedes simplemente:
var ix: IX = null;
...
ix = new IXClass(...);
// or
ix = ixFactory(...);