如何在TypeScript中实现类型安全的泛型字母排序函数?
如何让TypeScript泛型排序函数识别字段为string类型
要解决这个问题,你需要在泛型约束中明确限定传入的键K对应的字段类型必须是string,这样TypeScript就能自动推断出T[K]是string类型,无需手动类型转换。
方案1:自定义提取字符串键的类型别名
先定义一个类型别名StringKey<T>,它会自动提取类型T中所有值为string类型的键:
type StringKey<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T]; export const sortCollectionAlphabetically = <T>( collection: T[], key: StringKey<T> ): T[] => { return [...collection].sort((a, b) => { return a[key].localeCompare(b[key]); }); };
这里额外做了优化:用[...collection]创建原数组的副本再排序,避免修改原数组(因为Array.sort()是原地排序方法)。
方案2:直接在泛型参数中添加约束
也可以直接在泛型参数里约束T[K]必须是string,写法更紧凑:
export const sortCollectionAlphabetically = <T, K extends keyof T>( collection: T[], key: K extends keyof T ? (T[K] extends string ? K : never) : never ): T[] => { return [...collection].sort((a, b) => { return a[key].localeCompare(b[key]); }); };
效果说明
两种方案都能让TypeScript自动完成校验:
- 只有当传入的
key是T中类型为string的字段时,才允许调用函数 - 在排序回调中,
a[key]和b[key]会被自动推断为string类型,直接调用localeCompare不会有类型错误
示例测试:
interface User { id: number; name: string; email: string; } const users: User[] = [ { id: 1, name: "Bob", email: "bob@example.com" }, { id: 2, name: "Alice", email: "alice@example.com" } ]; // 合法:name是string类型 sortCollectionAlphabetically(users, "name"); // 报错:id是number类型,不符合约束 sortCollectionAlphabetically(users, "id");
内容的提问来源于stack exchange,提问作者jhamm
相关产品推荐
相关产品推荐

