反应 redux 打字稿:连接缺少类型错误 [英] React redux typescript: connect has missing type error

查看:48
本文介绍了反应 redux 打字稿:连接缺少类型错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让 react-redux 应用程序与 typescript 一起运行,但我一直在围绕相同的错误盘旋.以下代码编译并产生预期结果

I am trying to get a react-redux app going with typescript, but I keep circling around the same error. The following code compiles and produces expected result

// State definition
interface HelloWorldState {
    clickCount: number
}
interface AppState extends HelloWorldState {}


// Props definitions
interface HelloWorldProps {
    count: number
}


// Actions
const CLICK = 'CLICK';
const click = () => {return {type:CLICK}};


// Reducers
function clickCount(state:number = 0, action:Action) {
    if (typeof state === 'undefined') {
        return 0;
    }
    switch (action.type) {
        case CLICK:
            return state + 1;
        default:
            return state;
    }
}
let rootReducer = combineReducers({
    clickCount
});


// Store
let store = createStore(rootReducer);


// Components
class HelloWorld extends React.Component<any, any> {
    render() {
        return <div onClick={this.handleClick.bind(this)}>Hello world "{this.props.count}"</div>
    }

    handleClick() {
        store.dispatch(click())
    }
}


// Container components
const mapStateToProps = (state:AppState):HelloWorldState => {
    return Immutable.fromJS({
        count: state.clickCount
    })
};
const ConnectedHelloWorld = connect(
    mapStateToProps
)(HelloWorld);

render(
    <Provider store={store}>
        <ConnectedHelloWorld/>
    </Provider>,
    container
);

太好了!但我使用的是 TypeScript,因为我想在编译时进行类型检查.类型检查最重要的是 state 和 props.所以我想做 class HelloWorld extends React.Component 而不是 class HelloWorld extends React.Component.但是,当我这样做时,我从对 render

Great! But I am using TypeScript, because I want to get type checks at compile time. The most important thing to type check is state and props. So instead of class HelloWorld extends React.Component<any, any>, I want to do class HelloWorld extends React.Component<HelloWorldProps, any>. When I do this, however, I get the following compile error from the call to render

TS2324:Property 'count' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<HelloWorld> & HelloWorldProps & { children?: React...'.

我真的不明白为什么.count IS 出现在 HelloWordProps 定义中,它是由 reducer 提供的,所以我应该没问题,对吧?类似的问题表明这是一个推理问题,我应该声明对 connect 的调用类型,但我似乎无法找出如何

I don't really understand why. count IS present in the HelloWordProps definition, and it is provided by the reducer, so I should be fine, right? Similar questions has suggested that it is an inference problem, and that I should declare the type of the call to connect, but I can't seem to find out how

package.json

package.json

{
  "name": "reacttsx",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "ts-loader": "^1.3.3",
    "typescript": "^2.1.5",
    "webpack": "^1.14.0",
    "typings": "^2.1.0"
  },
  "dependencies": {
    "es6-promise": "^4.0.5",
    "flux": "^3.1.2",
    "immutable": "^3.8.1",
    "isomorphic-fetch": "^2.2.1",
    "jquery": "^3.1.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-redux": "^5.0.2",
    "redux": "^3.6.0",
    "redux-logger": "^2.7.4",
    "redux-thunk": "^2.2.0"
  }
}

typings.json

typings.json

{
  "dependencies": {
    "flux": "registry:npm/flux#2.1.1+20160601175240",
    "immutable": "registry:npm/immutable#3.7.6+20160411060006",
    "react": "registry:npm/react#15.0.1+20170104200836",
    "react-dom": "registry:npm/react-dom#15.0.1+20160826174104",
    "react-redux": "registry:npm/react-redux#4.4.0+20160614222153",
    "redux-logger": "registry:dt/redux-logger#2.6.0+20160726205300",
    "redux-thunk": "registry:npm/redux-thunk#2.0.0+20160525185520"
  },
  "globalDependencies": {
    "es6-promise": "registry:dt/es6-promise#0.0.0+20160726191732",
    "isomorphic-fetch": "registry:dt/isomorphic-fetch#0.0.0+20170120045107",
    "jquery": "registry:dt/jquery#1.10.0+20170104155652",
    "redux": "registry:dt/redux#3.5.2+20160703092728",
    "redux-thunk": "registry:dt/redux-thunk#2.1.0+20160703120921"
  }
}

