Ist es möglich, Getter / Setter in der Schnittstellendefinition zu verwenden?

91

Derzeit ist die TypeScriptVerwendung von get / set-Methoden (Accessoren) in Schnittstellen nicht zulässig. Beispielsweise:

interface I {
      get name():string;
}

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

Darüber hinaus erlaubt TypeScript nicht die Verwendung von Array-Funktionsausdrücken in Klassenmethoden: zum Beispiel:

class C {
    private _name:string;

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

Gibt es eine andere Möglichkeit, einen Getter und Setter für eine Schnittstellendefinition zu verwenden?

Ivan Popov
quelle

Antworten:

125

Sie können die Eigenschaft auf der Schnittstelle angeben, aber Sie können nicht erzwingen, ob Getter und Setter wie folgt verwendet werden:

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

In diesem Beispiel zwingt die Schnittstelle die Klasse nicht dazu, Getter und Setter zu verwenden. Ich hätte stattdessen eine Eigenschaft verwenden können (Beispiel unten) - aber die Schnittstelle soll diese Implementierungsdetails trotzdem verbergen, da dies ein Versprechen für den aufrufenden Code ist darüber, was es nennen kann.

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

Und schließlich =>ist dies für Klassenmethoden nicht zulässig. Sie können eine Diskussion über Codeplex beginnen, wenn Sie der Meinung sind, dass es einen brennenden Anwendungsfall dafür gibt. Hier ist ein Beispiel:

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

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

    // No
    get name() => 'Steve';
}
Fenton
quelle
1
Sie können =>Klassenmethoden wie name = (a: string) => this._name;folgt definieren : In der Ausgabe JS wird sie jedoch innerhalb der Klassenfunktion definiert, anstatt das Prototypobjekt zu erweitern.
Orad
43

Um die anderen Antworten zu ergänzen, können Sie Folgendes verwenden, wenn Sie eine get valueauf einer Schnittstelle definieren möchten readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

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

Soweit mir bekannt ist und wie bereits erwähnt, gibt es derzeit keine Möglichkeit, eine Set-Only-Eigenschaft in der Schnittstelle zu definieren. Sie können die Beschränkung jedoch auf einen Laufzeitfehler verschieben (nur während des Entwicklungszyklus nützlich):

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

Nicht empfohlene Übung ; aber eine Option.

Meirion Hughes
quelle
2

Zunächst einmal unterstützt Typescript getund setSyntax nur, wenn es auf Ecmascript 5 abzielt. Um dies zu erreichen, müssen Sie den Compiler mit aufrufen

tsc --target ES5

Schnittstellen unterstützen keine Getter und Setter. Um Ihren Code zum Kompilieren zu bringen, müssten Sie ihn in ändern

interface I { 
    getName():string;
}

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

Was Typoskript unterstützt, ist eine spezielle Syntax für Felder in Konstruktoren. In Ihrem Fall könnten Sie haben

interface I {
    getName():string;
}

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

Beachten Sie, dass die Klasse Cdas Feld nicht angibt name. Es wird tatsächlich mit syntaktischem Zucker public name: stringim Konstruktor deklariert .

Wie Sohnee betont, soll die Schnittstelle tatsächlich alle Implementierungsdetails verbergen. In meinem Beispiel habe ich die Schnittstelle so ausgewählt, dass eine Getter-Methode im Java-Stil erforderlich ist. Sie können jedoch auch eine Eigenschaft festlegen und dann die Klasse entscheiden lassen, wie die Schnittstelle implementiert werden soll.

Valentin
quelle
1
Sie können getund setSchlüsselwörter in TypeScript verwenden.
Fenton
Eine Randnotiz zur Unterstützung von ECMAScript 5 - Object.definePropertywird in IE8 +, FF4 +, Opera 12+, WebKit und Safari unterstützt. Es gibt auch eine EC5 Shim unter github.com/kriskowal/es5-shim
Fenton
-1

Verwenden von 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());

Siehe Beispiel auf TypeScript Playground .

Jack
quelle