我试图基于具有相同键的另一个类型创建一个类型,其值的类型基于但不等于另一个类型。与React
的{{1}}相似,它接受一个值或一个获取当前值并返回新值的函数。
经过研究,与该错误有关的所有问题似乎都与缺少类型提示有关。我已经尝试为所有setState
,next
和current
变量指定类型。没用。
newTheme[key]
我期望的是type Mode = "light" | "dark";
interface Theme {
mode: Mode;
test: number;
}
type ThemeUpdate = {
[K in keyof Theme]: Theme[K] | ((current: Theme[K]) => Theme[K])
};
const reducer = (currentTheme: Theme, action: Partial<ThemeUpdate>): Theme => {
const newTheme: Partial<Theme> = {};
(Object.keys(action) as (keyof Theme)[]).forEach((key: keyof Theme) => {
const next = action[key];
const current = currentTheme[key];
newTheme[key] = typeof next === "function" ? next(current) : next;
// ^^^^^^^
// Argument of type 'number | "light" | "dark"' is not assignable to parameter of type 'never'. Type 'number' is not assignable to type 'never'
});
return { ...currentTheme, ...newTheme };
};
函数将根据当前键解析参数类型。而是将参数解析为类型next
,然后收到错误消息:
'number |类型的参数“光” | “ dark”不能分配给 类型为“从不”的参数。类型“数字”不可分配给类型 '从不'`
never
函数应在next
时将current
参数推论为Mode
,在key === "mode"
时应推论为key === "test"
< / p>
答案 0 :(得分:0)
是的,这是我一直在称correlated types的TypeScript中的痛点之一。问题在于您有一组联合类型的值,这些值彼此不独立。 is equivalent to
与which is equivalent to
的关联方式取决于next
的值。但是TypeScript只是将current
视为值或函数或未定义的联合(正确),而将key
视为值的联合(也正确),却没有意识到这是不可能的next
对应于current
,并且next
同时对应于"mode"
。 improved support for calling unions of functions只会使这个问题更令人困惑,因为current
交集并没有太多提示。
这里没有很好的解决方案。我发现的解决方法是手动编译器处理不同情况,如下所示:
"test"
这是相当安全的类型,但很繁琐...
或者,否则,您将需要在某个地方进行类型声明,以说服编译器您所做的事情是安全的(您对此承担安全责任;编译器正在放弃)。对于此特定问题,我考虑将never
回调作为键类型为 (Object.keys(action) as (keyof Theme)[]).forEach(key => {
switch (key) {
case "mode": {
const next = action[key];
const current = currentTheme[key];
newTheme[key] = typeof next === "function" ? next(current) : next; // okay
break;
}
case "test": {
const next = action[key];
const current = currentTheme[key];
newTheme[key] = typeof next === "function" ? next(current) : next; // okay
break;
}
}
});
的泛型函数,然后使用您的断言告诉编译器forEach()
依赖于{{1 }}以一种理解的方式:
K
这更方便,但不那么安全。
我通常在这里推荐断言(link to code),并希望有一天能为TypeScript中的相关类型提供更好的支持。
好的,希望能有所帮助。祝你好运!