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
相关产品推荐
相关产品推荐

