TypeScript:如何定义含唯一确定字段的对象数组类型?
关于TypeScript中排序函数的参数类型定义问题
场景示例
我有如下对象数组:
const obj = [ { createdAt: "2022-10-25T08:06:29.392Z", updatedAt: "2022-10-25T08:06:29.392Z"}, { createdAt: "2022-10-25T08:06:29.392Z", animal: "cat"} ]
我想编写一个按createdAt字段排序的函数,该字段是数组中每个对象唯一确定存在的字段,函数代码如下:
export const sortArrayByCreatedAt = (arr: TypeArr) => { return arr.sort(function (a, b) { return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf(); }); };
我的疑问
我当前对参数arr的类型定义如下:
type TypeArr = { createdAt: string }[]
这种仅定义已知字段的方式是否为最佳实践?我担心其他开发者看到该函数会误以为数组元素仅包含createdAt字段,但暂未找到更优方案。
解决方案与分析
1. 更合理的类型定义
你最初的类型定义存在一个问题:它会让TypeScript把数组元素判定为仅包含createdAt的对象,丢失了原对象的其他字段类型信息。更优的方案是用泛型约束来定义参数类型:
export const sortArrayByCreatedAt = <T extends { createdAt: string }>(arr: T[]) => { return arr.sort((a, b) => { return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf(); }); };
如果想单独抽离类型,也可以先定义一个基础类型,再用泛型约束:
type HasCreatedAt = { createdAt: string; }; export const sortArrayByCreatedAt = <T extends HasCreatedAt>(arr: T[]) => { return arr.sort((a, b) => { return new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf(); }); };
2. 泛型约束的优势
- 保留完整类型信息:传入的数组元素不管有多少额外字段(比如
updatedAt、animal),返回的数组都会保留这些字段的类型,不会出现后续使用时类型报错的情况。 - 避免误解:其他开发者看到
T extends { createdAt: string }时,能立刻明白这个函数只要求对象必须有createdAt字段,完全允许存在其他属性,不会产生“元素只能有createdAt”的误解。 - 复用性更强:同一个排序函数可以直接用在任何包含
createdAt字段的对象数组上,不用为不同结构的数组重复写排序逻辑。
3. 关于“仅定义已知字段”的实践
你最初的写法并非最佳实践,因为它会在类型层面“阉割”掉原对象的额外字段,虽然运行时不会有问题,但不符合TypeScript的类型安全设计理念——我们希望类型能准确反映数据结构,而不是刻意缩小范围。
内容的提问来源于stack exchange,提问作者afohr
相关产品推荐
相关产品推荐

