typescript - Combinarea DeepPartial/DeepMerge/Limitarea genericului
Încerc să creez un generic destul de complicat. Am pus multe întrebări pe StackOverflow pentru a încerca să asamblez ceea ce vreau, așa că m-am gândit să explic pur și simplu ce caut.
Având o interfață:
type Person = {
name: string,
age: number,
address: {
line1: string,
line2: string | null | number,
zip: string | number,
address: {
line1: string,
line2: string | null | number,
zip: string | number,
} | string,
},
};
Caut o modalitate de a putea crea o altă interfață pornind de la această interfață, care să limiteze o parte din domeniul său de aplicare, păstrând în același timp o parte din acesta.
Exemple
De exemplu, mi-ar plăcea să am capacitatea de a
- limitează
Person.address.addressla doar un șir
type PersonEdit = {
address: {
address: string,
},
};
- limitează
Person.address.addressdoar la un obiect
type PersonEdit = {
address: {
address: {},
},
};
- schimbați orice proprietate în opțional,
type PersonEdit = {
address: {
address?: {} | string,
},
};
- limitează
Person.address.address.zipla doar un număr
type PersonEdit = {
address: {
address: {
zip: number
},
},
};
Cerințe
- Mi-ar plăcea să pot să mă concentrez doar pe proprietatea imbricată și să moștenesc toate celelalte tipuri din restul interfeței.
- Aceste
Editsar trebui să fie unDeepPartial<>al sursei și să nu permită proprietăți noi sau uniuni care nu se află în părinte.
Generice existente
Iată ce au reușit să mă ajute să găsesc cei minunați de pe StackOverflow până acum din alte întrebări pe care le-am pus.
type Confine<A, B extends { [K in keyof B]: K extends keyof A ? A[K] : never }> = B;
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends (infer U)[]
? DeepPartial<U>[]
: T[P] extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: DeepPartial<T[P]>
};
type DeepMerge<T, U> = T extends any ? U extends any ?
[T, U] extends [object, object] ?
{
[K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
K extends keyof U ? (
K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
) : (
K extends keyof T ? T[K] : never
)
)
} : U : never : never;
Actualizare
type DeepMerge<T, U> = T extends any ? U extends DeepPartial<T> ?
[T, U] extends [object, object] ?
{
[K in keyof (U & Pick<T, Exclude<keyof T, keyof U>>)]: (
K extends keyof U ? (
K extends keyof T ? DeepMerge<T[K], U[K]> : U[K]
) : (
K extends keyof T ? T[K] : never
)
)
} : U : never : never;
Acest lucru funcționează bine, dar nu limitează U să nu adauge proprietăți noi.