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

TypeScript根据对象属性类型定义匹配处理函数的类型问题

问题原因

现有Record类型定义中,所有处理函数的参数均被标注为完整的Activity联合类型,TypeScript无法建立对象key与参数子类型的关联,因此不会自动触发类型窄化,导致无法访问不同类型独有的属性。

实现方法

通过映射类型遍历所有metaData.type的字面量值,结合Extract工具类型筛选出对应type的Activity子类型,将其作为对应处理函数的参数类型即可实现自动窄化。

  1. 首先定义类型提取工具,用于匹配指定type对应的Activity子类型:
type ActivityOfType<T extends Activity["metaData"]["type"]> = Activity & {
  metaData: Extract<Activity["metaData"], { type: T }>
}

Extract会从metaData的联合类型中,筛选出type属性等于泛型T的成员,与原Activity类型交叉后得到精准窄化的子类型。

  1. 使用映射类型重新定义格式化函数集合的类型:
export const activityFormatFunctions: {
  [K in Activity["metaData"]["type"]]: (activity: ActivityOfType<K>) => string
} = {
  createScenario: (activity) => {
    // 自动窄化为createScenario类型,可直接访问对应独有属性
    activity.metaData.data.scenarioId;
    return ""
  },
  createTask: (activity) => {
    activity.metaData.data.taskId;
    return ""
  },
  deleteScenario: (activity) => {
    activity.metaData.data.scenarioName;
    return ""
  },
  deleteTask: (activity) => {
    activity.metaData.data.taskName;
    return ""
  },
  updateScenario: (activity) => {
    // 可直接访问updateScenario独有的scenario属性、data下的scenarioName,无类型报错
    activity.metaData.data.scenarioName;
    activity.metaData.scenario;
    return ""
  },
  updateTask: (activity) => {
    activity.metaData.data.taskName;
    return ""
  },
};
额外优化

如果需要统一调用处理函数,可以封装通用调用方法,全程保留类型校验:

function formatActivity<T extends Activity["metaData"]["type"]>(
  activity: ActivityOfType<T>
): string {
  return activityFormatFunctions[activity.metaData.type](activity);
}

该实现会自动获得以下类型能力:

  • 新增Activity类型时,TS会强制要求补充对应处理函数,避免遗漏
  • 每个处理函数内部会自动做类型窄化,非法访问不存在的属性会直接报类型错误
  • 调用formatActivity时无需手动断言类型,TS会自动推导返回值类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:00:36