我創建了一個型別,使所有可為空的屬性都是可選的,甚至是嵌套的,但由于某種原因,當給定另一個型別的陣列時它不起作用。
這很奇怪,因為它在陣列在父型別中“展開”時起作用。這是我的型別:
// returns null if T is nullable
type ExtractNull<T> = Extract<T, null> extends null
? Extract<T, null> extends never
? T
: null
: T
// returns an union type of all nullable keys in T
type NullKeys<T extends Record<PropertyKey, any>> = {
[K in keyof T]: ExtractNull<T[K]> extends null
? K
: T[K] extends Record<PropertyKey, any>
? NullKeys<T[K]>
: never
}[keyof T]
// makes all nullable properties optional
export type OptionalNulls<T extends Record<PropertyKey, any>> = {
[K in keyof T as Exclude<K, NullKeys<T>>]: T[K] extends Record<
PropertyKey,
any
>
? OptionalNulls<T[K]>
: T[K]
} & Partial<{
[K in keyof T as Extract<K, NullKeys<T>>]: T[K]
}>
這是我的測驗設定("not optional"
字串應該是可選的):
type TestRoot = {
prop0: null | string
testObj: TestObj
testObjArray: TestObj[]
testObjArrayUnwrapped: [
{
prop1: null | string
arr: [
{
prop2: null | string
}
]
}
]
}
type TestObj = {
prop1: null | string
arr: [
{
prop2: null | string
}
]
}
const test: OptionalNulls<TestRoot> = {
prop0: "optional",
testObj: {
prop1: "optional",
arr: [{ prop2: "optional" }],
},
testObjArray: [{ prop1: "not optional", arr: [{ prop2: "not optional" }] }],
testObjArrayUnwrapped: [
{
prop1: "optional",
arr: [
{
prop2: "optional",
},
],
},
],
}
uj5u.com熱心網友回復:
我讓它通過兩個小的修改作業:
您定義的NullKeys
型別與元組中斷。為了讓它正常作業,我添加了一個小改動。
type NullKeys<T extends Record<PropertyKey, any>> = {
[K in keyof T]: ExtractNull<T[K]> extends null
? K
: T[K] extends Record<PropertyKey, any>
? NullKeys<T[K]>
: never
}[keyof T & (T extends any[] ? `${bigint}` : string)] // <-- filter unwanted props
這將阻止 TypeScript 使用所有陣列屬性,如length
索引此型別的迭代器。
type T0 = NullKeys<TestRoot>
// before:
// type T0 = number | "prop0" | "prop1" | "prop2" | (() => IterableIterator<"prop2">) | // (() => {
// copyWithin: boolean;
// entries: boolean;
// fill: boolean;
// find: boolean;
// findIndex: boolean;
// keys: boolean;
// values: boolean;
// }) | ... 90 more ... |
// after:
// type T0 = "prop0" | "prop1" | "prop2"
TypeScript 現在會抱怨:型別實體化太深并且可能是無限的。但是我們可以通過這個簡單的技巧輕松地使編譯器靜音:
export type OptionalNulls<T extends Record<PropertyKey, any>> = {
[K in keyof T as Exclude<K, NullKeys<T>>]: T[K] extends Record<
PropertyKey,
any
>
? OptionalNulls<T[K]>
: T[K]
} & Partial<{
[K in keyof T as NullKeys<T> extends infer O ? Extract<K, O> : never]: T[K] // <-- silence compiler warning
}>
操場
但是我認為您使問題過于復雜了。這是一個更簡單的解決方案:
type OptionalNulls<T> = {
[K in keyof T as null extends T[K] ? K : never]?: T[K] extends object
? OptionalNulls<T[K]>
: T[K]
} & {
[K in keyof T as null extends T[K] ? never : K]: T[K] extends object
? OptionalNulls<T[K]>
: T[K]
}
操場
uj5u.com熱心網友回復:
我找到了這個解決方案,但@Tobias S. 一個更好
// returns null if T is nullable
type ExtractNull<T> = Extract<T, null> extends null
? Extract<T, null> extends never
? T
: null
: T
// returns an union type of all nullable keys in T
type NullableKeys<T extends Record<PropertyKey, any>> = {
[K in keyof T]: ExtractNull<T[K]> extends null
? K
: T[K] extends Record<PropertyKey, any>
? NullableKeys<T[K]>
: never
}[keyof T]
// makes all nullable properties optional
export type OptionalNullable<T> = T extends Array<infer I>
? I extends ObjectRecord
? ({
[K in keyof I as Exclude<
K,
NullableKeys<I>
>]: I[K] extends Array<any> ? OptionalNullable<I[K]> : I[K]
} & Partial<{
[K in keyof I as Extract<K, NullableKeys<I>>]: I[K]
}>)[]
: I[]
: T extends ObjectRecord
? {
[K in keyof T as Exclude<
K,
NullableKeys<T>
>]: T[K] extends Array<any> ? OptionalNullable<T[K]> : T[K]
} & Partial<{
[K in keyof T as Extract<K, NullableKeys<T>>]: T[K]
}>
: never
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/486349.html
上一篇:非二叉樹python中的順序