typescript - 如何使用嵌套接口限定 TypeScript 泛型类型
问题描述
我正在尝试为接受三个参数的函数创建一个通用接口。填写第一个参数时,第二个的选项应该在第一个的范围内。第三个参数应该在第二个参数的范围内。
我当前的代码如下所示:
type SettingActionCreator<T> = <
L extends T,
K extends keyof L,
C extends keyof L[K]
>(
type: K,
settingKey: keyof L[K],
settingValue: L[K][C]
)
export interface SomeSettings {
[Type.TypeA]: {
settingA: "value1" | "value2";
settingB: "value3 | "value4";
};
[Type.TypeB]: {
...
};
[Type.TypeC]: {
...
};
}
const setSomeSetting: SettingActionCreator<SomeSettings> = (
type,
settingKey,
settingValue
) =>
// do something
所以当我想setSomeSetting
用参数调用时,我希望我的范围对于我传递给它的每个参数都会变小。
例如,如果我填写第一个参数,那么 SettingActionCreator 会确保第二个参数 ( settingKey
) 只能是settingA
or settingB
。到目前为止,一切都按预期工作。
setSomeSetting(Type.TypeA, ....) // <-- settingKey accepts "settingA" and "settingB"
但是对于第三个论点,我似乎无法解决它。当我设置第一个参数和第二个参数时,我希望第三个参数只接受所选settingKey
参数中的联合选项。但不是那样,我在Type.TypeA
. 所以settingValuessettingA
和settingB
使用此代码:
setSomeSetting(Type.TypeA, "settingA", "value3") // <-- settingValue should only accept "value1" or "value2"
我预计会出现如下错误:
TS2345: Argument of type '"value3"' is not assignable to parameter of type `"value1" | "value2"
但相反,我没有收到类型错误,因为它同时接受 和 的settingA
值settingB
。
有人对我做错了什么有建议吗?
解决方案
您需要向 TypeScript 证明 thesettingKey
与settingValue
-settingKey: keyof L[K]
您的声明中的 - 混淆它(我不知道为什么 -感觉就像一个错误type C extends keyof L[K] != keyof L[K]
,但它绝对是类型推断代码的限制)。
将该参数的类型更改为settingKey: C
,TypeScript 将能够理解三个参数之间的关系:
type SettingActionCreator<T> = <
L extends T,
K extends keyof L,
C extends keyof L[K]
>(
type: K,
settingKey: C, // <-- changed from keyof L[K]
settingValue: L[K][C]
) => void;
declare const Type: {
readonly TypeA: unique symbol,
readonly TypeB: unique symbol,
readonly TypeC: unique symbol
}
export interface SomeSettings {
[Type.TypeA]: {
settingA1: "valueA1" | "valueA2";
settingA2: "valueA3" | "valueA4";
},
[Type.TypeB]: {
settingB1: "valueB1" | "valueB2",
settingB2: "valueB3" | "valueB4"
},
[Type.TypeC]: {
//
}
}
const setSomeSetting: SettingActionCreator<SomeSettings> = (
type,
settingKey,
settingValue
) => {}
这会导致您正在寻找的错误类型:
setSomeSetting(Type.TypeB, "settingB1", "valueA3")
// Argument of type '"valueA3"' is not assignable to parameter of type '"valueB1" | "valueB2"'.
推荐阅读
- php - Shell_exec 不执行 php 文件
- c++ - 访问嵌套的 ROS 消息
- keras - keras-vis 可视化显着性问题
- mysql - Sensenet:是否支持Mysql
- python - 在tensorflow python中替换值或创建张量掩码
- sql - 具有任意 LAG 的字段的 Postgres 历史依赖性
- python - 如何使用 PyCharm 在 2 台不同的机器上远程开发 python
- flask - Flask url_for 无法基于工作代码构建端点。问我要不要索引?
- bash - 使用 bash 确定目录 A 中不存在于目录 B 和 C 中的文件
- python - 根据聚合计数对 Pandas DataFrame 的行进行排序并随机获取一行