我有一个从对象获取属性的函数 .
// Utils.ts
export function getProperty<T, K extends keyof T>(obj: T, key: string): T[K] {
if (key in obj) { return obj[key as K]; }
throw new Error(`Invalid object member "${key}"`);
}
我想检查返回的属性是否是具有给定签名的函数,然后使用提供的参数调用该属性 .
getProperty()
用于动态获取对象的方法之一并调用它 . 我试过了:
let property: this[keyof this] = utils.getProperty(this, name);
if (typeof property === 'function') ) { property(conf); }
但这会给出"Cannot invoke an expression whose type lacks a call signature. Type 'any' has no compatible call signatures."错误 . 我知道来自 getProperty()
的属性确实可以是任何类型,但如何确定它是 (conf: {}): void
签名的函数?
2 回答
对于函数类型,它看起来不像typeof type guards . 它似乎是by design(那个问题是关于
instanceof
类型的守卫,但我也是类似的推理) .但是,TypeScript确实有user-defined type guards,这意味着您可以编写一个函数,以任何方式缩小其参数的类型 . 那么,什么运行时测试将确定某个值
x
是否为(conf: {}) => void
类型的函数?当然,您可以测试是否typeof x === "function"
. 这并不表示该函数将采用任何特定类型的参数而不返回任何内容 . 也许您只知道从getProperty
中提取的任何函数都是正确的类型 . 如果没有,您应该弄清楚如何区分运行时的差异 . (是x.length === 1
?还有其他一些显着特征吗?)一旦了解了运行时测试,就可以创建一个类型保护:
希望有所帮助 . 祝好运!
在你的函数签名中有一个错误,
key
参数应该是K
类型,当你使用参数常量时,这将给你更好的推理:使用字符串键并且在编译时未验证的问题是编译器无法真正帮助您 . 它会假设,因为您索引我的任意字符串,返回类型可以是目标的任何有效字段类型 . 在运行时无法验证函数参数类型,因为它们将被擦除,您可以验证参数计数: