TypeScript能否通过this类型校验禁止方法传入自身实例作为参数
问题解答
首先明确:你要的「允许同类型其他实例传入、仅禁止当前实例自身传入」的校验,无法仅通过TypeScript静态类型系统实现,原因如下:
- TypeScript是结构化类型系统,不会追踪单个实例的唯一身份,同一个类实例化出来的所有对象,都共享同一个类型,比如你示例中的
b和bb的类型都是B,静态层面无法区分二者。 - 你示例中的
T extends this ? never : T写法的逻辑是基于类型匹配的,只要传入的参数类型和当前实例类型一致,就会被判定为never,会把b.addChild(bb)也误判为错误,不符合你的预期。
如果你可以接受「禁止传入所有和当前实例同类型的实例」的校验规则,可以调整写法实现前两个测试用例的校验效果:
type AB = A | B; export class A { a: string = ''; } export class B { b: string = ''; /** 仅允许传入A类实例,禁止传入所有B类实例 */ addChild<T extends AB>(token: Exclude<T, B>) { return this; } } const a = new A(); const b = new B(); b.addChild(a); // 🟢 正常通过 b.addChild(b); // 🔴 抛出类型错误
如果你必须要保留「允许同类型其他实例传入」的规则,只能搭配运行时校验实现,代码如下:
type AB = A | B; export class A { a: string = ''; } export class B { b: string = ''; addChild(token: AB) { if (token === this) { throw new Error('禁止传入实例自身作为子节点'); } return this; } } const a = new A(); const b = new B(); const bb = new B(); b.addChild(a); // 🟢 正常通过 b.addChild(bb); // 🟢 正常通过 b.addChild(b); // 🔴 运行时抛出错误
该代码在传入自身实例时会主动抛出运行时错误,同时静态层面允许所有符合AB类型的参数传入,满足你b.addChild(bb)正常通过的需求。
内容的提问来源于stack exchange,提问作者jon
相关产品推荐
相关产品推荐

