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

如何在TypeScript中实现类似Rust枚举、Kotlin密封类的变体类型

在TypeScript中创建类似Rust枚举/Kotlin密封类的HTTP响应变体类型

我希望在TypeScript中为HTTP响应创建一种可包含多种状态的变体类型。在Rust中可如下实现:

enum Response<T> {
    Empty,
    Loading,
    Failure(String),
    Success(data: T),
}

在Kotlin中可通过密封类实现:

sealed class Response<out T> {
  object Empty: Response<Nothing>()
  object Loading: Response<Nothing>()
  class Failure(val err: String): Response<Nothing>()
  class Success(val data: T): Response<T>()
}

请问在TypeScript中是否有办法创建这类变体类型?


答案:可以使用区分联合类型(Discriminated Unions)

TypeScript没有原生支持带关联数据的枚举,但可以通过区分联合类型实现相同效果——这是TS中处理多状态变体类型的标准方案,具备完整的类型安全性。

基础实现:带区分标记的联合类型

定义包含所有状态的联合类型,每个状态通过唯一的type字段作为区分符,同时携带对应的数据:

// 定义HTTP响应变体类型
type Response<T> =
  | { type: 'Empty' }
  | { type: 'Loading' }
  | { type: 'Failure'; error: string }
  | { type: 'Success'; data: T };

创建各状态实例

// 空状态
const emptyResp: Response<never> = { type: 'Empty' };
// 加载中状态
const loadingResp: Response<never> = { type: 'Loading' };
// 失败状态
const failureResp: Response<never> = { type: 'Failure', error: '请求超时,请重试' };
// 成功状态(携带自定义数据类型)
const successResp: Response<{ id: number; name: string }> = {
  type: 'Success',
  data: { id: 1, name: '用户信息' }
};

类型收窄与处理

TypeScript会根据type字段自动推断每个分支的具体类型,无需额外类型断言:

function handleResponse<T>(response: Response<T>) {
  switch (response.type) {
    case 'Empty':
      console.log('当前无响应数据');
      break;
    case 'Loading':
      console.log('数据加载中...');
      break;
    case 'Failure':
      // 此处response.error自动推断为string类型
      console.error('请求失败:', response.error);
      break;
    case 'Success':
      // 此处response.data自动推断为T类型
      console.log('请求成功,数据:', response.data);
      break;
  }
}

可选:类风格实现(接近Kotlin密封类)

如果希望每个状态是类实例(更贴近Kotlin密封类的写法),可以用抽象类+内部子类实现:

abstract class Response<T> {
  private constructor() {}

  static Empty = class extends Response<never> {};
  static Loading = class extends Response<never> {};
  static Failure = class extends Response<never> {
    constructor(public error: string) {
      super();
    }
  };
  static Success = class<T> extends Response<T> {
    constructor(public data: T) {
      super();
    }
  };
}

// 使用示例
const empty = new Response.Empty();
const loading = new Response.Loading();
const failure = new Response.Failure('接口返回错误');
const success = new Response.Success({ id: 2, content: '文章内容' });

这种方式需要用instanceof进行类型收窄:

function handleResponse<T>(response: Response<T>) {
  if (response instanceof Response.Empty) {
    console.log('响应为空');
  } else if (response instanceof Response.Loading) {
    console.log('加载中');
  } else if (response instanceof Response.Failure) {
    console.error('失败原因:', response.error);
  } else if (response instanceof Response.Success) {
    console.log('获取数据:', response.data);
  }
}

内容的提问来源于stack exchange,提问作者dessalines

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:52:58