为什么 Exclude 实用程序类型无法与 TypeScript 中枚举上的映射条件类型结合使用?
Why is the Exclude utility type not working as expected in combination with mapped conditional types on enums in TypeScript?
只是为了提供一点上下文:我正在构建一个非常复杂的表单,其中包含条件所需的值,这些值取决于之前输入中选择的内容。
因此,我创建了以下对象来指示是否需要输入:
enum IssueType {
Error = "Error",
Advice = "Advice",
}
enum Category {
Software = "Software",
Hardware = "Hardware",
Other = "Other",
}
const inputNames = {
issueType: "issueType",
concerning: "concerning",
serialNumber: "serialNumber",
errorCode: "errorCode",
} as const;
const conditions: Conditions = {
[IssueType.Error]: {
~~~~~~~~~~~~~~~> Property 'Other' is missing in type ...
[Category.Software]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
},
[Category.Hardware]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
}
},
[IssueType.Advice]: {
[Category.Software]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
},
[Category.Hardware]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
},
[Category.Other]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
}
}
};
现在我的问题是 conditions
的类型(上面代码段中的 Conditions
)是什么样的。我试过这个:
type Conditions = {
[K in IssueType]: {
[K in IssueType extends IssueType.Error
? Exclude<Category, Category.Other>
: Category]: {
[K in Exclude<
keyof typeof inputNames,
typeof inputNames.issueType
>]: boolean;
};
};
};
但是 Category.Other
的 Exclude
不起作用。如果它的父对象键的类型为 IssueType.Error
,则它应该只是强制性的 属性。我在这里做错了什么?
我也想避免(如果可能的话)Nullable Types 例如:
type Conditions = {
[K in IssueType]: {
[K in Category]?: {
[K in Exclude<
keyof typeof inputNames,
typeof inputNames.issueType
>]: boolean;
};
};
};
在对象的第二层,您应该引用 K
(从上一层)而不是 IssueType
。为此,您不能将所有级别的密钥类型命名为 K
。
为了清楚起见,我将 K
重命名为 A
、B
和 C
:
type Conditions = {
[A in IssueType]: {
[B in A extends IssueType.Error
? Exclude<Category, Category.Other>
: Category]: {
[C in Exclude<
keyof typeof inputNames,
typeof inputNames.issueType
>]: boolean;
};
};
};
检查playground。
只是为了提供一点上下文:我正在构建一个非常复杂的表单,其中包含条件所需的值,这些值取决于之前输入中选择的内容。
因此,我创建了以下对象来指示是否需要输入:
enum IssueType {
Error = "Error",
Advice = "Advice",
}
enum Category {
Software = "Software",
Hardware = "Hardware",
Other = "Other",
}
const inputNames = {
issueType: "issueType",
concerning: "concerning",
serialNumber: "serialNumber",
errorCode: "errorCode",
} as const;
const conditions: Conditions = {
[IssueType.Error]: {
~~~~~~~~~~~~~~~> Property 'Other' is missing in type ...
[Category.Software]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
},
[Category.Hardware]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
}
},
[IssueType.Advice]: {
[Category.Software]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
},
[Category.Hardware]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
},
[Category.Other]: {
[inputNames.concerning]: true,
[inputNames.serialNumber]: true,
[inputNames.errorCode]: true,
}
}
};
现在我的问题是 conditions
的类型(上面代码段中的 Conditions
)是什么样的。我试过这个:
type Conditions = {
[K in IssueType]: {
[K in IssueType extends IssueType.Error
? Exclude<Category, Category.Other>
: Category]: {
[K in Exclude<
keyof typeof inputNames,
typeof inputNames.issueType
>]: boolean;
};
};
};
但是 Category.Other
的 Exclude
不起作用。如果它的父对象键的类型为 IssueType.Error
,则它应该只是强制性的 属性。我在这里做错了什么?
我也想避免(如果可能的话)Nullable Types 例如:
type Conditions = {
[K in IssueType]: {
[K in Category]?: {
[K in Exclude<
keyof typeof inputNames,
typeof inputNames.issueType
>]: boolean;
};
};
};
在对象的第二层,您应该引用 K
(从上一层)而不是 IssueType
。为此,您不能将所有级别的密钥类型命名为 K
。
为了清楚起见,我将 K
重命名为 A
、B
和 C
:
type Conditions = {
[A in IssueType]: {
[B in A extends IssueType.Error
? Exclude<Category, Category.Other>
: Category]: {
[C in Exclude<
keyof typeof inputNames,
typeof inputNames.issueType
>]: boolean;
};
};
};
检查playground。