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

如何声明条件存在的属性?TypeScript条件属性类型定义

如何定义TypeScript类型,让data仅在code为200时存在?

我的服务器返回的数据结构如下:

{
    code: number;
    info: string;
    data //仅在code为200时存在
}

我编写了如下代码处理返回结果:

const res = await fetch(...)
const result:MyType = await res.json()
if (result.code != 200) {
   //处理无data的情况
} else {
  //处理result.data
}

GitHub Copilot给出了一种实现方案,看起来可行,但我想了解是否有其他实现方式:

type Type1 = {
    code: number;
    info: string;
    data?: string; // 可选属性
}

type Type2 = Type1 & { code: 200, data: string };

// 使用示例:
const obj1: Type2 = { code: 200, info: "Success" }; // 报错:缺少data属性,但可以将obj1定义为Type1
const obj2: Type1 = { code: 404, info: "Not Found" }; // 合法
const obj3: Type2 = { code: 200, info: "Success", data: "Some data" }; // 合法 

其他可行的实现方式

1. 直接使用判别式联合类型(最推荐)

这是TypeScript中处理这类"条件存在属性"场景最直观的方式,通过联合两个明确的类型,让TypeScript能根据code的值自动推断属性是否存在:

// 定义成功响应类型,code固定为200且必须有data
type SuccessResponse = {
  code: 200;
  info: string;
  data: string; // 这里可以换成你实际的data类型,比如unknown/自定义类型
};

// 定义失败/其他响应类型,code为非200,没有data
type ErrorResponse = {
  code: Exclude<number, 200>;
  info: string;
};

// 联合类型作为最终的响应类型
type ApiResponse = SuccessResponse | ErrorResponse;

// 使用示例
const res = await fetch(...);
const result: ApiResponse = await res.json();

if (result.code === 200) {
  // TypeScript会自动推断这里result是SuccessResponse,可直接访问result.data
  console.log(result.data);
} else {
  // 这里result是ErrorResponse,不存在data属性
  console.log(result.info);
}

这种方式的优势是类型检查最严格:如果code是200,TypeScript会强制要求存在data;如果code不是200,就完全不能访问data,避免了可选属性可能带来的undefined风险。

2. 利用条件类型实现

通过条件类型可以动态根据code的值决定类型结构,适合需要复用类型逻辑的场景:

type ApiResponse<TCode extends number> = TCode extends 200 
  ? { code: 200; info: string; data: string } 
  : { code: TCode; info: string };

// 使用示例
// 当明确code为200时
const successRes: ApiResponse<200> = { code: 200, info: "ok", data: "data" };
// 当code为其他值时
const errorRes: ApiResponse<404> = { code: 404, info: "not found" };

// 对于未知code的情况,可以结合联合类型
type UnknownApiResponse = ApiResponse<200> | ApiResponse<Exclude<number, 200>>;
const result: UnknownApiResponse = await res.json();
if (result.code === 200) {
  console.log(result.data);
}

3. 改进Copilot的方案

Copilot的方案使用了交叉类型,但可以优化得更严格:把基础类型中的code改为非200的数值,避免出现code=200却没有data的合法情况:

type ErrorResponse = {
  code: Exclude<number, 200>;
  info: string;
  data?: never; // 明确禁止非200响应出现data
};

type SuccessResponse = {
  code: 200;
  info: string;
  data: string;
};

type ApiResponse = ErrorResponse | SuccessResponse;

这样修改后,非200的响应即使写了data也会报错,进一步强化了类型约束。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 08:43:31