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

TypeScript中如何定义包含Void属性的泛型与非泛型版本类型?

TypeScript中如何定义包含Void属性的泛型与非泛型版本类型?

嘿,我来帮你搞定这个TypeScript里的类型定义问题!很多时候我们都需要这样的场景:有一个响应类型,既可以在不需要返回具体业务数据的时候用“轻量版”,又能在需要带数据的时候用泛型版本来约束数据结构,就像你想实现的ServiceResponse那样。

一开始你可能会尝试写两个同名的类,比如:

export class ServiceResponse {}
export class ServiceResponse<T> extends ServiceResponse {}

但这种写法在TypeScript里直接就会报重复定义的错误,根本跑不起来。那靠谱的做法是什么呢?给你两种常用的方案:

方案一:单个类+泛型默认值(最简洁)

我们可以给泛型参数设置一个默认类型,比如void,这样当你不指定泛型参数时,就自动用这个默认类型,完美兼顾两种场景:

export class ServiceResponse<T = void> {
  status: number;
  message: string;
  data: T;

  constructor(status: number, message: string, data: T) {
    this.status = status;
    this.message = message;
    this.data = data;
  }
}

怎么用?

  • 非泛型场景(不需要数据):直接实例化,不用传泛型参数,data可以传undefined或者符合void类型的值
    const successResp = new ServiceResponse(200, "操作成功", undefined);
    
  • 泛型场景(带具体数据):指定泛型参数,把对应的数据传进去就行
    // 先定义个示例数据类型
    interface User {
      id: number;
      name: string;
    }
    const userResp = new ServiceResponse<User>(200, "获取用户成功", { id: 1, name: "张三" });
    

方案二:基础接口+泛型接口(更灵活)

如果你希望非泛型版本完全不带data属性,那可以用接口来拆分:

// 基础的响应结构,所有场景都共用
interface BaseServiceResponse {
  status: number;
  message: string;
}

// 带数据的泛型版本,继承基础结构
interface ServiceResponse<T> extends BaseServiceResponse {
  data: T;
}

// 给非泛型版本起个别名,用void作为泛型参数
type VoidServiceResponse = ServiceResponse<void>;

这种方式的好处是类型划分更清晰,VoidServiceResponse就是没有业务数据的响应,ServiceResponse<T>是带数据的版本,用的时候按需选择就行。

其实这两种方案都能解决你的问题,我个人更倾向第一种,代码量少还直观,你可以根据自己的项目需求选~

备注:内容来源于stack exchange,提问作者emery.noel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:38:15