如何让TypeScript不为带调用签名的Proxy伪装对象添加不存在属性?
解决TypeScript中Proxy伪装函数时的类型提示问题
这个问题的核心在于:TypeScript会默认把带有调用签名的类型视为Function的子类型,所以会自动给这类接口加上apply、call、length等Function原型的属性,但你的Proxy目标是普通Object,实际并不具备这些属性,导致类型提示和实际情况不符。
下面提供两种实用的解决方案:
方案一:通过类型交叉排除Function原型属性
我们可以利用索引类型,把Function的所有属性标记为never,让TypeScript明确知道这些属性不存在:
// 定义类型:调用签名 + 自定义属性 + 排除所有Function原型属性 type AA = { (): void; abc: number; } & { [K in keyof Function]?: never }; // 使用类型断言让TS接受Proxy实例 const aa = new Proxy({ abc: 12345 }, { apply() { console.log('aa~') } }) as AA;
这样处理后,当你试图访问aa.apply、aa.length这类属性时,TypeScript会提示类型为never,明确告诉你这些属性不存在,完全符合实际运行时的情况。
方案二:手动覆盖Function属性为never(更直观)
如果你觉得索引类型不够直观,也可以手动列出需要屏蔽的Function核心属性,把它们的类型设为never:
interface AA { (): void; abc: number; // 覆盖Function原型的核心属性,标记为never apply: never; call: never; bind: never; length: never; name: never; arguments: never; caller: never; } const aa = new Proxy({ abc: 12345 }, { apply() { console.log('aa~') } }) as AA;
这种方式适合你明确知道不需要哪些Function属性的场景,缺点是需要手动列举属性,但胜在清晰易懂。
为什么需要类型断言?
因为Proxy构造函数返回的类型是对应目标对象的类型,和我们定义的带调用签名的类型天然不兼容,所以必须用as AA来告诉TypeScript:“我确认这个实例符合AA类型的要求”。
内容的提问来源于stack exchange,提问作者Fuu
相关产品推荐
相关产品推荐

