如何定义可接收严格类型对象路径的TypeScript函数?
TypeScript类型安全的对象路径校验函数实现
要实现能让编译器校验SomeType合法路径的doSomething函数,核心是通过递归类型生成所有合法路径的联合类型,再将函数参数约束为该类型。具体步骤如下:
1. 定义递归路径生成类型
先实现两个辅助类型,用来递归遍历对象属性并生成合法路径字符串:
// 判断类型是否为可遍历的对象(排除数组和基本类型) type IsObject<T> = T extends object ? T extends Array<any> ? false : true : false; // 递归生成所有合法路径的联合类型 type Path<T> = T extends object ? { [K in keyof T]: K extends string ? IsObject<T[K]> extends true ? `${K}` | `${K}.${Path<T[K]>}` : `${K}` : never; }[keyof T] : never;
2. 定义约束参数的函数
将doSomething的参数类型指定为Path<SomeType>,这样编译器会自动校验传入的路径是否合法:
type SomeType = { propA: { propA1: { propA12: string; }; propA2: string; }; propB: { propB1: string; propB2: { propB12: string; propB22: string; }; }; }; function doSomething(path: Path<SomeType>) { // 这里编写函数逻辑 }
3. 验证效果
- 合法调用:编译器不会报错
doSomething('propA.propA1') // 正常 doSomething('propA') // 正常 doSomething('propB.propB2.propB12') // 正常
- 非法调用:编译器会直接提示类型错误
doSomething('propA.propB') // 报错:类型不匹配 doSomething('propB.propA1') // 报错:类型不匹配 doSomething('propA.propA2.propA12') // 报错:类型不匹配
类型工作原理
IsObject用于过滤出可以继续遍历的对象类型,避免对字符串、数字等基本类型或数组进行无效遍历。Path<T>通过映射类型遍历对象的每个属性键:如果属性值是对象,则生成当前键本身,以及当前键拼接子属性路径的字符串;如果属性值是基本类型,则只生成当前键。最终通过[keyof T]将所有可能的路径合并为一个联合类型,实现参数的类型约束。
内容的提问来源于stack exchange,提问作者Pablo Grabarnik
相关产品推荐
相关产品推荐

