【问题标题】:InteliJ: Typescript auto check {} object against an interface?IntelliJ:Typescript 根据接口自动检查 {} 对象?
【发布时间】:2021-01-27 23:38:31
【问题描述】:

这里是错误连接到 Redux 的 React 组件的示例违规代码。

import React from 'react';
import { View, StyleSheet, ViewStyle, Text } from 'react-native';
import { connect } from "react-redux";
import { StoreState } from "../../store/storeState/storeState";
import { LogFactory, Logger } from "../../vlabs-js/general/logging/log";

interface DevCompProps {
    counter: number
}

class UnconnectedDevComp extends React.Component<DevCompProps> {
    private logger: Logger;

    constructor(props: DevCompProps) {
        super(props);

        this.logger = LogFactory.fromComp('DevComp');
    }

    render() {
        this.logger.info(`render(): props='${this.props.counter}'`);

        return <View style={{flexDirection: 'row', borderWidth: 3, borderColor: 'black', padding: 5}}>
            <Text>Counter:</Text>
            <Text>{this.props.counter}</Text>
        </View>
    }
}

const mapStateToProps = (state: StoreState) => {
    return {
        number: state.devState.counter
    };
};


export const DevComp = connect(mapStateToProps)(UnconnectedDevComp)

为了让代码正常工作,mapStateToProps 应该是


const mapStateToProps = (state: StoreState) => {
    return {
        counter: state.devState.counter
    };
};

代替


const mapStateToProps = (state: StoreState) => {
    return {
        number: state.devState.counter
    };
};

有没有办法编译/InteliJ-Warn 检查 mapStateToProps 返回的对象是否与接口匹配

interface DevCompProps {
    counter: number
}

所以这样的错误会被 IDE 标记出来,而不必手动发现。

【问题讨论】:

    标签: reactjs typescript intellij-idea redux


    【解决方案1】:

    简短的回答是“不”,因为这里的所有解决方案都很糟糕。处理函数组件和useSelector 钩子可能会更好。

    当您使用错误的键进行映射时,您的组合 DevComp 将成为一个组件,当您调用它时需要传入 counter 属性,以便 typescript 正确处理该部分。

    您可以通过在connect 函数上设置一些泛型来引发错误,但这似乎很痛苦。我们要设置的变量是第一个,它是从 mapStateToProps 返回的 props,第三个是您希望调用组件的 props。

    const DevComp = connect<DevCompProps, {}, {}>(mapStateToProps)(UnconnectedDevComp)
    

    同样,您可以通过将mapStateToProps 上的返回类型设置为Partial&lt;DevCompProps&gt; 来引发错误。

    您需要覆盖 react-redux 包中的某些类型才能自动获得该推断。但这也很糟糕。

    我们想让 mapStateToProps 返回的 props 不能包含组件 props 中不存在的任何键。

    你不能通过操作MapStateToProps 类型来做到这一点。这有三个变量,但没有一个代表要映射的组件的类型。你需要的是 TStateProps 被限制。

    export type MapStateToProps<TStateProps, TOwnProps, State = DefaultRootState> =
        (state: State, ownProps: TOwnProps) => TStateProps;
    

    归根结底,问题在于connect HOC 的两步性质。 “连接器”的创建与将其应用于组件是分开的,因此连接器不能依赖于该组件。

    这样做很好:

    const myWrapper = connect(mapStateToProps);
    

    获取类型

    InferableComponentEnhancerWithProps<{ number: number; } & DispatchProp<AnyAction>, {}>
    

    myWrapper 是一个可以包装 任何 组件的函数,并会为其添加一个 prop number。它不知道要应用的组件类型,也不关心该组件是否真的需要一个 prop number

    您需要定义自己的函数,将这两个步骤组合成一个带有两个参数的函数,以便参数可以相互推断类型。我没有完整的解决方案。 connect 有 15 种不同的重载,此类型签名仅描述一种。实现也是一个错误,但是函数类型可以满足您的需求。

    const myConnect = <InnerProps, MappedProps extends Partial<InnerProps> , State = DefaultRootState>(
      mapStateToProps: (state: State) => MappedProps, Component: ComponentType<InnerProps>
      ): ComponentType<Omit<InnerProps, keyof MappedProps>> => {
        return connect(mapStateToProps)(Component);
    }
    
    export const DevComp = myConnect(mapStateToProps, UnconnectedDevComp)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 2011-07-06
      • 1970-01-01
      • 2015-05-28
      • 2019-06-04
      相关资源
      最近更新 更多