我可以使用包含变量作为对象键的模板文字吗?

时间:2019-07-15 19:18:51

标签: typescript template-literals

我希望以下代码能正常工作,但我不确定为什么它不起作用:

interface Person {
  firstName: string
}

const property: 'Name' = 'Name'

const zack: Person = {
  [`first${property}`]: 'Zack'
}

创建zack会引发错误:

Property 'firstName' is missing in type '{ [x: string]: string; }' but required in type 'Person'.

更多地使用它,任何字符串连接似乎都是问题所在:

type EqualsFirstName = 'firstName'

const value: EqualsFirstName = 'first' + 'Name'

那也不行。

2 个答案:

答案 0 :(得分:1)

TypeScript编译器在评估映射类型时非常严格。有很多事情不能很好地与它们配合使用,这就是其中之一。当您声明类型时,它可以工作:

const zack: Person = {
    [`first${property}` as 'firstName']: 'Zack'
}

这并不是真正有用的,但是如下面的代码所示,它也可以很好地编译,但是在运行时却失败了:

const property: 'Foo' = 'Foo'

const zack: Person = {
  [`first${property}` as 'firstName']: 'Zack'
}

另一个(有点笨拙)的选项是用Person声明类型as(并首先通过断言到unknown):

const zack = {
  [`first${property}`]: 'Zack'
} as unknown as Person

就像第一个选项一样,如果断言无效,这将在运行时对您没有帮助。

我建议您尝试在没有此标记的情况下尝试并选择一种更“ TS编译器友好”的方式。这是一个非常不寻常的构造,从技术上讲是有效的,但是您宁愿在实践中避免使用。

答案 1 :(得分:0)

此黑客可能会解决

interface Person {
  firstName: string
}

const property: 'Name' = 'Name'
type EqualsFirstName = 'firstName'

const zack: Person = {
  [`first${property}` as EqualsFirstName]: 'Zack'
}