【发布时间】:2020-04-21 15:24:49
【问题描述】:
我有一个嵌套对象,我想为它写一个类型定义。这是对象:
const colors = {
grayscale: {
black: '#141414',
darkGray: '#303030',
white: '#F0F0F0',
},
green1: '#1DB954',
green2: '#1ED760',
}
这是我尝试编写类型定义的方式:
interface ObjectOf<V> {
[_: string]: V
}
type ColorObject = ObjectOf<string> | string
type Colors = ObjectOf<ColorObject>
const colors: Colors = {
... (same object as above)
}
我使用ObjectOf<V> 来创建一个对象,该对象可以具有任何字符串键,但只能具有V 类型的值。这似乎适用于未嵌套的对象。
当我尝试像这样使用这个对象时:colors.grayscale.black,打字稿编译器给了我这个错误:
Property 'black' does not exist on type 'ColorObject'.
Property 'black' does not exist on type 'string'. TS2339
> 82 | backgroundColor: colors.grayscale.black,
| ^
似乎打字稿忽略了ColorObject 可以是ObjectOf<> 的事实,这意味着任何字符串都应该是有效的键。相反,它认为它只能是一个字符串,因此获取grayscale 对象的black 键失败。为什么会这样,和/或如何修复类型定义以便可以按原样使用颜色对象?
【问题讨论】:
-
不能忽略它可以是
ObjectOf<string>。它担心它可能是string,在这种情况下它不会有一个名为black的属性。您只能访问存在于联合的所有成员中的联合的属性。或者你必须通过测试消除工会成员,例如if (typeof colors.grayscale === "string") throw new Error();,然后访问colors.grayscale.black。为什么将colors注释为Colors?这是一个相当广泛的类型,故意忘记了colors的结构。你的用例是什么? -
我明白了,这是有道理的。我的用例是在 React 组件中使用颜色对象和另一个类似的对象作为样式。当我对只能接受某些字符串(如 flexDirection)的属性使用“row”之类的字符串时,Typescript 给了我错误,即使“row”是这些有效值之一。我想我会指定所有这些对象的类型以避免这种情况,但我想这不是最好的解决方案。
-
我摆脱了颜色的类型定义,我可能会就我遇到的实际问题发布一个不同的问题(现在我正在使用类型转换来安抚编译器,但如果那是最佳解决方案)。感谢您的指导!
-
下面的呢:
ts const colors = { grayscale: { black: '#141414', darkGray: '#303030', white: '#F0F0F0', }, green1: '#1DB954', green2: '#1ED760', } as const type Colors = typeof colors我倾向于在有一些具体结构的地方使用它,并且我想从中建立一个强大的合同。我只能导出应用程序的类型和事实来源将是colors对象。当您在其中添加删除内容时,类型会自动更新。缺点很少,但我相信仍然有用。 -
@rusev 谢谢,这正是我所需要的!您想将此作为答案提交以便我接受吗?如果没有,我会将其作为我自己的答案发布,以便其他人可以看到。
标签: typescript