Is it possible to use getters/setters in interface definition?

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?

100207 次浏览

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.

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';
}

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.

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.