打字稿类型-有关使用推断

时间:2019-09-10 22:17:52

标签: reactjs typescript redux react-redux

使用redux,我最终在商店代码中编写了以下代码段:

type CombinedParamTypes<T extends {
    [key: string]: (state: any, action: any) => any;
}> = T extends {
    [key: string]: (state: infer R, action: any) => any;
} ? R : never;

type CombinedReturnTypes<T extends {
    [key: string]: (...args: any) => any;
}> = T extends {
    [key: string]: (...args) => infer R;
} ? R : never;

示例:

import camera from "./camera/reducer";
import settings from "./settings/reducer";

export const ALL_REDUCERS = {
    camera,
    settings,
};

const COMBINED_REDUCERS = combineReducers(ALL_REDUCERS);

export type FlatReduxState = CombinedParamTypes<typeof ALL_REDUCERS>;
// returns intersection type: ICameraState & ISettingsState

export type WhyDifferent = CombinedReturnTypes<typeof ALL_REDUCERS>;
// returns union type: ICameraState | ISettingsState

谁能解释为什么他们返回的方式不同?我意识到一个人在看一个参数,另一个人在看返回类型,但是这如何转换成决定交集与并集呢?

1 个答案:

答案 0 :(得分:1)

函数类型为covariant in their return type and contravariant in the argument types。关于type inference in conditional types,在文档中也有说明:

  

[...]协变量位置中相同类型变量的多个候选导致推断联合类型[...]同样,反变量位置中相同类型变量的多个候选导致交集类型被推断[。]

对于您的reducer返回类型,TypeScript推断R的所有实例化的通用 supertype ,这将导致返回类型的并集类型-ICameraState | ISettingsState。反过来说,R的函数参数中所有CombinedParamTypes的实例化都将作为交集类型组合起来,以获得R-{{1 }}。

当您第一次(和第二次-对我来说...)听到它时,协方差和反方差的基本概念有时会很难理解。某种意义上,协方差意味着当基本组件类型以函数,列表或其他更复杂的类型(高阶类型/ HOT)打包时,基本类型的子类型关系得以保留。逆变性是相反的-在函数中,子类型成为超类型,因为函数的参数类型是逆变量。

this recommended article的狗和动物为类比的简单示例:

ICameraState & ISettingsState

Playground

希望,我可以解决一些问题。