怎么获取一个object中所有的属性
描述
举例:
type Person = {
name: {
fullname: string;
nickname: string;
};
age: number;
job: {
name: string;
address: {
country: string;
detail: string;
};
};
}
function toPath<T>(obj: T, path: string) {
console.log(obj, path);
}
const person: Person = {
name: {
fullname: '',
nickname: '',
},
age: 30,
job: {
name: '',
address: {
country: '',
detail: '',
},
},
};
/** 调用时,自动枚举出以下属性: **/
// name
// name.fullname
// name.nickname
// age
// job
// job.name
// job.address
// job.address.country
// job.address.detail
toPath(person, 'name.fullname');
toPath(person, 'job.address.country');
实际应用场景:
lodash中的toPath函数
问题
显然,由于path为string类型,这里并没有类型约束,填啥也不会报错!! 对于程序运行时来说,相当不友好。
分布实现
1. 首先获取第一层属性
对大多数同学来说,都非常简单,直接使用keyof即可,如下:
type Path = keyof Person;
function toPath<T>(obj: T, path: Path) {
console.log(obj, path);
}
toPath(person, 'name');
2. 实现嵌套获取
- 声明一个新类型
type NestedPath<ObjectType extends object> = {
// todo
}[keyof ObjectType];
type Paths = NestedPath<Person>;
- 遍历对象的属性
type NestedPath<ObjectType extends object> = {
[Key in keyof ObjectType]: ObjectType[Key]
}[keyof ObjectType];
显然,这样只能获取一层。 当值为object,需要嵌套调用NestedPath
- 嵌套调用NestedPath
type NestedPath<ObjectType extends object> = {
[Key in keyof ObjectType]:
ObjectType[Key] extends object
? `${Key}.${NestedKeyOf<ObjectType[Key]>}`
: Key
}[keyof ObjectType];
此时路径并不包含name, job, 并且Key存在报错
添加属性本身 & 添加Key类型约束
type NestedPath<ObjectType extends object> =
{
[Key in keyof ObjectType & (string | number)]:
ObjectType[Key] extends object
? Key | `${Key}.${NestedPath<ObjectType[Key]>}`
: `${Key}`
}[keyof ObjectType & (string | number)];
到此,实现结束~
思考?????
若job是个数组类型,该如何调整??需求如下:
type Person = {
name: {
fullname: string;
nickname: string;
};
age: number;
job: {
name: string;
address: {
country: string;
detail: string;
};
}[];
}
const person: Person = {
name: {
fullname: '',
nickname: '',
},
age: 30,
job: [
{
name: 'tom',
address: {
country: '',
detail: '',
},
}
],
};