Причина, по которой это не удается, заключается в том, что в strictNullChecks
необязательные поля имеют тип OriginalType | undefined
. Доступны только общие члены объединения, и, поскольку undefined
не имеет членов, это приводит к never
.
Если вы наберете obj как obj: O | undefined | null
, это вытянет null
из O
function prop<O, K extends keyof O>(obj: O | undefined | null, key: K): O[K] | undefined | null {
return obj && obj[key]
}
let x = prop(test, 'one') // number | null | undefined
let y = prop(test.two, 'n') // number | null | undefined
Или версия, которая не вводит null
и undefined
без необходимости:
interface Test {
one?: number,
two?: {
n: number
}
req: {
n: number
}
}
const test: Test = {
one: 1,
two: { n: 2 },
req: { n: 2 }
}
function prop<O, K extends keyof Exclude<O, undefined | null>>(obj: O, key: K): Extract<O, undefined | null> | Exclude<O, undefined | null>[K]
function prop<K extends PropertyKey, V>(obj: Record<K, undefined | null | V>, key: K): V | undefined | null {
return obj && obj[key]
}
let x = prop(test, 'one') // number | undefined
let y = prop(test.two, 'n') // number | undefined
let z = prop(test.req, 'n') // number