使用重构定义时,React组件上不存在属性

时间:2017-10-01 20:42:57

标签: reactjs typescript recompose

我使用create-react-app和typescript脚本作为基础,尝试使用重构的简单示例。

问题是我无法将属性直接发送到组件。

我创建了一个简单的用户组件./components/User.tsx

import * as React from 'react';
import { compose, withState, withHandlers } from 'recompose';

export interface WithStateProps {
    counter: number
    setCounter: (x: (c: number) => number) => void;
}

export interface WithHandlerProps {
    increment: () => void
    decrement: () => void
}

interface ComponentProps {
    name: string
}

export type ComposedProps = WithStateProps & WithHandlerProps
export type UserProps = ComposedProps & ComponentProps

export const enhance = compose<UserProps, {}>(
    withState<WithStateProps, number, 'counter', 'setCounter'>('counter', 'setCounter', 1),
    withHandlers<UserProps, UserProps>({
        increment: ({ setCounter }) => () => setCounter( n => n + 1 ),
        decrement: ({ setCounter }) => () => setCounter( n => n - 1 )
    })    
)

const User: React.StatelessComponent<UserProps> = ({counter, increment, decrement, name}: UserProps) => (
    <div className='User'>
        {name} : counter : {counter}
        <div>
            <button onClick={increment}> add </button>
            <button onClick={decrement}> remove </button>
        </div>
    </div>
)

export default enhance(User)

我在index.tsx内使用它:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Provider } from 'react-redux';

import registerServiceWorker from './registerServiceWorker';
import './index.css';

import User from './components/User'

import { createStore } from 'redux';
import { enthusiasm } from './reducers/index';
import { StoreState } from './types/index';

const store = createStore<StoreState>(enthusiasm, {
  enthusiasmLevel: 1,
  languageName: 'TypeScript',
});

ReactDOM.render(
  <Provider store={store}>
    <div>
      <User />
    </div>
  </Provider>,
  document.getElementById('root') as HTMLElement
);
registerServiceWorker();

以上工作正常,但如果我使用以下代码:

<User name='andrew hopkins' />

我收到以下错误消息:

./src/index.tsx
(22,13): error TS2339: Property 'name' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<{}, ComponentState>> & Readonly<{ childr...'.

我的package.json file

{
  "name": "ts-rxjs-recompose",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "react-redux": "^5.0.6",
    "react-scripts-ts": "2.7.0",
    "recompose": "^0.25.1",
    "redux": "^3.7.2"
  },
  "scripts": {
    "start": "react-scripts-ts start",
    "build": "react-scripts-ts build",
    "test": "react-scripts-ts test --env=jsdom",
    "eject": "react-scripts-ts eject"
  },
  "devDependencies": {
    "@types/enzyme": "^2.8.9",
    "@types/jest": "^21.1.1",
    "@types/node": "^8.0.31",
    "@types/react": "^16.0.7",
    "@types/react-dom": "^15.5.5",
    "@types/react-redux": "^5.0.9",
    "@types/recompose": "^0.24.2",
    "enzyme": "^3.0.0",
    "react-addons-test-utils": "^15.6.2"
  }
}

1 个答案:

答案 0 :(得分:6)

解决方案是使用ComponentProps作为撰写的TOutter类型:

export const enhance = compose<UserProps, ComponentProps>(

这是因为,查看compose的类型定义

export function compose<TInner, TOutter>(
        ...functions: Function[]
    ): ComponentEnhancer<TInner, TOutter>;

我正在UserProps作为TInner传递,但是TOutter,增强的组件的空对象,导致错误。

编辑: 为了扩展答案,TOutter是外部copmonent的类型,在这种情况下是接收名称props的类型,即<User />中使用的index.tsx组件。 TInner期望内部组件的类型将接收使用重构创建的所有道具,在本例中为User中的./components/User.tsx组件。