typescript - 使用點記法為物件路徑定義型別
我正在嘗試輸入一個用點記法表示物件路徑的字串(例如:"users.1.name")。我已經非常接近擁有一個完全可行的解決方案。我的最後一個問題是遞迴類型會出現這個錯誤:
Type instantiation is excessively deep and possibly infinite.
我想解決這個問題,或者至少找到一種限制遞迴的方法,以免出現這個錯誤。
這是我的程式碼(Playground):
type PathImpl<T, K extends keyof T> =
K extends (string | number)
? T[K] extends Record<string, any>
? T[K] extends ArrayLike<any>
? K | `${K}.${PathImpl<T[K], number>}`
: K | `${K}.${PathImpl<T[K], keyof T[K]>}`
: K
: never;
export type ObjectPath<T> = PathImpl<T, keyof T> | keyof T;
// Test:
type User = {
name: string,
address: {
lines: {
street: string,
streetNumber: number
}[],
zip: string,
}
};
const streetNumber: ObjectPath<User> = "address.lines.2.streetNumber" // ✅
const foo: ObjectPath<User> = "address.lines.2.foo" // ❌ rejects invalid path as expected
// Recursive type (TS is fine with it)
type UserWithFriends = {
name: string,
friends: UserWithFriends[]
}
// TS Error: Type instantiation is excessively deep and possibly infinite.
const f: ObjectPath<UserWithFriends> = 'name'
(這段程式碼的靈感來自這則推文)