我使用 Graphql codegen 从我们的模式生成类型。我需要访问嵌套类型并常用以下方法:
type Iresponse = myType[level1][level2]
当没有 Maybes 时,这很有效,这意味着它有可能为空。当类型被定义为“可能”时,我无法使用它并且它会引发错误。
有没有人有一个实用的解决方案来指定这些嵌套类型?我不想将每一步都包装在许多非可空泛型中......
先感谢您 !
我使用 Graphql codegen 从我们的模式生成类型。我需要访问嵌套类型并常用以下方法:
type Iresponse = myType[level1][level2]
当没有 Maybes 时,这很有效,这意味着它有可能为空。当类型被定义为“可能”时,我无法使用它并且它会引发错误。
有没有人有一个实用的解决方案来指定这些嵌套类型?我不想将每一步都包装在许多非可空泛型中......
先感谢您 !
任意深度:
type Get<T, X> = X extends keyof T ? T[X] : never
type Path<T, P extends any[]> = P extends [infer X, ...infer Y] ? Path<Get<NonNullable<T>, X>, Y> : T
type Iresponse = Path<myType, ["level1", "level2", "response"]>
您可以使用内置的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'>
或者
type Truthy<T> = NonNullable<T>
type GetData = Truthy<Truthy<MyType['foo']>>['bar']
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>
谢谢你们的回答,他们真的很有帮助!
我最终做的是在 graphql 生成器中使用“typescript-compatibility”。它添加了也可能为 null 的类型和子类型。基本上它所做的只是将所有嵌套类型包装在 NonNullable 类型中。