我正在嘗試創建一個通用型別,該型別將使用模板文字映射鍵。一般來說,我只想從逗號分隔的鍵串列中創建一個嵌套型別:
type TFoobar = "address" | "year" | "owner.age" | "owner.address.street";
const foobar: DotToType<TFooBar> = {
address: true,
owner: {
age: true,
address: {
street: true
}
}
}
我試過像這樣實作它:
type DotToType<keys extends string> = {
[Key in keys]: Key extends `${infer Parent}.${infer Leaf}`
? {[key in Parent]: DotToType<Leaf>}
: {[k in Key]: boolean}
}[keys];
雖然它確實具有正確的型別,但它使屬性成為可選的(至少需要一個,但沒有任何東西可以強制它們都存在)
const foobar: DotToType<TFooBar> = {
address: true,
}; //valid, shouldnt be
const foobar: DotToType<TFooBar> = {
owner: {
age: true
},
}; //valid, shouldnt be
const foobar: DotToType<TFooBar> = {
address: true,
year: false,
owner: {
age: true,
address: {
street: true
}
}
}; //valid
我也試過這樣做:
type DotToType<keys extends string> = {
[Key in keys as Key extends `${infer Parent}.${infer Leaf}` ? Parent : Key]:
Key extends `${infer Parent}.${infer Leaf}` ? DotToType<Leaf> : boolean
};
雖然它確實強制執行欄位,但如果我對同一個物件有多個路徑,它就會停止作業。
const foobar: DotToType<"address" | "year" | "owner.address.street"> = {
"address": true,
"year": true,
owner: {
address: {
street: true
}
}
}; // this works fine
const foobar: DotToType<"address" | "year" | "owner.address.street" | "owner.age"> = {
"address": true,
"year": true,
owner: {
address: {
street: true
}
}
}; // this only allows the first `owner.{Leaf}`
uj5u.com熱心網友回復:
您的初始代碼會生成一個聯合,這就是屬性是可選的原因:
type DotToType<keys extends string> = {
[Key in keys]: Key extends `${infer Parent}.${infer Leaf}`
? {[key in Parent]: DotToType<Leaf>}
: {[k in Key]: boolean}
}[keys];
type MyType = DotToType<TFoobar>
// produces:
type MyType = {
address: boolean;
} | {
year: boolean;
} | {
owner: {
age: boolean;
};
} | {
owner: {
address: {
street: boolean;
};
};
}
您可以使用以下內容:
type TFoobar = "address" | "year" | "owner.age" | "owner.address.street";
type BeforeDot<K extends string> = K extends `${infer Parent}.${infer _}` ? Parent : K;
type ChildrenAfterDot<K extends string, P extends string> = K extends `${P}.${infer $Leaf}` ? $Leaf : never;
type DotToType<keys extends string> = {
[Key in BeforeDot<keys>]: Key extends keys
? boolean
: DotToType<ChildrenAfterDot<keys, Key>>
};
type MyType = DotToType<TFoobar>
// produces:
type MyType = {
address: boolean;
year: boolean;
owner: DotToType<"age" | "address.street">;
}
游樂場鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/481454.html
