TypeScript 的类型系统非常强大,尤其是在 TypeScript 4.1 引入了模板字面量类型和递归类型之后,可以通过类型体操来实现一些复杂的类型检查。然而,TypeScript 的类型系统仍然是静态的,无法在运行时动态验证对象路径字符串的有效性。
不过,你可以通过类型体操来在一定程度上验证对象路径字符串的有效性。具体来说,你可以利用递归类型和模板字面量类型来解析路径字符串,并检查它是否与给定的对象类型匹配。
假设我们有一个对象类型 Obj
,我们想要验证一个路径字符串是否有效:
type Obj = {
user: {
name: string;
age: number;
address: {
city: string;
zip: string;
};
};
posts: {
title: string;
content: string;
}[];
};
type Path<T, K extends keyof T = keyof T> = K extends string
? T[K] extends Record<string, any>
? `${K}.${Path<T[K]>}`
: K
: never;
type ValidPath<T> = Path<T> | keyof T;
// 示例路径
type UserNamePath = ValidPath<Obj>; // "user.name" | "user.age" | "user.address.city" | "user.address.zip" | "posts"
在这个例子中,Path<T>
类型会递归地生成所有可能的路径字符串。ValidPath<T>
类型则是所有可能的路径字符串的联合类型。
function getValue<T, P extends ValidPath<T>>(obj: T, path: P): any {
// 实际实现需要解析路径字符串并获取值
return path.split('.').reduce((acc, key) => acc[key], obj);
}
const obj: Obj = {
user: {
name: "Alice",
age: 30,
address: {
city: "Wonderland",
zip: "12345"
}
},
posts: [
{ title: "Post 1", content: "Content 1" },
{ title: "Post 2", content: "Content 2" }
]
};
const userName = getValue(obj, "user.name"); // 类型安全
const userAge = getValue(obj, "user.age"); // 类型安全
const city = getValue(obj, "user.address.city"); // 类型安全
const invalidPath = getValue(obj, "user.invalid"); // 类型错误
虽然 TypeScript 的类型体操可以在一定程度上验证对象路径字符串的有效性,但它并不能完全替代运行时的路径验证。对于复杂的场景,建议结合运行时验证和静态类型检查来确保路径的有效性。