我想有一个常量引用接口的键。我希望对这个常量进行类型检查,以确保键的名称正确,并且我还希望将它们键入为文字。
如果我执行以下操作:
interface MyInterface {
keyA: string;
keyB: string;
}
export const MY_KEYS: Record<string, keyof MyInterface> = {
CONSTANT_KEY_A: 'keyA',
CONSTANT_KEY_B: 'keyB',
} as const;
MY_KEYS.CONSTANT_KEY_A
那么MY_KEYS.CONSTANT_KEY_A
的类型是'keyA' | 'keyB'
。但我希望它是'keyA'
!
如果我删除Record<string, keyof MyInterface>
,那么它就可以工作,但是我的键不再被类型检查为MyInterface的键。
你知道我该怎么做吗
例如,我可以添加第二个死变量来执行Record检查,并只使用as const
保留第一个变量,而不将其转换为Record,但这非常冗长,而且不太清楚。
谢谢你!
2条答案
按热度按时间qij5mzcb1#
通常在这种情况下,我会引入一个助手函数,它检查一个值是否可以分配给一个类型,而不会将该值扩展到该类型。helper函数的一般版本如下所示:
然后让它检查你调用的特定类型,并手动指定该类型:
现在你有了一个函数,它只接受正确类型的值,当你做错了什么时,它会给予你预期的错误:
但函数的输出不按需要加宽:
请注意,您甚至不需要
as const
,因为编译器认为您希望将对象文字解释为可分配给Record<string, keyof MyInterface>
,因此不会将文字字符串值扩展为string
。不过,如果as const
在其他方面有帮助,您仍然可以使用它。从概念上讲,这与您的“死变量”想法没有什么不同,当然在运行时,
(() => u => u)()(someValue)
是编写someValue
的一种奇怪方式。但是在TypeScript中没有内置的“验证可分配性而不扩大”操作符(比如microsoft/TypeScript#30809?),这是我所知道的一般情况下最好的方法。好吧,希望能帮上忙;祝你好运!
Playground链接到代码
klr1opcd2#
对于使用typescript 4.9.5或更高版本的用户,只需使用
satisfies
(链接):