完整更新
我错了,我只是覆盖了call
method.
很抱歉给你提供了一个不好的例子。
使用我之前的代码,调用Object.prototype.[any prototype method].call
会像打字机一样,这是错误的。
以前的wrong code:
interface CallableFunction extends Function {
call<T, Prop extends string, R>(this: (this: T, property: Prop) => R, thisArg: T, property: Prop): thisArg is T & Record<Prop, string>;
}
上面代码的意思是Object.prototype.propertyIsEnumerable.call
将充当打字员,因为我只打字了call
.
工作示例
type Tag = { [prop: `tag${number}`]: never }
interface Object {
hasOwnProperty(v: PropertyKey): boolean & Tag
}
interface CallableFunction extends Function {
call<
T,
Prop extends string,
R extends boolean & Tag
>(this: (this: T, property: Prop) => R, thisArg: T, property: Prop): thisArg is T & Record<Prop, string>;
}
declare const obj: { name?: string, surname?: number }
if (Object.prototype.hasOwnProperty.call(obj, 'name')) {
const test = obj.name // string
}
if (Object.prototype.propertyIsEnumerable.call(obj, 'name')) {
const test = obj.name // string | undefined
}
操场
它是如何工作的 ?
我创建了一个品牌类型Tag
并将其与hasOwnProperty
返回类型。
它给了我什么?
call
方法能够推断出返回类型hasOwnProperty
。这是知道调用了哪个原型方法的唯一方法。
然后,我添加了约束R
通用类型。R
是从原型方法推断的返回类型。在我们的例子中是boolean & Tag
。就是这样call
方法能够弄清楚我们已经调用了hasOwnProperty
.