typescript 如何在同一个类中键入值作为键(作为“this”对象)和方法的类

uqjltbpv  于 2022-11-26  发布在  TypeScript
关注(0)|答案(1)|浏览(120)

我想把JS模块重写成TS,而不改变它的结构。
我现在拥有的:

class Row {
  // values are like an object { eur: 10 }
  constructor(values) {
    Object.assign(this, values);
  }

  addRow(row) {
    // row + row method
  }
}

const row1 = new Row({ eur: 10 })
const row2 = new Row({ eur: 30 })

console.log(row1) // -> { eur: 10 }
console.log(row1.addRow(row2)) // -> { eur: 40 }

我尝试执行的操作,但出现TS错误

class Row {
  [key: string]: number

  constructor(values: Record<string, number>) {
    // @ts-expect-error "Property 'addRow' of type '(row: Row) => Row' is not assignable to 'string' index type 'number'"
    Object.assign(this, values)
  }

  addRow(row: Row) {
     // return row + row method
  }
}

// Want to use the same way

const row1 = new Row({ eur: 10 })
const row2 = new Row({ eur: 30 })

console.log(row1) // -> { eur: 10 }
console.log(row1.addRow(row2)) // -> { eur: 40 }

如何摆脱这种打字错误?

vnzz0bqm

vnzz0bqm1#

...也许我可以使用regexp来修复某个变量中的所有内容,比如“values”,这样就可以用row.values.eur来访问它...
是的,这就是你可能想要做的重构。
然而,不幸的是,我认为使用TypeScript进行正确的类型输入太松散了。您使用Row示例 * 同时 * 作为键/值对的包 * 和 * 作为方法(addRow)的源代码。如果您抑制addRow上的错误(并稍微调整实现),使用当前版本的TypeScript,它将工作:

class Row {
    [key: string]: number;

    constructor(values: Record<string, number>) {
        for (const key in values) {
            if (key !== "addRow") {
                this[key] = values[key];
            }
        }
    }

    // @ts-expect-error ts 2411 - this is incompatible with an index signature
    addRow(row: Record<string, number>) {
        const result = new Row(this);
        for (const key in row) {
            if (key !== "addRow") {
                result[key] = (result[key] ?? 0) + row[key];
            }
        }
        return result;
    }
}

// Want to use the same way

const row1 = new Row({ eur: 10 });
const row2 = new Row({ eur: 30 });

console.log(row1); // -> { eur: 10 }
console.log(row1.addRow(row2)); // -> { eur: 40 }

Playground链接(这里是一个在构造函数中接受多个参数的版本,就像你最初的问题一样)。

但是,我会犹豫是否使用它,因为我不能说明天的TypeScript不会以不同的方式处理addRows(从类型的Angular 来看),并抱怨addRows调用,因为它决定addRows是一个number而不是一个方法。(也就是说,如果发生了这种情况,那么,您将知道它发生了。)

关于我在那里所做的一些说明:
1.我让构造函数和addRow接受Record<string, number>而不是Row,这样您的对象文字就可以工作了。
1.我删除了Object.assign,并将其替换为我们自己的循环,这样我们就可以跳过addRows属性(如果有)。
1.它有一个不幸的@ts-expect-error(见上面的警告)。
1.如果row有一个属性,但this没有,我使用空合并将该属性添加到record,在这种情况下使用值0

相关问题