如何解决如何创建允许按任何字符串查询的类型安全对象
我想创建一个对象 + getter 函数,它将返回已知值类型(如果键为 extends keyof typeof obj
)或值类型或 undefined 如果我们不知道键是否在对象与否。有点像这样:
const obj = {
a: 1,b: 2,c: 3
}
const a = obj.a
// typeof a = number
const b = obj['b']
// typeof b = number
let key: string = 'anything'
const d = obj[key]
// typeof d = number | undefined
if (d) {
// typeof d = number
} else {
// typeof d = undefined
}
实际发生的事情是
let key: string = 'anything'
const d = obj[key]
// TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ a: number; b: number; c: number; }'. No index signature with a parameter of type 'string' was found on type '{ a: number; b: number; c: number; }'.
I've been trying to create a `get` function which would work this way,but can't get it to work. The result type is always either `any` or `unknown`.
解决方法
我做对了吗?
const obj: Record<string,any> = { ... };
const getter = (key: string): string => {
if (key in obj) return typeof obj[key];
return undefined;
}
,
在我看来,TypeScript 对这种东西有点不满意。但是,我认为通常的做法是编写类型保护。有点像下面的东西。 isObjKey 显式检查包含键 (obj[key] !== undefined
) 的实际 JavaScript 对象,并在函数返回 true 时告诉 TypeScript 类型 (key is keyof typeof obj
)。现在,如果我们使用它进行测试,TypeScript 知道当您执行 obj[key] 时,它在“if”的第一个分支中有一个数字,我认为这就是您所要求的。令人不满意的地方在于,我们不得不编写一个新的、困难的函数来做一些琐碎的事情,而且我们已经检索了 obj[key] 两次,只是为了获得常量对象的类型安全性。
const obj = {
a: 1,b: 2,c: 3
};
let key: string = Math.random() < 0.5 ? 'a' : 'anything';
function isObjKey(key: string): key is keyof typeof obj {
return obj.hasOwnProperty(key);
}
if (isObjKey(key)) {
const d = obj[key];
// d is a number here as far as TypeScript is concerned
console.log(d);
}
else {
// key isn't a valid key of obj,there's no need for another obj[key] access
// (but if you do it's type any,not undefined)
console.log('undefined');
}
另一种方法是破解它。你向 TypeScript 断言你的键肯定是 obj 的键,即使它可能不是,并且 TypeScript 认为它在 obj[key] 之后有一个数字:
const d = obj[key as keyof typeof obj];
if (d) {
// TypeScript thinks d is a number
console.log(d);
} else {
// TypeScript still thinks d is a number,but it probably doesn't matter!
console.log('undefined');
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。