[英]How to extend the Record type's keys in typescript
这是打字稿中的预期行为吗?
const NeedsRecord = <T extends Record<string, any>>(record: T) => {}
NeedsRecord({
5: "🚨 Should error, doesn't 🚨"
});
我想通过继承来限制Record
键类型的类型。 我怎样才能做到这一点?
将键类型作为泛型参数也不能按预期工作:
const NeedsRecord = <T extends string>(record: Record<T, any>) => { }
NeedsRecord({
5: "🚨 Should error, doesn't 🚨"
});
显式定义联合键类型有效,但使用起来很难看:
const NeedsRecord = <T extends string>(record: Record<T, any>) => { }
NeedsRecord<"a"|"b">({
a: "works",
b: "works",
// 5: "🚨 fails properly"
// c: "🚨 fails properly"
});
这是预期的 TypeScript 行为。 “数字”对象键实际上是字符串,因此,TypeScript 将字符串索引签名视为支持数字甚至符号键。
如果要强制编译器在传递number
值键时产生错误,可以这样做:
const needsRecord = <T extends { [K in keyof T]: K extends number ? never : any }>(
record: T
) => { }
needsRecord({
a: "works",
b: "works",
5: "error" // string is not assignable to never
});
但要注意......在 JavaScript 中, {5: ""}
和{"5": ""}
之间真的没有区别,因为键被强制转换为字符串:
const oN = { 5: "" };
console.log(typeof (Object.keys(oN)[0])); // "string"
const oS = { "5": "" };
console.log(JSON.stringify(oS) === JSON.stringify(oN)); // true
这意味着上面的needsRecord()
会认为这很好:
needsRecord({
a: "works",
b: "works",
"5": "oops" // no error
})
但是没有充分的理由允许一个而不允许另一个。 而且 TypeScript 目前没有很好的内置方法来排除“类似数字的字符串”,所以我不确定您可以在这里做更多的事情。
鉴于5
和"5"
作为键是相同的,你为什么真正关心禁止这个? 对于您的用例,TypeScript 的预期行为是否可能实际上是可以接受的? 或者,如果您允许使用数字键,真的会出错吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.