英文:
Spreading tuples and also applying optional attributes
问题
以下是修改后的代码:
type ArrayBuilder<
T extends Def[],
A extends any[] = [],
B extends any[] = [],
C extends any[] = [],
State extends 'A' | 'B' = 'A',
> = T extends [
infer H extends Def,
...infer R extends Def[],
] ? State extends 'A' ? H['spread'] extends true ? ArrayBuilder<R, A, H['optional'] extends true ? [boolean] : [], [...A, H['type']], 'B'> : ArrayBuilder<R, [...A, H['type']], [], [], 'A'>
: ArrayBuilder<R, A, H['optional'] extends true ? [boolean] : [], [...C, H['type']], 'B'>
: [...A, ...B, ...C]
type Test2 = ArrayBuilder<[A, B, C]> // [string, boolean?, ...string[]]
通过在适当的位置添加条件来检查 optional
字段,我们可以实现 Test2
产生 [string, boolean?, ...string[]]
的结果。这里的条件检查将在需要时将 boolean
类型添加到类型数组中。
英文:
Can the code below be modified, such that Test2
produces: [string, boolean?, ...string[]]
by factoring in the optional field?
type Def = { type: any, spread: boolean, optional: boolean }
type A = { type: string, spread: false, optional: false }
type B = { type: boolean, spread: false, optional: true }
type C = { type: string[], spread: true, optional: false }
type D = { type: number, spread: false, optional: false }
type ArrayBuilder<
T extends Def[],
A extends any[] = [],
B extends any[] = [],
C extends any[] = [],
State extends 'A' | 'B' = 'A',
> = T extends [
infer H extends Def,
...infer R extends Def[],
] ? State extends 'A' ? H['spread'] extends true ? ArrayBuilder<R, A, H['type'], [], 'B'> : ArrayBuilder<R, [...A, H['type']], [], [], 'A'>
:ArrayBuilder<R, A, B, [...C, H['type']], 'B'>
: [...A, ...B, ...C]
type Test1 = ArrayBuilder<[A,C,D]> // [string, ...string[], number]
// Can the code above be modified, such that Test2 produces: [string, boolean?, ...string[]] by factoring in the optional field?
type Test2 = ArrayBuilder<[A,B,C]> // [string, boolean, ...string[]] - should become [string, boolean?, ...string[]]
To apply the spread, I'm doing [...A,...ItemToSpread]
, but to apply the optional attribute I must do {[I in keyof T]?: T[I] }
- which doesn't play nice with spreads.
答案1
得分: 2
正如你检查H["spread"]
一样,你可以在将H["type"]
传递给ArrayBuilder
之前检查H["optional"]
:
type ArrayBuilder<
T extends Def[],
A extends any[] = [],
B extends any[] = [],
C extends any[] = [],
State extends "A" | "B" = "A"
> = T extends [infer H extends Def, ...infer R extends Def[]]
? State extends "A"
? H["spread"] extends true
? ArrayBuilder<R, A, H["type"], [], "B">
: H["optional"] extends true ? ArrayBuilder<R, [...A, H["type"]?], [], [], "A"> : ArrayBuilder<R, [...A, H["type"]], [], [], "A">
: H["optional"] extends true ? ArrayBuilder<R, A, B, [...C, H["type"]?], "B"> : ArrayBuilder<R, A, B, [...C, H["type"]], "B">
: [...A, ...B, ...C];
如果你启用了exactOptionalPropertyTypes
,你将获得Test2
的期望结果:
type Test2 = ArrayBuilder<[A, B, C]>; // [string, boolean?, ...string[]]
英文:
Just as you check for H["spread"]
, you can check for H["optional"]
before passing H["type"]
to ArrayBuilder
:
type ArrayBuilder<
T extends Def[],
A extends any[] = [],
B extends any[] = [],
C extends any[] = [],
State extends "A" | "B" = "A"
> = T extends [infer H extends Def, ...infer R extends Def[]]
? State extends "A"
? H["spread"] extends true
? ArrayBuilder<R, A, H["type"], [], "B">
: H["optional"] extends true ? ArrayBuilder<R, [...A, H["type"]?], [], [], "A"> : ArrayBuilder<R, [...A, H["type"]], [], [], "A">
: H["optional"] extends true ? ArrayBuilder<R, A, B, [...C, H["type"]?], "B"> : ArrayBuilder<R, A, B, [...C, H["type"]], "B">
: [...A, ...B, ...C];
and if you have exactOptionalPropertyTypes
enabled, you will get the desired result for Test2
:
type Test2 = ArrayBuilder<[A, B, C]>; // [string, boolean?, ...string[]]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论