TypeScript中如何根据类的类型调用对应的实例方法?
解决方案
针对这个TypeScript类型校验问题,有三类常用实现方案,可根据业务场景选择:
方案1:用instanceof做运行时类型缩小(实现最简单)
直接通过实例所属类判断是否支持对应方法,运行时做兼容处理即可:
// 首先给SchemaSetter补充当前SchemaBuilder实例的定义,类型为两种Builder的联合类型 class SchemaSetter { private currentBuilder: BaseSchemaBuilder<BaseSchema> | SingleLineSchemaBuilder; constructor(builder: BaseSchemaBuilder<BaseSchema> | SingleLineSchemaBuilder) { this.currentBuilder = builder; } onSetLabel(label: string) { // 两类Builder都实现了setLabel,可直接调用 this.currentBuilder.setLabel(label); } onSetMaxLength(length: string) { // 类型缩小:判断当前实例是否为SingleLineSchemaBuilder if (this.currentBuilder instanceof SingleLineSchemaBuilder) { this.currentBuilder.setMaxLength(length); } else { // 业务侧可自定义降级逻辑:打印警告、抛错或者直接忽略 console.warn('当前Schema类型不支持设置最大长度'); } } }
方案2:自定义类型守卫(更灵活,抗重构)
如果后续可能修改类名、或者有多个子类都支持setMaxLength方法,可以基于属性存在性做类型判断:
// 自定义类型谓词,判断实例是否支持setMaxLength方法 function isSupportMaxLength(builder: BaseSchemaBuilder<BaseSchema>): builder is SingleLineSchemaBuilder { return 'setMaxLength' in builder; } class SchemaSetter { private currentBuilder: BaseSchemaBuilder<BaseSchema> | SingleLineSchemaBuilder; constructor(builder: BaseSchemaBuilder<BaseSchema> | SingleLineSchemaBuilder) { this.currentBuilder = builder; } onSetMaxLength(length: string) { if (isSupportMaxLength(this.currentBuilder)) { this.currentBuilder.setMaxLength(length); } } }
方案3:泛型约束(编译期校验,类型安全性最高)
如果要从类型层面禁止BaseSchemaBuilder场景下调用onSetMaxLength,可以给SchemaSetter加泛型约束,编译期就能发现非法调用:
class SchemaSetter<T extends BaseSchemaBuilder<BaseSchema>> { constructor(private currentBuilder: T) {} onSetLabel(label: string) { this.currentBuilder.setLabel(label); } // 仅当泛型为SingleLineSchemaBuilder时,该方法才允许被调用 onSetMaxLength: T extends SingleLineSchemaBuilder ? (length: string) => void : never = ((length: string) => { if (this.currentBuilder instanceof SingleLineSchemaBuilder) { return this.currentBuilder.setMaxLength(length); } throw new Error('当前Schema不支持设置maxLength属性'); }) as any; } // 使用示例 const baseBuilder = new BaseSchemaBuilder({ label: '' }); const baseSetter = new SchemaSetter(baseBuilder); baseSetter.onSetMaxLength('10'); // 编译阶段直接报错,类型不匹配 const singleLineBuilder = new SingleLineSchemaBuilder({ label: '', maxLength: '' }); const singleLineSetter = new SchemaSetter(singleLineBuilder); singleLineSetter.onSetMaxLength('10'); // 正常调用无报错
内容的提问来源于stack exchange,提问作者Natheeshkumar Rangasamy
相关产品推荐
相关产品推荐

