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

如何在TypeScript泛型中校验指定键对应值的类型?

问题:如何在TypeScript中校验泛型对象指定键的值类型?

我写了一个sortData函数,用来接收键名并根据该键对应的值对对象数组排序:

function compare(v1: string | number, v2: string | number) {
  return (v1 < v2 ? -1 : v1 > v2 ? 1 : 0);
}    

function sortData<T>(data: Array<T>, column: keyof T, direction: string): Array<T> {
  if (direction === '' || column === '') {
    return data;
  } else {
    return [...data].sort((a, b) => {
      const res = compare(a[column], b[column]);
      return direction === 'asc' ? res : -res;
    });
  }
}

现在的问题是,泛型T的对象中,column指定的键对应的值类型可能不是string | number,没法合法传入compare函数。我希望调用sortData时,如果传入的column对应值类型不符合要求,TypeScript编译器直接报错。请问该怎么校验泛型对象指定键的值类型?


解决方案

要实现这个校验,核心是给泛型和参数加类型约束,确保传入的column对应的属性值必须是string | number。下面两种方法都能解决问题:

方法1:筛选对象中可排序的键(推荐)

先定义一个工具类型,提取出对象中值类型为string | number的键,然后让column参数只能是这些键:

function compare(v1: string | number, v2: string | number) {
  return (v1 < v2 ? -1 : v1 > v2 ? 1 : 0);
}    

// 工具类型:提取T中值类型为string | number的键
type ValidSortKey<T> = {
  [K in keyof T]: T[K] extends string | number ? K : never;
}[keyof T];

function sortData<T>(
  data: T[],
  column: ValidSortKey<T>,
  direction: 'asc' | 'desc' | '' = '' // 把direction改成字面量类型,避免传入无效字符串
): T[] {
  if (!direction || !column) {
    return data;
  }
  return [...data].sort((a, b) => {
    const res = compare(a[column], b[column]);
    return direction === 'asc' ? res : -res;
  });
}

方法2:直接约束整个对象的属性类型

如果你的场景里,传入的数组对象所有属性都必须是可排序的(即值为string | number),可以直接给泛型T加约束:

function compare(v1: string | number, v2: string | number) {
  return (v1 < v2 ? -1 : v1 > v2 ? 1 : 0);
}    

// 约束T的所有属性值都是string或number
function sortData<T extends Record<string, string | number>>(
  data: T[],
  column: keyof T,
  direction: 'asc' | 'desc' | '' = ''
): T[] {
  if (!direction || !column) {
    return data;
  }
  return [...data].sort((a, b) => {
    const res = compare(a[column], b[column]);
    return direction === 'asc' ? res : -res;
  });
}

效果验证

现在当你传入不符合要求的column时,TypeScript会立刻报错:

interface User {
  name: string;
  age: number;
  isActive: boolean; // 这个属性值是boolean,不能用于排序
}

const users: User[] = [
  { name: 'Alice', age: 25, isActive: true },
  { name: 'Bob', age: 30, isActive: false }
];

sortData(users, 'isActive', 'asc'); // 编译器报错:"isActive"不能赋值给ValidSortKey<User>类型的参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:02:18