Typescript: Support getter setters in interfaces

Created on 5 Jul 2015  路  11Comments  路  Source: microsoft/TypeScript

Classes support getters / setters

class MyClass {
  get value(): string { return 'value'; }
  set value(v: string): string {}
}

but the corresponding interface is not supported:

interface MyInterface {
  get value(): string;
  set value(v: string): string;
}
By Design Canonical Duplicate

Most helpful comment

Sorry for not being more clear. How do I create an interface which only has getters (no setters). Please reopen.

interface IName {
  get name():string; // SYNTAX ERROR
}

class User implements IName {
  name: string; // SHOULD WORK
}

class User2 implements IName {
  get name() { return value; } // ALSO SHOULD WORK
}

class User2 implements IName {
  set name(value) { } // SHOULD FAIL
}

All 11 comments

You simply declare it as a property.

interface MyInterface {
  value: string;
}

Whether a property is implemented as a field or a getter/setter pair is an implementation detail, not part of the type.

Sorry for not being more clear. How do I create an interface which only has getters (no setters). Please reopen.

interface IName {
  get name():string; // SYNTAX ERROR
}

class User implements IName {
  name: string; // SHOULD WORK
}

class User2 implements IName {
  get name() { return value; } // ALSO SHOULD WORK
}

class User2 implements IName {
  set name(value) { } // SHOULD FAIL
}

We've had an outstanding feature request for read-only: https://github.com/Microsoft/TypeScript/issues/12 You might want to pile on there, also.

Now that we have abstract, I think this problem is solved:

abstract class HasReadonlyProp {
  abstract get foo(): number;
}
class HasReadonlyPropImpl extends HasReadonlyProp {
  get foo(): number { return 1; }
}
function ClientCode() {
  let h = new HasReadonlyProp();
  console.log(h.foo); //=> 1
  h.foo = 2; //=> typechecking error 
}

abstract is a part of single class inheritance, this does not solve the problem when you want an interface definition added to an existing class hierarchy.

This is really solved now fully with readonly which signifies and interface where there is only a getter (or an interface where you logically want to disallow assignment at design time).

interface IName {
  readonly name(): string; // not a syntax error
}

@kitsonk yes, but only without parenthesizes:

interface IName {
  readonly name:: string; // not a syntax error
}

This feature would be useful for TypeScript Java interop declarations. I'm compiling TS into JS for use with Java's Nashorn scripting engine, and have been declaring the Java classes/interfaces in TS for better type safety and code completion.

Java does not natively support properties. However, Nashorn will pass-through property usage to an object's appropriately named getter and setter.

All this is to say, copying Java declarations into TypeScript would be significantly easier and with less work, because the Java interface already has a getter and setter method, with full documentation. Converting this to the other property syntax is cumbersome.

I totally realize it's a weird edge case and probably shouldn't influence TypeScript's development, but the lack of this syntax does seem a little inconsistent.

That's kind of ironic since Java still doesn't have properties. It sounds like your use case would be best addressed by code generation.

I'm writing a container that updates the address field of its elements. The elements can currently be any object.
I want to be able to declare the type of the elements as one that may or may not have a value under address, but supports setting the address field to string values. This will improve the readability of the container's API greatly, as it does not intend to read the address of the elements, but rather update it to some string values over time.

an interface with a property setter would be a nice fit IMO:

interface Element {
  set address(a:string):void;
}

I wish we could just type:

interface ISome {
 field: string;
}
class C implements ISome {
 public get field() { return _field; }
 public set field(v: string) { // MY STUFF; _field = field; }
}

and it should works in TS, maybe with some warnings about missing overrides keyword :)

IMHO.....IMHO.....IMHO.....IMHO.....IMHO.....IMHO.....IMHO.....IMHO.....

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kyasbal-1994 picture kyasbal-1994  路  3Comments

manekinekko picture manekinekko  路  3Comments

CyrusNajmabadi picture CyrusNajmabadi  路  3Comments

blendsdk picture blendsdk  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments