首页 > 解决方案 > 带有 toString() 的类可以用作字符串,但是如何说服 TypeScript 编译器呢?

问题描述

我的类实现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'};

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

标签: typescripttype-safetytype-coercion

解决方案


你不能

您不能“说服”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


推荐阅读