带有toString()的类可以用作字符串,但是如何说服TypeScript编译器呢?

new9mtju  于 2023-01-06  发布在  TypeScript
关注(0)|答案(1)|浏览(98)

我的类实现了toString(),以便在构建其他对象时可以方便地使用任何示例作为属性名,但TypeScript编译器并不信服,并输出:a computed property name must be of type 'string'如何以满足编译器要求的方式声明类?

class Foo {
  name: string  
  constructor(name: string) { this.name = name; }
  toString() { return this.name; }
}

其可以如下使用:

const myFoo = new Foo('Clytemnestra');
const someObject = { [myFoo]: 'she murders Agamemnon'};

目前,上面的最后一行会产生前面提到的类型错误。

jc3wubiy

jc3wubiy1#

你不能

您不能“说服”Typescript静态类型检查器忽略对象的类型而依赖于强制类型--这将使静态类型检查的整个目的落空。
但你可以...
0通过更改有问题的行来覆盖静态确定的类型:

const someObject = { [myFoo as unknown as string ]: 'she murders Agamemnon'};

一闻就臭。
好吧,不如这样:

const someObject = { [ myFoo.toString() ]: 'she murders Agamemnon'};

这稍微好一点,因为您显式地对字符串执行“强制”操作。
但这两种方法最终都不是好主意。任何对象都可以被强制为字符串,默认值通常是“[object Object]"。依赖toString()方法会破坏类型安全性。因此,您再次违背了静态类型检查的目的。您必须问:我为什么要使用 typescript ?

相反,一种类型安全性更高的方法

class Subject {
  name: string
  city: string
  constructor(name: string, city: string) { 
    this.name = name
    this.city = city
  }
}

const vengefulWife = new Subject('Clytemnestra', 'Mycenae');

const summaries = new Map<Subject, string>()
summaries.set(vengefulWife, 'she murders Agamemnon')

for (const [key, value] of summaries) {
  console.log(`${key.name} of ${key.city}: ${value}`);
}

因为Typescript知道key的类型,所以它将对key.namekey.city的引用识别为有效

相关问题