TypeScript中如何利用泛型void类型实现参数可选
问题描述
我想创建一个能返回接收泛型类型参数的类实例的类,有时这个泛型参数可能不存在。我不想让参数处于可能为undefined的状态,因此考虑使用void类型,但遇到了问题:当泛型类型为void时,必须传入undefined值。我想知道能不能直接调用Result.ok()而不传入任何参数?
class Result<A>{ private constructor(private readonly data: A){} static ok<A>(data: A): Result<A> { return new Result<A>(data); } print(): void { console.log(this.data ?? 'void'); } } interface IUseCase<A> { execute(): Result<A>; } class UseCaseVoid implements IUseCase<void> { execute(): Result<void> { // 这里是问题所在:必须传入undefined值 const result = Result.ok(undefined); result.print(); return result; } } class UseCaseString implements IUseCase<string> { execute(): Result<string> { const result = Result.ok('string'); result.print(); return result; } } const useCaseVoid = new UseCaseVoid(); useCaseVoid.execute(); // 输出 void const useCaseStr = new UseCaseString(); useCaseStr.execute(); // 输出 string
解决方案
可以通过给Result.ok添加重载签名,实现泛型为void时无需传参的需求,同时保证其他类型的类型安全:
class Result<A>{ private constructor(private readonly data: A){} // 重载:泛型为void时无需传参 static ok(): Result<void>; // 重载:泛型为其他类型时必须传入对应参数 static ok<A>(data: A): Result<A>; // 方法实现 static ok<A>(data?: A): Result<A | void> { return new Result(data as A); } print(): void { console.log(this.data ?? 'void'); } } interface IUseCase<A> { execute(): Result<A>; } class UseCaseVoid implements IUseCase<void> { execute(): Result<void> { // 现在可以直接调用Result.ok(),无需传参 const result = Result.ok(); result.print(); return result; } } class UseCaseString implements IUseCase<string> { execute(): Result<string> { const result = Result.ok('string'); result.print(); return result; } } const useCaseVoid = new UseCaseVoid(); useCaseVoid.execute(); // 输出 void const useCaseStr = new UseCaseString(); useCaseStr.execute(); // 输出 string
这种方式通过重载签名明确区分了两种场景:当你不需要传数据时直接调用Result.ok(),TypeScript会自动推断出返回的是Result<void>;当传入具体值时,会对应到正确的泛型类型,既满足了需求又保证了类型检查的严谨性。
内容的提问来源于stack exchange,提问作者A.L. Developer
相关产品推荐
相关产品推荐

