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

修复TypeScript条件添加对象属性时的类型推导错误

解决TypeScript条件添加对象属性的类型定义问题

问题分析

当前实现的addIf和fancyObject功能逻辑正常,但类型推导存在缺陷:计算属性会被识别为宽泛的字符串索引,最终返回类型无法精准反映条件属性是否存在,不符合预期的明确类型定义。

解决方案

通过调整addIf的泛型条件类型,让TypeScript根据条件字面量判断返回的键类型;再通过映射类型过滤掉标记为移除的属性,实现精准的类型推导。

修改后的完整代码

const REMOVE_CONST = 'removeMe'

// 根据条件字面量决定返回的键类型
const addIf = <T extends string, C extends boolean>(
  condition: C,
  key: T
): C extends true ? T : typeof REMOVE_CONST => {
  return (condition ? key : REMOVE_CONST) as any
}

// 映射类型:过滤掉键为REMOVE_CONST的属性
type FilterRemoveKeys<T> = {
  [K in keyof T as K extends typeof REMOVE_CONST ? never : K]: T[K]
}

function fancyObject<T extends Record<string, unknown>>(POJO: T): FilterRemoveKeys<T> {
  const { [REMOVE_CONST]: _, ...POJO_ } = POJO
  return POJO_ as FilterRemoveKeys<T>
}

效果验证

  1. 条件为字面量true:
const myObj = fancyObject({
  a: 'apple',
  b: 'banana',
  c: 'cajo',
  [addIf(true, 'd')]: () => 'mew',
})
// 推导类型(符合最优预期):
// {
//   a: string;
//   b: string;
//   c: string;
//   d: () => string;
// }
  1. 条件为字面量false:
const myObj2 = fancyObject({
  a: 'apple',
  [addIf(false, 'd')]: () => 'mew',
})
// 推导类型:
// {
//   a: string;
// }
  1. 条件为动态布尔值(非字面量):
const condition = Math.random() > 0.5
const myObj3 = fancyObject({
  a: 'apple',
  [addIf(condition, 'd')]: () => 'mew',
})
// 推导类型(符合次优预期):
// {
//   a: string;
//   d?: () => string;
// }

原理说明

  • addIf通过泛型C extends boolean捕获条件的字面量类型,利用条件类型返回对应的键:条件为true时返回指定键T,为false时返回标记值REMOVE_CONST。
  • FilterRemoveKeys映射类型遍历对象的所有键,仅保留非REMOVE_CONST的键,过滤掉需要移除的属性类型。
  • 这样TypeScript就能精准识别条件属性的存在性,避免出现宽泛的字符串索引签名。

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:57:41