Typescript-gränssnittsimplementation har ingen effekt på indexsignatur


För mitt nya lilla projekt bestämde jag mig för att använda TypeScript av en anledning som inte är bättre än att få mig att känna att jag programmerar i C på remarkabla steroider och uppenbarligen betalar jag priset.

Jag har ett gränssnitt, eller hur

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

Vilket tydligen tillåter mig att definiera objekt med strängnycklar och vilka värden som helst. Sedan implementerar jag det

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];
    }
  }
}

Nu får jag detta fel

Element har implicit typen 'any' eftersom typen 'Model' inte har någon indexsignatur

på den här raden

      model[prop] = data[prop];

Men om jag ändrar min modell för att inkludera signaturen

import DataObject from "./data-object";

export default class Model implements DataObject {

  [key: string]: any;

  ...
}

Då finns det inget fel.

Varför har inte gränssnittets signatur någon effekt på min klass?

Svar #1

Jag tror att gränssnitt inte har någon påverkan på implementeringen. Om du ändrar det till en klass och ärver den så fungerar det som förväntat. Det beror på att du kan implementera indexet på ett annat sätt, som egenskaper, se exemplet (i 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
        }
    }
}

Relaterade artiklar