【发布时间】:2020-03-18 00:25:21
【问题描述】:
我有一个MyObject 类型的对象,它有两个字符串属性。
interface MyObject {
a: number,
b: string,
}
const myObject = {
a: 5,
b: 'str'
}
然后我有一个接受字符串的函数,我希望能够访问由字符串参数指定的上述对象的属性。我想要做的是在访问属性之前使用类型保护来检查字符串是否是对象的键。有必要在这里做一些检查,因为参数只是一个字符串,对象没有索引签名。
如果我制作一个特定版本来检查这种特定类型的对象(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”不可分配给类型“字符串”。 键入'字符串 |号码 |符号'不可分配给类型'字符串'。 类型“数字”不可分配给类型“字符串”。(2677)
【问题讨论】:
-
这里有什么特别需要用户定义的类型保护的理由吗?使用
in操作符就更简单了:if (key in obj) { return obj[key] } -
@wrsx 我不认为该解决方案有效,我只是在 TS Playground 中尝试过,如下: const getProperty3 = (property: string) => { if (property in myObject) { myObject[属性] } }
-
没有索引签名是不可能的,但是您可以在示例中使用通用的索引签名:
getProperty<T extends { [i: string]: any }>(property: string, obj: T) -
我看不出有什么区别:codesandbox.io/s/vigilant-hoover-b3v4h
-
@wrsx 不同的是我需要一个类型保护。换句话说,我希望能够优化传入参数的类型。您的解决方案只是从对象中获取属性,如果属性不在对象中,则返回 undefined。这是没有意义的,可以直接在调用代码中使用简单的 obj[property] 来完成。
标签: typescript