【发布时间】:2020-01-01 01:12:45
【问题描述】:
我正在尝试为接受三个参数的函数创建一个通用接口。填写第一个参数时,第二个的选项应该在第一个的范围内。第三个参数应该在第二个参数的范围内。
我当前的代码如下所示:
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 或 settingB。到目前为止,一切都按预期工作。
setSomeSetting(Type.TypeA, ....) // <-- settingKey accepts "settingA" and "settingB"
但是对于第三个论点,我似乎无法解决它。当我设置第一个参数和第二个参数时,我希望第三个参数只接受所选 settingKey 参数中的联合选项。但是,我在Type.TypeA 中获得了所有选项。所以settingA和settingB的settingValues都是
使用此代码:
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 的值。
有人对我做错了什么有建议吗?
【问题讨论】:
-
你能创建一个带有问题工作示例的打字稿游乐场链接吗? typescriptlang.org/play 通过工作演示回答这样的问题要容易得多。
-
我不确定你想要的是否完全可能。它接受
settingA和settingB这两个值的原因是因为它们都是适合您所描述的类型系统的值。没有办法进一步缩小范围,因为这需要在 typescript 解析时不存在的运行时信息。我建议您重新设计您的设计,以减少打字系统的嵌套,或者考虑为最终选项抛出运行时错误 -
Idk,我怀疑一定有办法让这种事情发挥作用。如果不使用普通参数,那么它必须使用柯里化函数,对吧?
标签: typescript typescript-generics