É possível usar getters / setters na definição da interface?

93

No momento, TypeScriptnão permite o uso de métodos get / set (acessores) em interfaces. Por exemplo:

interface I {
      get name():string;
}

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

além disso, o TypeScript não permite o uso de Array Function Expression em métodos de classe: por exemplo:

class C {
    private _name:string;

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

Existe alguma outra maneira de usar um getter e setter em uma definição de interface?

Ivan Popov
fonte

Respostas:

125

Você pode especificar a propriedade na interface, mas não pode impor se getters e setters são usados, como este:

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);

Neste exemplo, a interface não força a classe a usar getters e setters, eu poderia ter usado uma propriedade (exemplo abaixo) - mas a interface deve ocultar esses detalhes de implementação de qualquer maneira, pois é uma promessa para o código de chamada sobre o que pode chamar.

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);

E, por último, =>não é permitido para métodos de classe - você pode iniciar uma discussão no Codeplex se achar que há um caso de uso ardente para ele. Aqui está um exemplo:

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

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

    // No
    get name() => 'Steve';
}
Fenton
fonte
1
Você pode usar =>para definir métodos de classe como este: name = (a: string) => this._name;mas no JS de saída, ele será definido dentro da função de classe em vez de estender seu objeto de protótipo.
orad
44

Para complementar as outras respostas, se seu desejo é definir um get valueem uma interface, você pode usar readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

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

mas, tanto quanto eu sei, e como outros mencionaram, não há nenhuma maneira atualmente de definir uma propriedade apenas de conjunto na interface. Você pode, no entanto, mover a limitação para um erro de tempo de execução (útil apenas durante o ciclo de desenvolvimento):

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ática não recomendada ; mas uma opção.

Meirion Hughes
fonte
2

Primeiro de tudo, Typescript só suporta gete setsintaxe quando targetting ECMAScript 5. Para conseguir isso, você tem que chamar o compilador com

tsc --target ES5

As interfaces não oferecem suporte a getters e setters. Para obter o seu código para compilar, você teria que alterá-lo para

interface I { 
    getName():string;
}

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

O que o typescript suporta é uma sintaxe especial para campos em construtores. No seu caso, você poderia ter

interface I {
    getName():string;
}

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

Observe como a classe Cnão especifica o campo name. Na verdade, é declarado usando açúcar sintático public name: stringno construtor.

Como Sohnee aponta, a interface deve, na verdade, ocultar quaisquer detalhes de implementação. No meu exemplo, escolhi a interface para exigir um método getter no estilo java. No entanto, você também pode definir uma propriedade e deixar a classe decidir como implementar a interface.

Valentin
fonte
1
Você pode usar palavras get- setchave e no TypeScript.
Fenton
Uma nota lateral sobre o suporte ECMAScript 5 - Object.definePropertyé compatível com IE8 +, FF4 +, Opera 12+, WebKit e Safari. Há também um EC5 Shim em 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());

Veja o exemplo em TypeScript Playground .

Jack
fonte