4

For my new small project I decided to go with typescript for a reason no better than making myself feel like programming c on remarkable steroids and apparently I'm paying the price.

I have an interface, right

export default interface DataObject {
  [key: string]: any
};

Which is supposedly allowing me to define objects with string keys and whatever values. Then I'm implementing it

import DataObject from "./data-object";

export default class Model implements DataObject {

  constructor(data: DataObject = {}) {
    Model.fill(this, data);
  }

  static fill(model: Model, data: DataObject) {
    for (let prop in data) {
      model[prop] = data[prop];
    }
  }
}

Now I'm getting this error

Element implicitly has 'any' type because type 'Model' has no index signature

on this line

      model[prop] = data[prop];

But if I modify my model to include the signature

import DataObject from "./data-object";

export default class Model implements DataObject {

  [key: string]: any;

  ...
}

Then there is no error.

Why is the interface signature not having effect on my class?

0

1 Answer 1

2

I think interfaces don't have influence to the implementation. If you change it to a class and extends it than it works as expected. That’s because you can the index implement in another way, like properties, see the example (in the Playground).

interface DataObject {
    foo: any;
    bar: any;
    [key: string]: any;
};

class Model implements DataObject {

    private _bar: string = null;
    public get bar(): string {
        return this._bar;
    }
    public set bar(value: string) {
        this._bar = value;
    }

    constructor(data: DataObject = {}) {
        this.foo = "bar"; // error
        this.bar = "foo"; // no error
        Model.fill(this, data);
    }

    static fill(model: Model, data: DataObject) {
        for (let prop in data) {
            model[prop] = data[prop]; // error
        }
    }
}

class DataObject2 {
    foo: any;
    bar: any;
    [key: string]: any;
};

class Model2 extends DataObject2 {

    constructor(data: DataObject2 = { foo: "", bar: "" }) {
        super();
        this.foo = "bar"; // no error
        this.bar = "foo"; // no error
        Model2.fill(this, data);
    }

    static fill(model: Model2, data: DataObject2) {
        for (let prop in data) {
            model[prop] = data[prop]; // no error
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

But how is this making sense? Interfaces are not supposed to be able to define properties in the first place, but since they do, why are the classes not inheriting the signature? There is no value?
They don't define. They just say "there has to be a property if you implement me". Only the syntax looks the same. In TypeScript you can "implements" or "extends" something. Classes can be "extends" and interfaces (and classes) can be "implements".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.