Czy jest możliwe użycie getters / setters w definicji interfejsu?

93

W tej chwili TypeScriptnie pozwala na używanie metod get / set (akcesorów) w interfejsach. Na przykład:

interface I {
      get name():string;
}

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

ponadto, TypeScript nie zezwala na użycie wyrażenia funkcji Array w metodach klas: na przykład:

class C {
    private _name:string;

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

Czy istnieje inny sposób używania metody pobierającej i ustawiającej w definicji interfejsu?

Iwana Popowa
źródło

Odpowiedzi:

126

Możesz określić właściwość w interfejsie, ale nie możesz wymusić, czy używane są metody pobierające i ustawiające, na przykład:

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

W tym przykładzie interfejs nie wymusza na klasie używania metod pobierających i ustawiających, zamiast tego mógłbym użyć właściwości (przykład poniżej) - ale interfejs powinien i tak ukryć te szczegóły implementacji, ponieważ jest to obietnica dla kodu wywołującego o tym, jak to może nazwać.

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

I na koniec, =>nie jest to dozwolone dla metod klasowych - możesz rozpocząć dyskusję na temat Codeplex, jeśli uważasz, że istnieje dla niego nagły przypadek użycia. Oto przykład:

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

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

    // No
    get name() => 'Steve';
}
Fenton
źródło
1
Możesz użyć =>do zdefiniowania metod klas, takich jak ta: name = (a: string) => this._name;ale w wyjściowym JS zostanie on zdefiniowany wewnątrz funkcji klasy, zamiast rozszerzać jej obiekt prototypowy.
orad
to nie działa ze statycznymi właściwościami get: /
CervEd
46

Aby uzupełnić inne odpowiedzi, jeśli chcesz zdefiniować get valueinterfejs, możesz użyć readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

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

ale o ile mi wiadomo i jak wspominali inni, obecnie nie ma możliwości zdefiniowania właściwości tylko zestawu w interfejsie. Możesz jednak przenieść to ograniczenie na błąd czasu wykonywania (przydatne tylko podczas cyklu rozwoju):

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

Niezalecana praktyka ; ale opcja.

Meirion Hughes
źródło
2

Po pierwsze, Typescript obsługuje składnię geti obsługuje tylko setEcmascript 5. Aby to osiągnąć, musisz wywołać kompilator z

tsc --target ES5

Interfejsy nie obsługują metod pobierających i ustawiających. Aby kod mógł się skompilować, musisz go zmienić na

interface I { 
    getName():string;
}

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

Obsługiwany przez maszynopis to specjalna składnia pól w konstruktorach. W twoim przypadku mogłeś

interface I {
    getName():string;
}

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

Zwróć uwagę, że klasa Cnie określa pola name. W rzeczywistości jest deklarowany przy użyciu cukru syntaktycznegopublic name: string w konstruktorze.

Jak podkreśla Sohnee, interfejs ma właściwie ukrywać wszelkie szczegóły implementacji. W moim przykładzie wybrałem interfejs tak, aby wymagał metody pobierania w stylu Java. Możesz jednak również utworzyć właściwość, a następnie pozwolić klasie zdecydować, jak zaimplementować interfejs.

Valentin
źródło
1
Możesz używać geti setsłów kluczowych w TypeScript.
Fenton,
Dodatkowa uwaga na temat obsługi ECMAScript 5 - Object.definePropertyjest obsługiwana w IE8 +, FF4 +, Opera 12+, WebKit i Safari. Istnieje również podkładka EC5
Fenton
-1

Korzystanie z języka 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());

Zobacz przykład na TypeScript Playground .

Jacek
źródło