Big thanks to @jcalz, whose answer set me on the right path!
I was getting some strange behavior when arrays are involved. I think what was happening is that the resulting type was including a union of array properties. This could be what @jcalz was referring to when they said:
\> you will probably have some use cases where this definition does things you don't expect or like.
Here's an example of the array index / property issue I was facing:
result:
albumMedias: number | ShareAlbum_shared_album_album_medias_cursor_album_medias[] | (() => ArrayIterator<never>) | ... 38 more ... | ((index: number, value: never) => never[])
I modified the solution to properly handle arrays without including all the Array properties.
type GetDeepProp<T, K extends string> =
K extends keyof T
? T[K]
: T extends Array<infer U>
? GetDeepProp<U, K>
: T extends object
? {
[P in keyof T]:
P extends string
? GetDeepProp<T[P], K>
: never
}[keyof T]
: never
Thanks @jcalz!