Skip to content

SUGGESTIONS: getters/setters in interface #11878

@dungdm93

Description

@dungdm93

In TypeScript, we define abstract property in interface like:

interface I {
    prop: string; // abstract property = getter + setter
}

But there are no way to define only setter.
And currently we can use readonly property to defne abstract getter like:

interface IReadonly {
   readonly foo: string; // abstract getter, not un-reassignable property as expect
}

Even that, I realize that readonly have many drawbacks as:

  1. ambiguous meaning

    When using readonly keyword, most people expect an un-reassignable property (as they are in class). However, in interface it declare an abstract getter.
    In bellow example, some guys implement readonly property as computed property.

    class CComputed implements IReadonly {
        private first: string;
        private second: string;
    
        get foo(): string {   // It that bad?
            return `${this.first} ${this.second}`;
        }
    }
  2. missing implement

    Because interface make no distinction between regular properties and accessor properties. So compiler can't detect errors if child classes don't implement correctly.

    // no foo's getter, but no compile error at all.
    class CReadonly implements IReadonly {
        third: string;
        set foo(value: string) {
            this.third = value;
        }
    }

    Suggestion

I'd like to suggest that abstract getter/setter (accessors) is allowed in interface.

  • Setter
interface ISetter {
    set bar(value: string);
}

//===== Some implementation examples =====
// OK
class CSetter1 implements ISetter { // OK
    public bar: string = "Batman";
}

// OK
class CSetter2 implements ISetter {
    private secret: string = "Superman";
    set foo(value: string) {
        this.secret = value;
    }
}

// Compile error: Implement setter 'bar' is missing.
class CSetter3 implements ISetter {
    public readonly bar: string = "Iron Man";
}

// Compile error: Implement setter 'bar' is missing.
class CSetter4 implements ISetter {
    get bar(): string {
        return "Captain America";
    }
}

let iSetter: ISetter = { bar: "Thor" }; // OK
  • Getter
interface IGetter {
    get foo(): string;
}

//===== Some implementation examples =====
// OK
class CGetter1 implements IGetter {
    public foo: string = "Batman";
}

// Compile error: Implement getter 'foo' is missing.
class CGetter2 implements IGetter {
    private secret: string = "Superman";
    set foo(value: string) { // Error
        this.secret = value;
    }
}

// OK
class CGetter3 implements IGetter {
    get foo(): string {
        return "Captain America";
    }
}

// OK
class CGetter4 implements IGetter {
    public readonly foo: string = "Iron Man";
}

let iGetter: IGetter = { foo: "Thor" }; // OK

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions