typescript - 使用动态键访问具有不同值类型的对象时,是否可以缩小对象值类型?
问题描述
最小测试用例如下(TS游乐场链接)
interface TestObject {
a: string
b: number
}
type TestKeyType = keyof TestObject
const myObjct = {a: "cat", b:34} as TestObject;
const key = 'a' as TestKeyType;
if (typeof myObjct[key] !== 'string') {
throw TypeError();
}
// Error: Type 'string' is not assignable to type 'never'.
myObjct[key] = 'dog';
本质上,我有一个配置对象,其中的值可以是各种类型。当我更新这个对象时,键取决于用户输入,但根据输入的类别,我可以知道它是布尔值还是数字或字符串等。
如图所示,我可以编写一个类型保护,它应该保证动态键对应的类型,但 Typescript 不同意。
我还能做些什么简洁的事情来向 Typescript 证明我的类型是有效的?
我知道我可以枚举对应于每个值类型的键来检查,但这似乎有点冗长和多余;在扩展对象中的键时,我希望尽量减少需要更新的地方。
解决方案
你可以为此编写一个用户定义的类型保护:typeCheck(obj, key, type)
会告诉你是否obj[key]
有 type type
。皱纹是type
必须作为可以在运行时返回的字符串传递typeof
,因此您需要从这些字符串到 Typescript 类型的映射;此映射在Primitive
下面命名。必要时将您需要的任何其他内容添加到此映射中(例如bigint
)。
type Primitive = {
number: number,
string: string,
boolean: boolean,
}
type KeyAssignableTo<T, V> = {[K in keyof T]: T[K] extends V ? K : never}[keyof T]
function typeCheck<T, P extends keyof Primitive>(obj: T, key: keyof T, type: P): key is KeyAssignableTo<T, Primitive[P]> {
return typeof obj[key] === type;
}
用法:
if(!typeCheck(myObject, key, 'string')) {
throw TypeError();
}
// key: 'a'
myObject[key] = 'dog';
推荐阅读
- java - 正则表达式以适合所有不以已知后缀列表(不是字符,而是单词)结尾的字符串
- hashicorp-vault - 如何读取具有访问器的令牌值
- azure - jupyterhub 新用户的默认示例文件和文件夹太多
- python - 如何在外面使用 Django ORM 而不会出现问题?
- python - 无法连接到 MySQL 服务器,无法连接,因为 tared 机器主动拒绝它
- hadoop - HDFS Namenode 高可用性
- sql - 删除mysql中的最后n行
- feathersjs - 我如何使它成为一个异步钩子?
- bash - 带有标签的谷歌浏览器打开网址
- mysql - 如何获得返回地图的正确简单 Spring 数据 JPA 查询?