You can use built in NonNullable util
type MyType = {
foo: {
bar: [1, 2, 4] | null
} | null
}
type GetNullable<T, Prop extends keyof NonNullable<T>> = NonNullable<T>[Prop]
// [1, 2, 4] | null
type NestedData = GetNullable<MyType['foo'], 'bar'>
Playground
OR
type Truthy<T> = NonNullable<T>
type GetData = Truthy<Truthy<MyType['foo']>>['bar']
If you need more sophisticated util, please see this example last row and related answer
type Structure = {
user: {
tuple: [42],
emptyTuple: [],
array: { age: number }[]|null
}
}
type Values<T> = T[keyof T]
type IsNever<T> = [T] extends [never] ? true : false;
type IsTuple<T> =
(T extends Array<any> ?
(T['length'] extends number
? (number extends T['length']
? false
: true)
: true)
: false)
type IsEmptyTuple<T extends Array<any>> = T['length'] extends 0 ? true : false
type HandleDot<
Cache extends string,
Prop extends string | number
> =
Cache extends ''
? `${Prop}`
: `${Cache}.${Prop}`
type HandleObject<Obj, Cache extends string> = {
[Prop in keyof Obj]:
| HandleDot<Cache, Prop & string>
| Path<Obj[Prop], HandleDot<Cache, Prop & string>>
}[keyof Obj]
type Path<Obj, Cache extends string = ''> =
(Obj extends PropertyKey
? Cache
: (Obj extends Array<unknown>
? (IsTuple<Obj> extends true
? (IsEmptyTuple<Obj> extends true
? Path<PropertyKey, HandleDot<Cache, -1>>
: HandleObject<Obj, Cache>)
: Path<Obj[number], HandleDot<Cache, number>>)
: HandleObject<Obj, Cache>)
)
type WithDot<T extends string> = T extends `${string}.${string}` ? T : never
type Acc = Record<string, any>
type ReducerCallback<Accumulator extends Acc, El extends string> =
El extends keyof Accumulator ? Accumulator[El] : El extends '-1' ? never : Accumulator
type Reducer<
Keys extends string,
Accumulator extends Acc = {}
> =
Keys extends `${infer Prop}.${infer Rest}`
? Reducer<Rest, ReducerCallback<Accumulator, Prop>>
: Keys extends `${infer Last}`
? ReducerCallback<Accumulator, Last>
: never
type BlackMagic<T> = T & {
[Prop in WithDot<Extract<Path<Structure>, string>>]: Reducer<Prop, T>
}
type Result = Reducer<'user.array', Structure>
Playground