TypeScript:基于elseOp是否定义的条件类型实现问题
问题
我正在创建一系列继承抽象类Operation<T, R>的类,该类定义了方法perform(t: T): R。
我希望实现一个条件操作类ConditionalOperation<T, R> extends Operation<T, T | R>,其构造函数签名如下:
constructor( private predicate: (value: T) => boolean, private thenOp: Operation<T, R>, private elseOp?: Operation<T, R> ) { super(); }
该类的perform方法逻辑如下:
- 若
elseOp已定义,当断言为真时将输入值传给thenOp,否则传给elseOp。 - 若
elseOp未定义,当断言为真时将输入值传给thenOp,否则直接返回输入值。
这种行为决定了ConditionalOperation签名中的T | R:当elseOp定义时返回类型为R,否则为T | R。我尝试通过条件类型实现这种依赖于elseOp是否定义的返回类型校验,编写了对应代码,但TypeScript不允许在elseOp未定义时返回t,尽管此时对应的返回类型应为T | R。
请问除了创建两个条件类之外,还有其他实现方式吗?
解决方案
可以通过方法重载或泛型条件类型两种方式实现,无需拆分多个类。
方式一:利用perform方法重载
直接给perform定义不同的重载签名,让TypeScript根据elseOp的存在自动推断返回类型:
abstract class Operation<T, R> { abstract perform(t: T): R; } class ConditionalOperation<T, R> extends Operation<T, T | R> { constructor( private predicate: (value: T) => boolean, private thenOp: Operation<T, R>, private elseOp?: Operation<T, R> ) { super(); } // 重载签名1:传入elseOp时,返回类型为R perform(t: T): R; // 重载签名2:未传入elseOp时,返回类型为T | R perform(t: T): T | R; // 方法实现 perform(t: T): T | R { if (this.predicate(t)) { return this.thenOp.perform(t); } else { // 使用可选链和空值合并简化逻辑 return this.elseOp?.perform(t) ?? t; } } }
类型验证
// 场景1:无elseOp,返回number | string const op1 = new ConditionalOperation( (num: number) => num > 0, new class extends Operation<number, string> { perform(t: number): string { return t.toString(); } } ); const res1 = op1.perform(-1); // 类型为number | string // 场景2:有elseOp,返回string const op2 = new ConditionalOperation( (num: number) => num > 0, new class extends Operation<number, string> { perform(t) { return t.toString(); } }, new class extends Operation<number, string> { perform(t) { return `neg: ${t}`; } } ); const res2 = op2.perform(-1); // 类型为string
方式二:泛型条件类型+构造函数重载
通过泛型参数标记elseOp的类型,结合条件类型精确控制返回值:
abstract class Operation<T, R> { abstract perform(t: T): R; } // 定义条件类型:根据elseOp是否为undefined决定返回类型 type ConditionalResult<T, R, E> = E extends undefined ? T | R : R; class ConditionalOperation<T, R, E extends Operation<T, R> | undefined = undefined> extends Operation<T, ConditionalResult<T, R, E>> { // 构造函数重载1:传入elseOp constructor( predicate: (value: T) => boolean, thenOp: Operation<T, R>, elseOp: Operation<T, R> ); // 构造函数重载2:不传入elseOp constructor( predicate: (value: T) => boolean, thenOp: Operation<T, R> ); // 构造函数实现 constructor( private predicate: (value: T) => boolean, private thenOp: Operation<T, R>, private elseOp?: E ) { super(); } perform(t: T): ConditionalResult<T, R, E> { if (this.predicate(t)) { return this.thenOp.perform(t) as ConditionalResult<T, R, E>; } else { if (this.elseOp) { return this.elseOp.perform(t) as ConditionalResult<T, R, E>; } else { return t as ConditionalResult<T, R, E>; } } } }
这种方式的类型推断更严格,能在编译阶段就明确区分两种场景的返回类型。
内容的提问来源于stack exchange,提问作者Aisteru Firë
相关产品推荐
相关产品推荐

