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

TypeScript中限制keyof为字符串值类型的自定义筛选Hook类型报错问题咨询

解决useFilter Hook中筛选属性的类型约束问题

这个问题的核心是要让TypeScript精确约束filterProp必须是T中对应值为字符串类型的键,这样就能安全调用toUpperCase()方法了。咱们可以通过自定义条件类型来实现这个需求,具体步骤如下:

1. 定义筛选字符串值键的条件类型

首先创建一个工具类型,专门提取对象类型T中所有值为字符串的键:

type StringKeys<T> = {
  [K in keyof T]: T[K] extends string ? K : never;
}[keyof T];

这个类型的逻辑是:

  • 遍历T的所有键K
  • 如果T[K]是字符串类型,就保留键K,否则标记为never
  • 最后通过[keyof T]取到所有有效键的联合类型

2. 修改useFilter Hook的泛型约束

把原来的K extends Extract<keyof T, string>替换为K extends StringKeys<T>,这样TypeScript就会明确知道item[filterProp]一定是字符串类型:

type StringKeys<T> = {
  [K in keyof T]: T[K] extends string ? K : never;
}[keyof T];

export const useFilter = <T, K extends StringKeys<T>>(
  data: T[] | undefined,
  filterProp: K,
  searchText: string
) => {
  return data?.filter((item) => 
    item[filterProp].toUpperCase().indexOf(searchText.toUpperCase()) > -1
  ) ?? [];
};

3. 验证类型安全

现在测试一下这个Hook的类型约束是否生效:

// 定义一个测试类型
type User = {
  id: number;
  name: string;
  email: string;
};

const users: User[] = [
  { id: 1, name: "Alice", email: "alice@example.com" },
  { id: 2, name: "Bob", email: "bob@example.com" }
];

// ✅ 合法调用:filterProp是值为string的键(name/email)
useFilter(users, "name", "ali");

// ❌ TypeScript报错:'id'不是StringKeys<User>的成员(因为id对应的值是number)
useFilter(users, "id", "1");

这样修改后,不仅解决了原来的类型报错,还能在编译阶段就拦截错误的筛选属性传入,保证了类型安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 15:29:04