[英]Generic to recursively modify a given type/interface in Typescript
我正在努力制作一個通用的,它將遞歸地修改在嵌套遞歸數據結構中找到的所有元素。 這是我的數據結構的示例。 使用此遞歸數據定義,任何帖子都可以有無限數量的帶有回復的評論。
type Post = {
user: string,
content: string,
comments: Comment[],
reactions: Reaction[],
}
type Comment = {
user: string,
content: string,
replies: Comment[],
}
type Reaction = {
user: string,
reaction: "laugh" | "cry" | "smile",
}
我想要的是一個通用包裝器,我可以將其與這些以及任何其他數據類型一起使用,這些數據類型將用其他東西替換每個user
字段。 我可以為頂層做到這一點:
type UserFilled<T> = Omit<"user", T> & { user: { id: string, name: string }}
但這只會更改 Post 的user
字段。 我還希望它向下爬取並替換每個評論的更改user
字段,如果有更多字段,則用於反應、喜歡或任何其他包含user
的結構。
我已經看到有關遞歸省略某些內容的答案,但我無法使用聯合將修改后的屬性重新添加,我想知道是否有更直接的方法可以做到這一點,而不僅僅是省略而且替換字段?
例如,使用泛型我希望能夠做到這一點:
const post: Post = {
user: "1234",
content: "this is a post",
comments: [{
user: "3456",
content: "I agree",
replies: [{
user: "1234",
content: "thanks",
}],
}],
reactions: [{
user: "5678",
reaction: "smile",
}],
};
const postWUserInfo: UserFilled<Post> = {
user: { id: "1234", name: "Bob" },
content: "this is a post",
comments: [{
user: { id: "3456", name: "Jim" },
content: "I agree",
replies: [{
user: { id: "1234", name: "Bob" },
content: "thanks",
}],
}],
reactions: [{
user: { id: "5678", name: "Jim" },
reaction: "smile",
}],
};
您可以創建一個 DeepReplace 實用程序來遞歸檢查和替換密鑰。 另外我強烈建議只替換值並確保密鑰保持不變。
// "not object"
type Primitive = string | Function | number | boolean | Symbol | undefined | null
// If T has key K ("user"), replace it
type ReplaceKey<T, K extends string, R> = T extends Record<K, unknown> ? Omit<T, K> & Record<K, R> : T
// Check and replace object values
type DeepReplaceHelper<T, K extends string, R, ReplacedT = ReplaceKey<T, K, R>> = {
[Key in keyof ReplacedT]: ReplacedT[Key] extends Primitive ? ReplacedT[Key] : ReplacedT[Key] extends unknown[] ? DeepReplace<ReplacedT[Key][number], K, R>[] : DeepReplace<ReplacedT[Key], K, R>
}
// T = object, K = key to replace, R = replacement value
type DeepReplace<T, K extends string, R> = T extends Primitive ? T : DeepReplaceHelper<T, K, R>
// Define new type for "user" key
interface UserReplacement {
id: string
name: string
}
type UserFilled<T> = DeepReplace<T, "user", UserReplacement>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.