Valores predeterminados de la interfaz mecanografiada

Resuelto d512 asked hace 8 años • 17 respuestas

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 '{}'.

d512 avatar Jan 29 '16 06:01 d512
Aceptado

¿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 undefineden 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()
basarat avatar Jan 28 '2016 23:01 basarat

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.by x.csi esas propiedades no están configuradas.

Timar avatar Apr 05 '2017 09:04 Timar

Si bien la respuesta de @Timar funciona perfectamente para nulllos 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 optionsvariable 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
Jack Miller avatar Feb 01 '2019 07:02 Jack Miller

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(...);
Nitzan Tomer avatar Jan 29 '2016 01:01 Nitzan Tomer