Ezward
Ezward

Reputation: 17702

Is it possible to use a readonly property in TypeScript Interfaces?

I would like to define an interface with a readonly property. For instance (as a strawman);

interface foo {
    get bar():bool;
}

However, this gives the syntax error, "expected ';'" on bar. I have setup my VisualStudio to use the ES5 target, so getters are supported. How would I define a readonly property in an interface?

Upvotes: 107

Views: 52266

Answers (3)

chharvey
chharvey

Reputation: 9326

As @Vitaliy Ulantikov answered, you may use the readonly modifier on a property. This acts exactly like a getter.

interface Point {
    readonly x: number;
    readonly y: number;
}

When an object literal implements the interface, you cannot overwrite a readonly property:

let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

But when a class implements the interface, there is no way to avoid overwriting it.

class PointClassBroken implements Point {
    // these are required in order to implement correctly
    x: number;
    y: number;

    constructor(x: number, y: number) {
        this.x = x
        this.y = y
    }

    changeCoordinates(x: number, y: number): void {
        this.x = x // no error!
        this.y = y // no error!
    }
}

I guess that’s because when you re-declare properties in the class definition, they override the properties of the interface, and are no longer readonly.

To fix that, use readonly on the properties directly in the class that implements the interface

class PointClassFixed implements Point {
    readonly x: number;
    readonly y: number;

    constructor(x: number, y: number) {
        this.x = x
        this.y = y
    }

    changeCoordinates(x: number, y: number): void {
        this.x = x // error!
        this.y = y // error!
    }
}

See for yourself in the playground.

Upvotes: 6

Vitaliy Ulantikov
Vitaliy Ulantikov

Reputation: 10514

Getter-only properties were introduced in Typescript 2.0:

interface foo {
    readonly bar: boolean;
}

Upvotes: 133

Valentin
Valentin

Reputation: 8074

Yes, this is a limitation of interfaces. Whether or not the access to the property is implemented with a getter is an implementation detail and thus should not be part of the public interface. See also this question.

If you need a readonly attribute specified in an interface, you can add a getter method:

interface foo {
    getAttribute() : string;
}

Upvotes: 23

Related Questions