typescript - Cum să elimini cheile de tip `never`?
Am creat acest tip de utilitate numit Override pe care îl consider destul de util, dar un lucru care m-a deranjat este că nu este foarte convenabil să elimini complet proprietățile remove.
În exemplul de mai jos, vreau ca Bar să păstreze a din Foo, să suprascrie b pentru a fi un string în loc de un number și să elimine c. Totuși, c rămâne, doar că este tipizat ca never. Cum pot să elimin toate valorile de tip never în schimb?
type Override<A, B> = Omit<A, keyof B> & B
type Foo = {
a: string
b: number
c: boolean
}
type Bar = Override<Foo, {
b: string
c: never
}>
function f(bar: Bar) {
console.log(bar.c)
}
Teren de joacă
Răspuns #1
În loc de & B, poți să faci intersecția cu o mapare a unui tip de obiect nou din care au fost eliminate valorile never.
type Override<A, B> = Omit<A, keyof B> & {
[K in keyof B as B[K] extends never ? never : K]: B[K]
}
Acest lucru poate fi extins pentru a elimina orice tip de valoare doriți.
type Override<A, B> = Omit<A, keyof B> & {
[K in keyof B as B[K] extends never | void ? never : K]: B[K]
}
Răspunsul #2
am găsit o problemă similară https://github.com/microsoft/TypeScript/issues/23199
type Override<A, B> = Omit<A, keyof B> & B
type Foo = {
a: string
b: number
c: boolean
}
type FilteredKeys<T> = {
// this does not work
// [K in keyof T]: K
// this do
[K in keyof T]: T[K] extends never ? never : K
}[keyof T]
type RemoveNever<T> = {
[K in FilteredKeys<T>]: T[K]
}
type Bar = RemoveNever<
Override<
Foo,
{
b: string
c: never
d: number
}
>
>
function f(bar: Bar) {
console.log(bar.a)
console.log(bar.b)
console.log(bar.c)
console.log(bar.d)
}
Apropo, credem că aceste două forme sunt aceleași, dar tsc nu crede
[K in keyof T]: K[K in keyof T]: T[K] extends never ? never : K
