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

如何定义TypeScript类型,排除不含score属性的Model接口

问题描述

我正在开发一个前端应用,后端会生成供前端用于类型定义、服务调用等的SDK。前端使用的一个核心对象在类型定义上遇到了问题,以下是SDK生成的简化示例类型:

export enum ModelTypes {
  ModelOne = 'ModelOne',
  ModelTwo = 'ModelTwo'
}

export interface ModelOne {
  score: ModelOneScores;
  metadata: ModelOneMetadata;
  modelOneProp_A: string;
  modelOneProp_B: string;
}

export interface ModelTwo {
  modelTwoProp_A: number;
  modelTwoProp_B: number;
}

export interface Model {
  id: string;
  created: Date;
  updated: Date;
  data: (ModelOne | ModelTwo);
  type: ModelTypes;
}

如你所见,ModelOne拥有score和metadata属性,而ModelTwo没有。我编写了一个从任意Model中获取分数的函数(可假设ModelOneScores或其他ModelNScores接口内包含averageScore属性):

export function getModelScore(model: Sdk.Model): number {
  switch (model.type) {
    case Sdk.ModelTypes.ModelOne:
      return model.data.score.averageScore;
  }
}

显然TypeScript会报错,因为score不存在于ModelTwo。我需要一个通用类型来告诉TypeScript:我绝不会传入不含score属性的Model(比如ModelTwo),因此Sdk.Model的data始终包含score属性。

解决方案

1. 自定义筛选类型

利用TypeScript的Extract工具类型和条件判断,直接筛选出所有data包含score属性的Model子类型:

// 筛选出data带score属性的Model类型
type ModelWithScore = Extract<Model, { data: { score: unknown } }>;

这个类型会自动排除所有data中没有score的Model(比如示例中的ModelTwo对应的Model实例),只保留符合要求的类型。

2. 修改函数参数类型

将函数的参数类型替换为ModelWithScore,TypeScript就能准确推断出model.data一定包含score属性,不会再报错:

export function getModelScore(model: ModelWithScore): number {
  return model.data.score.averageScore;
}

如果需要保留switch分支用于后续扩展(比如新增其他带score的Model类型),TypeScript也能正确识别每个分支下的data类型:

export function getModelScore(model: ModelWithScore): number {
  switch (model.type) {
    case ModelTypes.ModelOne:
      return model.data.score.averageScore;
    // 后续新增ModelThree(带score)时,直接添加case即可,TypeScript会自动推断类型
  }
}

3. 通用类型工具(可选)

如果需要复用这种“筛选带有指定属性的Model”的逻辑,可以封装一个通用类型工具:

// 通用类型:筛选出data包含指定属性的Model
type ModelWithDataProperty<T extends keyof any> = Extract<Model, { data: Record<T, unknown> }>;

// 使用示例:筛选带score的Model
type ModelWithScore = ModelWithDataProperty<'score'>;
// 筛选带metadata的Model
type ModelWithMetadata = ModelWithDataProperty<'metadata'>;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 08:20:08