typescript - 扩展记录的通用参数不推断键类型约束
问题描述
创建 时Record
,keyof
正确确定其键类型。但是当泛型参数扩展 Record 时,不会推断出键类型约束:
export type Dictionary<K extends number | string, V> = Partial<Record<K, V>>;
type MyDict = Dictionary<string, any>;
type Key = keyof MyDict; // Key correctly infered as string;
const myFunc = <D extends MyDict>(dict: D) => {
// keyof D incorrectly infered as string | number | symbol
type OtherDict = Dictionary<keyof D, number>;
};
有没有办法解决这个问题,并应用约束而不必断言每个keyof D
实例的类型?
解决方案
编译器在技术上是正确的,D
可能具有symbol
-valued 键。TypeScript 中的对象类型是开放的/可扩展的,而不是封闭的/精确的。(有关确切类型的功能请求,请参阅microsoft/TypeScript#12936)您可以将属性添加到对象类型并仍然符合该对象类型。这是一个示例,但不太可能:
const s = Symbol("symbol");
interface YourDict extends MyDict {
[s]: number;
}
const d: YourDict = { [s]: 123 };
myFunc(d);
该类型YourDict
绝对是 的扩展MyDict
,并且它具有symbol
-valued 键。并且调用myFunc()
接受 type 的值YourDict
。由于D
可能有任何键,编译器不愿在keyof D
受限于string | number
.
解决此问题的最简单方法是在不尝试分开keyof D
排除symbol
的情况下,只允许symbol
您的键Dictionary
:
export type Dictionary<K extends PropertyKey, V> = Partial<Record<K, V>>;
该类型PropertyKey
是与 同义的内置实用程序类型string | number | symbol
。这清除了错误:
const myFunc = <D extends MyDict>(dict: D) => {
type OtherDict = Dictionary<keyof D, number>; // okay
};
我的猜测是,这可能足以满足您的需求,因为我怀疑您根本不想花很多时间担心symbol
钥匙。如果你有一些重要的原因禁止symbol
或其他键,你可以采取一些步骤,但是 TypeScript 类型系统的开放类型使得这有点棘手,所以我不推荐它。
推荐阅读
- javascript - 如何将本地 json 文件数据导入我的 JavaScript 变量?
- angular - 导入自定义库时出现编译错误
- mysql - 将查询输出连接到 mysql 工作台中的 csv 文件?
- ssh - SSH 无密码:martin@XXX.XXX.XXX.XXX:权限被拒绝(公钥、gssapi-keyex、gssapi-with-mic)
- arrays - Json 列表/数组案例中的 JOLT TRANSFORM
- html - 在服务器上使用应用程序时图像抛出 404 错误
- javascript - html表单在mysql中插入数据的数据提交中断
- javascript - 循环遍历数组并填充矩阵 - JS
- python - 我正在尝试打开扩展名为 .ml 的文件
- jsonpath - jsonpath查找所有键离开包含一个字符串