我有一个MyObject
类型的对象,它有两个字符串属性。
interface MyObject {
a: number,
b: string,
}
const myObject = {
a: 5,
b: 'str'
}
然后我有一个接受字符串的函数,并且我希望能够访问由string参数指定的上述对象的属性。我想做的是在访问属性之前,使用类型防护来检查字符串是否是对象的键。必须进行某种检查,因为该参数只是一个字符串,并且该对象没有索引签名。
如果我创建一个特定版本来检查这种特定类型的对象(MyObject),那么它将起作用:
// specific version
const isValidPropertyForMyObject = (property: string): property is keyof MyObject => Object.keys(myObject).indexOf(property) !== -1
const getProperty1 = (property: string) => {
if (isValidPropertyForMyObject(property)) {
myObject[property]
}
}
但是,如果我希望能够传入具有泛型类型和字符串参数的对象,并检查该属性是否实际上是该对象的键,该怎么办?这是我的尝试:
const isValidMethodForHandler = <T extends { [i: string]: any }>(handler: T) => (
method: string
): method is keyof T => Object.keys(handler).indexOf(method) !== -1;
const getProperty = (property: string) => {
// const acceptedProperties = ["a", "b"];
// if (acceptedProperties.indexOf(property) !== -1) {
// myObject[property]
// }
if (isValidMethodForHandler(myObject)(property)) {
myObject[property]
}
}
问题出在类型防护中:
类型谓词的类型必须可分配给其参数的类型。 类型“ keyof T”不可分配给类型“ string”。 输入'string |编号符号”不能分配给“字符串”类型。 无法将“数字”类型分配给“字符串”类型。(2677)
答案 0 :(得分:0)
您当然可以写:
interface MyObject {
a: number,
b: string,
}
const myObject = {
a: 5,
b: 'str'
}
const isValidPropertyForMyObject = (property: string): property is keyof MyObject =>
property in myObject;
然后您可以执行以下操作:
const f = <K extends keyof MyObject>(obj: MyObject, k: K): MyObject[K] => obj[k];
const g = <K extends keyof MyObject>(obj: MyObject, k: string | K): MyObject[K] | string =>
isValidPropertyForMyObject(k) ? f(obj, k) : "NOT LEGAL";
假定存在一个常量myObject
,该常量在运行时列出了MyObject
的所有键。
答案 1 :(得分:0)
答案基于TypeScript问题跟踪程序here中的该线程。
上述问题中特定TypeScript错误的解释在this other question
中我的示例代码的解决方案是:
const isValidMethodForHandler = <T extends { [i: string]: any }>(handler: T) => (
method: string
): method is Extract<keyof T, string> => Object.keys(handler).indexOf(method) !== -1;
const getProperty = (property: string) => {
if (isValidMethodForHandler(myObject)(property)) {
myObject[property]
}
keyof
返回所有已知键,并且这些键均为string | number | symbol
类型。
要仅获取字符串属性,请使用Extract
。