132

At the moment, TypeScript does not allow use get/set methods(accessors) in interfaces. For example:

interface I {
      get name():string;
}

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

furthermore, TypeScript does not allow use Array Function Expression in class methods: for ex.:

class C {
    private _name:string;

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

Is there any other way I can use a getter and setter on an interface definition?

Dave Hillier
  • 18,105
  • 9
  • 43
  • 87
Ivan Popov
  • 1,331
  • 2
  • 8
  • 5

4 Answers4

153

You can specify the property on the interface, but you can't enforce whether getters and setters are used, like this:

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 this example, the interface doesn't force the class to use getters and setters, I could have used a property instead (example below) - but the interface is supposed to hide these implementation details anyway as it is a promise to the calling code about what it can call.

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

And lastly, => is not allowed for class methods - you could start a discussion on Codeplex if you think there is a burning use case for it. Here is an example:

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

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

    // No
    get name() => 'Steve';
}
Fenton
  • 241,084
  • 71
  • 387
  • 401
  • 1
    You can use `=>` for defining class methods like this: `name = (a: string) => this._name;` but in the output JS it will be defined inside the class function rather than extending its prototype object. – orad Aug 18 '13 at 02:09
  • 1
    this doesn't seem to work with static get properties :/ – CervEd Sep 22 '20 at 15:33
67

To supplement the other answers, if your desire is to define a get value on an interface, you can use readonly:

interface Foo {
  readonly value: number;
}

let foo: Foo = { value: 10 };

foo.value = 20; //error

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

but as far as I'm aware, and as others mentioned, there is no way currently to define a set-only property in the interface. You can, however, move the limitation to a run-time error (useful during the development cycle only):

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

Not recommended practice; but an option.

Meirion Hughes
  • 24,994
  • 12
  • 71
  • 122
  • This does feel like the correct answer until `get` and `set` can be declared normally on interfaces. – Ash Blue Jun 03 '22 at 17:53
3

First of all, Typescript only supports get and set syntax when targetting Ecmascript 5. To achieve this, you have to call the compiler with

tsc --target ES5

Interfaces do not support getters and setters. To get your code to compile you would have to change it to

interface I { 
    getName():string;
}

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

What typescript does support is a special syntax for fields in constructors. In your case, you could have

interface I {
    getName():string;
}

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

Notice how class C does not specify the field name. It is actually declared using syntactic sugar public name: string in the constructor.

As Sohnee points out, the interface is actually supposed to hide any implementation details. In my example, I have chosen the interface to require a java-style getter method. However, you can also a property and then let the class decide how to implement the interface.

Valentin
  • 7,874
  • 5
  • 33
  • 38
  • 1
    You can use `get` and `set` keywords in TypeScript. – Fenton Oct 11 '12 at 12:07
  • A side note on ECMAScript 5 support - `Object.defineProperty` is supported in IE8+, FF4+, Opera 12+, WebKit and Safari. There is also an EC5 Shim at https://github.com/kriskowal/es5-shim – Fenton Oct 11 '12 at 12:18
0

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

See example on TypeScript Playground.

Jack
  • 1,881
  • 24
  • 29