You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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ı

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:40:03