TypeScript如何基于数组字符串路径提取对象嵌套类型实现类型安全排序函数
类型安全嵌套路径数值排序函数实现
问题根源
原有实现的泛型仅约束了路径的第一层属性为目标对象的属性,没有递归校验深层路径的合法性,同时也没有约束路径最终指向的属性必须为数值类型,因此出现了合法嵌套路径被判定为类型错误、非法嵌套路径无类型提示的问题。
解决方案
通过递归工具类型生成目标对象所有合法的数值类型属性路径,再对sortByNumeric的路径参数做泛型约束,即可解决问题。
完整实现代码
export enum SortDirection { ASCENDING = "ASCENDING", DESCENDING = "DESCENDING", } // 递归工具类型:生成对象所有指向指定叶子类型的合法嵌套路径数组 type PathArray<T, LeafType = unknown> = T extends LeafType ? [] : { [K in keyof T]: [K, ...PathArray<T[K], LeafType>] }[keyof T] /** * 生成数值类型排序比较器 * @param path 指向数值类型值的嵌套属性路径 * @param direction 数值排序的方向 * @returns 可直接传入Array.sort的比较函数 */ export const sortByNumeric = <T extends object>( path: PathArray<T, number>, direction = SortDirection.ASCENDING ) => (current: T, next: T) => { const extractedA = path.reduce((acc, key) => acc[key as keyof typeof acc], current) as number const extractedB = path.reduce((acc, key) => acc[key as keyof typeof acc], next) as number return direction === SortDirection.ASCENDING ? extractedA - extractedB : extractedB - extractedA }
测试效果
const source = [ { name: 'Jon', age: 20, father: { name: 'Jon Senior', age: 60, otherProp: 100 } }, { name: 'Gabriel', age: 25, father: { name: 'Jon Senior', age: 80, otherProp: 20 } } ] // 单层属性路径:正常运行 source.sort(sortByNumeric(['age'])) // 合法嵌套路径:正常运行,无类型错误 source.sort(sortByNumeric(['father', 'otherProp'])) // 非法嵌套路径:直接抛出类型错误,提示路径不符合约束 // source.sort(sortByNumeric(['age', 'father']))
内容的提问来源于stack exchange,提问作者Християн Христов
相关产品推荐
相关产品推荐

