如何解决在不丢失类型的情况下,对const文字的键进行类型检查
我想要一个引用接口键的常量。 我希望对此常量进行类型检查,以确保键名正确,并且我还希望将它们键入为文字。
如果我执行以下操作:
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的密钥中。
关于如何实现这一目标的任何想法?
例如,我可以添加第二个Dead变量来进行Record检查,并仅使用as const
保留我的第一个变量,而不将其强制转换为Record,但这很冗长,而且不清楚。
谢谢!
解决方法
通常在这种情况下,我会引入一个辅助函数,该函数检查将值分配给某个类型而不将值扩展为该类型。辅助函数的常规版本如下:
const checkType = <T>() => <U extends T>(u: U) => u;
然后要让它检查特定类型,请调用它并手动指定该类型:
const checkKeys = checkType<Record<string,keyof MyInterface>>();
现在,您有了一个仅接受正确类型的值的函数,并且在执行错误操作时会得到预期的错误:
export const MY_KEYS = checkKeys({
CONSTANT_KEY_A: 'keyA',CONSTANT_KEY_B: 'keyB',// CONSTANT_KEY_C: 'keyC',// error! '"keyC"' is not assignable to '"keyA" | "keyB"'.
})
但该函数的输出未根据需要扩展:
MY_KEYS.CONSTANT_KEY_A // "keyA"
请注意,您甚至不需要as const
,因为编译器认为您要将对象文字解释为可分配给Record<string,keyof MyInterface>
,因此不会将文字字符串值扩展为{{1} }。不过,如果string
可以通过其他方式帮助您,则仍然可以使用。
从概念上讲,这与您的“死变量”想法并没有什么不同,当然在运行时as const
是一种编写(() => u => u)()(someValue)
的怪异方法。但是在TypeScript中没有内置的“无需扩展就可以验证可分配性”运算符(例如microsoft/TypeScript#30809?),这通常是我知道该怎么做的最好方法。
好的,希望能有所帮助;祝你好运!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。