如何在TypeScript中根据null值推导不同类型?
解决方案
要实现根据responseConstructor参数是否为null返回不同类型的需求,可以通过函数重载或条件类型两种方式实现,以下是具体方案:
方案1:函数重载(推荐,直观无断言)
利用TypeScript的函数重载特性,为不同参数类型定义对应的返回类型:
import { Message } from "@bufbuild/protobuf"; // 重载签名1:传入null时,返回空对象类型 export async function sendRequest(responseConstructor: null): Promise<{}>; // 重载签名2:传入有效构造函数时,返回带data的类型 export async function sendRequest<T extends Message>(responseConstructor: new () => T): Promise<{ data: T }>; // 实现签名(仅用于内部逻辑,对外不暴露) export async function sendRequest<T extends Message>( responseConstructor: (new () => T) | null ): Promise<{} | { data: T }> { if (!responseConstructor) { return {}; } return { data: new responseConstructor() }; }
效果说明
- 当调用
sendRequest(null)时,TypeScript会自动推断返回类型为Promise<{}> - 当传入有效的
Message构造函数(比如sendRequest(UserMessage))时,返回类型为Promise<{ data: UserMessage }>,此时data不再包含null的可能性
方案2:条件类型(灵活复用类型逻辑)
通过自定义条件类型,根据参数的泛型类型动态推导返回类型:
import { Message } from "@bufbuild/protobuf"; // 条件类型:根据构造函数类型推导返回结果 type RequestResult<C> = C extends null ? {} : C extends new () => infer T ? { data: T } : never; export async function sendRequest<C extends (new () => Message) | null>( responseConstructor: C ): Promise<RequestResult<C>> { if (!responseConstructor) { return {} as RequestResult<C>; } return { data: new responseConstructor() } as RequestResult<C>; }
效果说明
泛型C捕获传入的参数类型(构造函数或null),RequestResult通过条件判断:
- 若
C是null,返回{} - 若
C是Message的构造函数,提取其实例类型T,返回{ data: T } - 实现时需要类型断言,因为TypeScript无法自动在分支中精确匹配条件类型的返回值
原代码问题分析
原代码的Result<T>固定为{ data: T | null },且泛型T仅绑定Message,未关联参数的null状态,导致无论参数是否为null,返回类型都包含data为null的可能,无法满足需求。
内容的提问来源于stack exchange,提问作者Ahmet Yazıcı
相关产品推荐
相关产品推荐

