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

如何让TypeScript推导同一类型的同一属性类型一致(排序场景)

解决方案:基于属性类型的类型守卫实现类型安全排序

要解决这个问题,我们可以通过提取特定类型属性名的工具类型+自定义类型守卫,让TypeScript基于Item的类型定义而非属性值来区分排序逻辑,完全避免冗余的运行时类型检查。

步骤1:定义工具类型筛选属性名

先创建两个工具类型,分别提取Item中类型为string和number的属性名:

type Item = {
  prop1: string;
  prop2: number;
  prop3: string;
  prop4: number;
};

// 提取Item中类型为string的属性名
type StringProps<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
// 提取Item中类型为number的属性名
type NumberProps<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T];

步骤2:实现带类型守卫的排序函数

编写通用排序函数,通过类型守卫判断属性名对应的类型分支,让TypeScript自动推导属性值类型:

function sortItems<T extends Item>(items: T[], propertyName: StringProps<T> | NumberProps<T>): T[] {
  // 类型守卫:判断属性是否为string类型的属性名
  function isStringProp(prop: StringProps<T> | NumberProps<T>): prop is StringProps<T> {
    // 利用题目中"每个属性类型单一"的约定,仅通过第一个元素做一次类型判断
    return typeof items[0][prop] === 'string';
  }

  return [...items].sort((item1, item2) => {
    const value1 = item1[propertyName];
    const value2 = item2[propertyName];

    if (isStringProp(propertyName)) {
      // TypeScript自动推导value1/value2为string类型
      return value1.localeCompare(value2);
    } else {
      // TypeScript自动推导value1/value2为number类型
      return value1 - value2;
    }
  });
}

步骤3:使用示例

调用时TypeScript会自动校验属性名,并匹配对应排序逻辑:

const items: Item[] = [
  { prop1: "b", prop2: 2, prop3: "x", prop4: 4 },
  { prop1: "a", prop2: 1, prop3: "y", prop4: 3 },
];

// 按string类型属性排序
const sortedByString = sortItems(items, "prop1");
// 按number类型属性排序
const sortedByNumber = sortItems(items, "prop2");

核心原理

  • 工具类型StringProps和NumberProps通过映射类型遍历Item属性,编译期就筛选出对应类型的属性名,让TypeScript提前知晓属性类型归属。
  • 自定义类型守卫仅做一次运行时判断(依赖题目中"属性类型单一"的约定),后续排序逻辑中TypeScript会完全信任类型断言,自动推导值的类型,避免对每个元素做冗余类型检查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 11:50:13