¿Es posible utilizar getters / setters en la definición de la interfaz?

93

Por el momento, TypeScriptno permite usar métodos get / set (accesores) en interfaces. Por ejemplo:

interface I {
      get name():string;
}

class C implements I {
      get name():string {
          return null;
      } 
}

Además, TypeScript no permite usar Array Function Expression en métodos de clase: por ejemplo:

class C {
    private _name:string;

    get name():string => this._name;
}

¿Hay alguna otra forma en que pueda usar un getter y setter en una definición de interfaz?

Ivan Popov
fuente

Respuestas:

126

Puede especificar la propiedad en la interfaz, pero no puede hacer cumplir si se utilizan captadores y definidores, así:

interface IExample {
    Name: string;
}

class Example implements IExample {
    private _name: string = "Bob";

    public get Name() {
        return this._name;
    }

    public set Name(value) {
        this._name = value;
    }
}

var example = new Example();
alert(example.Name);

En este ejemplo, la interfaz no obliga a la clase a usar getters y setters, podría haber usado una propiedad en su lugar (ejemplo a continuación), pero se supone que la interfaz oculta estos detalles de implementación de todos modos, ya que es una promesa para el código de llamada. sobre lo que puede llamar.

interface IExample {
    Name: string;
}

class Example implements IExample {
    // this satisfies the interface just the same
    public Name: string = "Bob";
}

var example = new Example();
alert(example.Name);

Y, por último, =>no está permitido para los métodos de clase; puede iniciar una discusión sobre Codeplex si cree que hay un caso de uso candente para ello. Aquí hay un ejemplo:

class Test {
    // Yes
    getName = () => 'Steve';

    // No
    getName() => 'Steve';

    // No
    get name() => 'Steve';
}
Fenton
fuente
1
Puede usar =>para definir métodos de clase como este: name = (a: string) => this._name;pero en el JS de salida se definirá dentro de la función de clase en lugar de extender su objeto prototipo.
orad
esto no parece funcionar con propiedades get estáticas: /
CervEd
46

Para complementar las otras respuestas, si su deseo es definir un get valueen una interfaz, puede usar readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

class Bar implements Foo {
  get value() {
    return 10;
  }
}

pero hasta donde yo sé, y como otros mencionaron, actualmente no hay forma de definir una propiedad de solo conjunto en la interfaz. Sin embargo, puede mover la limitación a un error de tiempo de ejecución (útil solo durante el ciclo de desarrollo):

interface Foo {
  /* Set Only! */
  value: number;
}

class Bar implements Foo {
  _value:number;
  set value(value: number) {
    this._value = value;
  }
  get value() {
    throw Error("Not Supported Exception");
  }
}

Práctica no recomendada ; pero una opción.

Meirion Hughes
fuente
2

En primer lugar, Letra de imprenta sólo es compatible gety setsintaxis al que apuntan a ECMAScript 5. Para lograrlo, hay que llamar al compilador

tsc --target ES5

Las interfaces no admiten getters ni setters. Para que su código se compile, tendrá que cambiarlo a

interface I { 
    getName():string;
}

class C implements I { 
    getName():string {
          return null;
    }   
}

Lo que admite mecanografiado es una sintaxis especial para campos en constructores. En tu caso, podrías tener

interface I {
    getName():string;
}

class C implements I {
    constructor(public name: string) {
    }
    getName():string {
        return name;
    }
}

Observe cómo la clase Cno especifica el campo name. En realidad, se declara usando azúcar sintáctico public name: stringen el constructor.

Como señala Sohnee, se supone que la interfaz oculta los detalles de implementación. En mi ejemplo, he elegido la interfaz para requerir un método getter de estilo java. Sin embargo, también puede establecer una propiedad y luego dejar que la clase decida cómo implementar la interfaz.

Valentin
fuente
1
Puede utilizar gety setpalabras clave en TypeScript.
Fenton
Una nota al margen sobre la compatibilidad con ECMAScript 5: Object.definePropertyes compatible con IE8 +, FF4 +, Opera 12+, WebKit y Safari. También hay un EC5 Shim en github.com/kriskowal/es5-shim
Fenton
-1

Usando TypeScript 3.4:

interface IPart {
    getQuantity(): number;
}

class Part implements IPart {
    private quantity: number;
    constructor(quantity: number) {
        this.quantity = quantity;
    }
    public getQuantity = (): number => {
        return this.quantity;
    };
}

let part = new Part(42);

// When used in typescript, quantity is not accessible.
// However, when compiled to javascript it will log '42'.
console.log(part.quantity);

// Logs '42'.
console.log(part.getQuantity());

Vea el ejemplo en TypeScript Playground .

Jack
fuente