TypeScript - ta bort alla egenskaper med en viss typ
Jag har en type som används för att projicera nycklar som finns i T till de gemensamma nycklarna och deras typer som finns i U:
type IntersectByCommonKey<T, U, V = any> = {
[K in keyof U]: K extends keyof T ?
T[K] extends V ?
U[K]
: T[K] extends object ?
IntersectByCommonKey<T[K], U[K], V>
: T[K] extends object | undefined ?
IntersectByCommonKey<T[K], U[K], V> | undefined
: never
: never
};
IntersectByCommonKey Playground-länk
där för varje nyckel K i U, om T har samma nyckel K, och om typen vid K extends V, inkluderar formen för den nyckeln, annars never.
Med typen som returneras av IntersectByCommonKey vill jag ta bort varje nyckel som har typen never, vilket betyder att det måste klara av inbäddade Record-strukturer också.
Det är tillräckligt enkelt att ta bort toppnivånycklar:
type ExcludeKeysWithTypeOf<T, V> = {
[K in keyof T]: Exclude<T[K], undefined> extends V ? never : K
}[keyof T]
type Without<T, V> = Pick<T, ExcludeKeysWithTypeOf<T, V>>;
ExkluderaNycklarMedTypAv Playground-länk
Jag har dock svårt att uppnå samma resultat för nästlade Records. Finns det ett sätt att rekursivt ta bort nycklar med typer av never?
Svar #1
Vi behöver göra ett rekursivt anrop för att gå in i nästlade typrekord. Här är ett exempel på en lösning:
type Without<T, V, WithNevers = {
[K in keyof T]: Exclude<T[K], undefined> extends V ? never
: (T[K] extends Record<string, unknown> ? Without<T[K], V> : T[K])
}> = Pick<WithNevers, {
[K in keyof WithNevers]: WithNevers[K] extends never ? never : K
}[keyof WithNevers]>
Huvudidén är att när vår T[K] kommer att ha typen Record, så kommer den rekursivt att anropa sig själv igen (Without typnivåfunktion). Hela typen kommer att reduceras till önskad form där varje nästlad objekt har de nycklar vi ville ta bort.
Hela kodsnutten - lekplatsen
Observera: Jag flyttade beräkningen av WithNevers inuti argumentlistan för typen för att uppnå bättre läsbarhet. Vi kan också definiera den som en separat typ.
