Можно ли использовать геттеры / сеттеры в определении интерфейса?

93

На данный момент TypeScriptне позволяет использовать методы get / set (аксессоры) в интерфейсах. Например:

interface I {
      get name():string;
}

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

кроме того, TypeScript не позволяет использовать выражение функции массива в методах класса: например:

class C {
    private _name:string;

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

Есть ли другой способ использовать геттер и сеттер в определении интерфейса?

Иван Попов
источник

Ответы:

126

Вы можете указать свойство в интерфейсе, но не можете указать, используются ли геттеры и сеттеры, например:

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

В этом примере интерфейс не заставляет класс использовать геттеры и сеттеры, вместо этого я мог бы использовать свойство (пример ниже), но интерфейс должен все равно скрывать эти детали реализации, поскольку это обещание вызывающему коду о том, что это может назвать.

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

И, наконец, =>это запрещено для методов класса - вы можете начать обсуждение Codeplex, если считаете, что для него существует актуальный вариант использования. Вот пример:

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

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

    // No
    get name() => 'Steve';
}
Фентон
источник
1
Вы можете использовать =>такие методы для определения класса: name = (a: string) => this._name;но в выходном JS он будет определяться внутри функции класса, а не расширять его объект-прототип.
orad
похоже, это не работает со статическими свойствами get: /
CervEd
46

В дополнение к другим ответам, если вы хотите определить a get valueв интерфейсе, вы можете использовать readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

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

но, насколько мне известно, и, как упоминалось другими, в настоящее время нет способа определить свойство только для набора в интерфейсе. Однако вы можете переместить ограничение на ошибку времени выполнения (полезно только во время цикла разработки):

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

Не рекомендуемая практика ; но вариант.

Мейрион Хьюз
источник
2

Прежде всего, Машинопись только поддерживает getи setсинтаксис , когда ориентируется ECMAScript 5. Для достижения этой цели, вы должны вызвать компилятор с

tsc --target ES5

Интерфейсы не поддерживают геттеры и сеттеры. Чтобы ваш код скомпилировался, вам нужно будет изменить его на

interface I { 
    getName():string;
}

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

Машинопись поддерживает специальный синтаксис для полей в конструкторах. В вашем случае вы могли бы

interface I {
    getName():string;
}

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

Обратите внимание, как класс Cне указывает поле name. Фактически он объявляется с помощью синтаксического сахара public name: stringв конструкторе.

Как указывает Сохни, интерфейс должен скрывать любые детали реализации. В моем примере я выбрал интерфейс, требующий метода получения в стиле Java. Однако вы также можете задать свойство, а затем позволить классу решать, как реализовать интерфейс.

Валентин
источник
1
Вы можете использовать getи setключевые слова в машинописи.
Fenton
Замечание о поддержке ECMAScript 5 - Object.definePropertyподдерживается в IE8 +, FF4 +, Opera 12+, WebKit и Safari. Также на github.com/kriskowal/es5-shim
Fenton
-1

Использование 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());

См. Пример на TypeScript Playground .

Джек
источник