更新

因为它抱怨 count 丢失,我尝试更新到

Since it was complaining that count was missing, I tried updating to

render(
    <Provider store={store}>
        <ConnectedHelloWorld count={0}/>
    </Provider>,
    container
);

这解决了问题.所以问题是编译器不知道 Provider 正在提供计数.提供者使用商店.商店应该有 clickCount 值,该值由容器组件映射到 count.

This solves the issue. So the issue is that the compiler doesn't know that the Provider is providing the count. Provider uses the store. The store should have the clickCount value which is mapped to count by the container component.

我注意到我忘记了商店的初始状态.因此,即使类型已检出,状态也会为空.我更新为

I noticed I'd forgotten an initial state for the store. So even if the types had checked out, the state would be empty. I updated it to

// Store
let initialState:AppState = {clickCount: 0};
let store = createStore(rootReducer, initialState);

现在我确定 clickCount 在商店中设置正确.所以我希望 mapStateToProps 函数采用 AppState 并返回指定的 HelloWorldProps,然后返回 Provider 应提供计数值.这是真的,但编译器没有看到.

Now I am certain that clickCount is set properly in the store. So I'd expect the mapStateToProps function to take the AppState and return the HelloWorldProps as specified, and then the Provider should provide the count value. This is true, but the compiler does not see it.

那么如何补救呢?

推荐答案

这就是我在 Typescript Redux 应用程序中的做法(已根据您的代码进行调整但未经过测试)

This how I do it in a Typescript Redux App (adjusted to your code but not tested)

在下方评论编辑

  1. 输入 connect 和连接组件的 props (ConnectedHelloWorldProps)

  1. type connect with props for the Connected Component (ConnectedHelloWorldProps)

const ConnectedHelloWorld:React.ComponentClass<ConnectedHelloWorldProps>  = 
    connect<any,any,HelloWorldProps>(mapStateToProps)(HelloWorld)

interface ConnectedHelloWorldProps { }

interface HelloWorldProps extends ConnectedHelloWorldProps {
    count: number
    ....
}

  • Provider

    <Provider store={store}>
        <ConnectedHelloWorld/>
    </Provider>
    

  • 注意:这适用于这些类型

    Note: this works fine with these typings

    "@types/react": "^0.14.52",
    "@types/react-dom": "^0.14.19",
    "@types/react-redux": "^4.4.35",
    "@types/redux-thunk": "^2.1.32",
    

    ConnectedHellowWorldProps 这里并不真正需要,因为它是一个空接口,但在现实世界的场景中它可能包含一些道具.

    ConnectedHellowWorldProps is not really needed here, since it is an empty interface, but in a real world scenario it is likely to contain a few props.

    基本原理是这样的:ConnectedHelloWorldProps 包含需要在 Provider 级别传递的内容.在 mapStateToProps 和/或 mapDispatchToProps 中,用任何需要的东西丰富实际的组件 HelloWorldProps

    The basic principle is this: ConnectedHelloWorldProps contain what needs to be passed at the Provider level. In mapStateToProps and/or mapDispatchToProps, enrich the actual Component HelloWorldProps with whatever is needed

    Redux Typescript 类型是一种野兽,但上面显示的应该足够了.

    Redux Typescript typings are a beast but what is shown above should be sufficient.

    export declare function connect<TStateProps, TDispatchProps, TOwnProps>(
    mapStateToProps: FuncOrSelf<MapStateToProps<TStateProps, TOwnProps>>,
     mapDispatchToProps?: FuncOrSelf<MapDispatchToPropsFunction<TDispatchProps, TOwnProps> | MapDispatchToPropsObject>): ComponentDecorator<TStateProps & TDispatchProps, TOwnProps>;
    
    
     interface ComponentDecorator<TOriginalProps, TOwnProps> {
        (component: ComponentClass<TOriginalProps> | StatelessComponent<TOriginalProps>): ComponentClass<TOwnProps>;
     }
    

    这篇关于反应 redux 打字稿:连接缺少类型错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