If i write the following type
type myType<T> = {
[K in keyof T]?: T[K] extends ({[k:string]: any} | undefined) ? T[K] : 0
}
when T[K]
is an array of any type, myType behaves as if T[K] extends ({[k:string]:any)|undefined)
was true even if any[]
is not a {[k:string]:any}
. So when i try to use this type like this i get an error:
declare class obj {
a?: string
b?: any[] // <-- if this gets changed to a primitive there is no more error
c?: {
d: number
}
}
const a: myType<obj> = {
a: 0,
b: 0, // <-- this gives an error
c: {
d: 1
}
}
The problem is that Array<any>
(number[]
, string[]
...) actually extends the type Object.
That is why any[]
checks as {[k:string]: any}
.
To solve that, you should validate specifically for array, before validating for {[k:string]: any}
.
It would be something like:
type myType<T> = {
[K in keyof T]?: T[K] extends (Array<any> | undefined) ? 0 : (T[K] extends ({ [k: string]: any } | undefined) ? T[K] : 0)
}
| undefined
can be removed if your array property is not optional.
But as you can see you need to nest 2 conditionals.
So instead of checking for a generic object { [k: string]: any }
, I would recommend you create another type, so you could validate using your custom type.
Otherwise, you might have more validation problems if you add other properties that are also objects.