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

TypeScript联合类型中嵌套对象的类型安全处理方案问询

实现简洁且类型安全的嵌套对象处理函数

假设我们有三个嵌套对象类型Basic、Extra、Extra2,它们共享部分configs配置,但嵌套结构存在差异。目前有两个功能完全一致的函数:

  • test写法简洁,但因嵌套对象的结构差异触发TypeScript类型错误
  • test2严格符合TypeScript规范,但代码过于冗长

先定义示例类型和问题函数:

// 共享的配置类型
type SharedConfigs = {
  timeout: number;
  retries: number;
};

// 基础类型
type Basic = {
  configs: SharedConfigs;
  type: 'basic';
};

// 扩展类型1
type Extra = {
  wrapper: {
    configs: SharedConfigs;
  };
  type: 'extra';
};

// 扩展类型2
type Extra2 = {
  nested: {
    inner: {
      configs: SharedConfigs;
    };
  };
  type: 'extra2';
};

// 简洁但类型报错的test函数
function test(obj: Basic | Extra | Extra2) {
  // TypeScript报错:无法确定obj的具体结构,无法直接访问嵌套的configs
  const configs = obj.configs || obj.wrapper?.configs || obj.nested?.inner?.configs;
  console.log(configs.timeout, configs.retries);
}

// 合规但冗长的test2函数
function test2(obj: Basic | Extra | Extra2) {
  let configs: SharedConfigs;
  if (obj.type === 'basic') {
    configs = obj.configs;
  } else if (obj.type === 'extra') {
    configs = obj.wrapper.configs;
  } else {
    configs = obj.nested.inner.configs;
  }
  console.log(configs.timeout, configs.retries);
}

方案一:自定义类型守卫函数

把类型判断逻辑封装成独立的类型守卫函数,主函数可以用简洁的三元表达式实现:

function isBasic(obj: Basic | Extra | Extra2): obj is Basic {
  return obj.type === 'basic';
}

function isExtra(obj: Basic | Extra | Extra2): obj is Extra {
  return obj.type === 'extra';
}

function isExtra2(obj: Basic | Extra | Extra2): obj is Extra2 {
  return obj.type === 'extra2';
}

function test3(obj: Basic | Extra | Extra2) {
  const configs = isBasic(obj) ? obj.configs : 
                  isExtra(obj) ? obj.wrapper.configs : 
                  obj.nested.inner.configs;
  console.log(configs.timeout, configs.retries);
}

方案二:封装提取逻辑到辅助函数

把提取configs的逻辑单独抽成辅助函数,主函数只需要调用该函数即可,写法简洁且类型安全:

function getConfigs(obj: Basic | Extra | Extra2): SharedConfigs {
  if ('configs' in obj) {
    return obj.configs;
  } else if ('wrapper' in obj) {
    return obj.wrapper.configs;
  } else {
    return (obj as Extra2).nested.inner.configs;
  }
}

function test4(obj: Basic | Extra | Extra2) {
  const configs = getConfigs(obj);
  console.log(configs.timeout, configs.retries);
}

方案三:利用区分联合类型的映射写法

因为三个类型都有type这个区分字段,可以直接用对象映射的方式快速匹配对应结构,写法最简洁:

function test5(obj: Basic | Extra | Extra2) {
  const configs = {
    basic: obj.configs,
    extra: (obj as Extra).wrapper.configs,
    extra2: (obj as Extra2).nested.inner.configs
  }[obj.type];
  
  console.log(configs.timeout, configs.retries);
}

总结

  • 类型守卫函数适合类型较多、需要复用判断逻辑的场景
  • 辅助函数适合把提取逻辑封装隔离,主函数聚焦业务逻辑
  • 区分联合类型的映射写法最简洁,适合有明确区分字段的联合类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:12:13