打字稿选择可选的未设置变量
Typescript Pick optionnal unset variable
我正在尝试使用打字稿的“选择”功能来获取我的对象的所有可能值。
我的对象具有可选属性,因此不一定要设置它们
const foo = [
{
name: 'index',
},
{
name: 'id',
type: 'number',
},
{
name: 'error',
},
] as const
type ElementArg<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType>
? Pick<ElementType, 'name' | 'type'>
: never
type result = ElementArg<typeof foo>
//result : {name: "index" | "id" | "error"}
//expected : {name: "index" | "id" | "error" type: "number" | "undefined"}
而且我还尝试将“类型”属性转换为具有以下类型的类型:
type typeDecoder<T> = T extends 'number' ? number
: T extends 'number[]' ? number[]
: T extends 'string' ? string
: T extends 'string[]' ? string[]
: T extends 'boolean' ? boolean
: T extends 'undefined' ? undefined
: never;
但我认为有更好的方法,但我不知道在哪里使用我的函数
我设法让一些东西起作用:
type ElementArg<T extends ReadonlyArray<unknown>, R extends {} = {}> = T extends readonly [infer First, ...infer Rest]
? ElementArg<Rest, {
[K in keyof First | keyof R]:
K extends keyof R
? K extends keyof First
? R[K] | First[K]
: R[K] | "undefined"
: K extends keyof First
? First[K]
: never
}>
: R;
主要思想是循环遍历元组中的每个元素,然后将其添加到我们累积的结果中。
T extends readonly [infer First, ...infer Rest]
这里我们得到第一个元素,其余元素作为一个元组。接下来是这个大块:
ElementArg<Rest, {
[K in keyof First | keyof R]:
K extends keyof R
? K extends keyof First
? R[K] | First[K]
: R[K] | "undefined"
: K extends keyof First
? First[K]
: never
}>
我们对其余元素再次使用 ElementArg
,然后 long 复杂映射类型正确地将此元素的内容添加到结果中。
逻辑是这样的:
对于元素或结果中的每个键
如果key是结果的key
如果键是元素的键
- 将键的值添加到结果中
否则
- 将
"undefined"
添加到结果
否则如果键是元素的键
- 这是我们添加到结果中的新键
最后,如果我们尝试获取第一个元素的第一步不起作用,这意味着 T
为空并且我们完成了,所以我们 return R
。
我正在尝试使用打字稿的“选择”功能来获取我的对象的所有可能值。 我的对象具有可选属性,因此不一定要设置它们
const foo = [
{
name: 'index',
},
{
name: 'id',
type: 'number',
},
{
name: 'error',
},
] as const
type ElementArg<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType>
? Pick<ElementType, 'name' | 'type'>
: never
type result = ElementArg<typeof foo>
//result : {name: "index" | "id" | "error"}
//expected : {name: "index" | "id" | "error" type: "number" | "undefined"}
而且我还尝试将“类型”属性转换为具有以下类型的类型:
type typeDecoder<T> = T extends 'number' ? number
: T extends 'number[]' ? number[]
: T extends 'string' ? string
: T extends 'string[]' ? string[]
: T extends 'boolean' ? boolean
: T extends 'undefined' ? undefined
: never;
但我认为有更好的方法,但我不知道在哪里使用我的函数
我设法让一些东西起作用:
type ElementArg<T extends ReadonlyArray<unknown>, R extends {} = {}> = T extends readonly [infer First, ...infer Rest]
? ElementArg<Rest, {
[K in keyof First | keyof R]:
K extends keyof R
? K extends keyof First
? R[K] | First[K]
: R[K] | "undefined"
: K extends keyof First
? First[K]
: never
}>
: R;
主要思想是循环遍历元组中的每个元素,然后将其添加到我们累积的结果中。
T extends readonly [infer First, ...infer Rest]
这里我们得到第一个元素,其余元素作为一个元组。接下来是这个大块:
ElementArg<Rest, {
[K in keyof First | keyof R]:
K extends keyof R
? K extends keyof First
? R[K] | First[K]
: R[K] | "undefined"
: K extends keyof First
? First[K]
: never
}>
我们对其余元素再次使用 ElementArg
,然后 long 复杂映射类型正确地将此元素的内容添加到结果中。
逻辑是这样的:
对于元素或结果中的每个键
如果key是结果的key
如果键是元素的键
- 将键的值添加到结果中
否则
- 将
"undefined"
添加到结果
- 将
否则如果键是元素的键
- 这是我们添加到结果中的新键
最后,如果我们尝试获取第一个元素的第一步不起作用,这意味着 T
为空并且我们完成了,所以我们 return R
。