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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions