首页 > 解决方案 > 连接组件作为子类型(TypeScript、ReactJS.React-redux)

问题描述

有组件 Translate 和 Text,并且想将 Translate 定义为 Text 的子项,但是 Translate 与商店有连接,并且存在问题(我不明白为什么)。

翻译组件

import * as React from 'react'
import {connect} from 'react-redux'
import appState from '../store/types/appState'

type TranslateProps = {
  translations?: string[]
  keyString: string
}

class Translate extends React.Component<TranslateProps, any> {
  public render() {
    return (
      <React.Fragment>
        {this.translateString(this.props.keyString)}
      </React.Fragment>
    )
  }

  private translateString(key: string) {
    return this.props.translations[key] ? this.props.translations[key] : key
  }
}

const mapStateToProps = (state: appState) => ({translations: state.translations})

export default connect(mapStateToProps)(Translate)

文本组件

import * as React from 'react'
import Translate from './Translate'

type TextProps = {
  children: React.ReactElement<Translate> | React.ReactElement<Translate>[]
}

class Text extends React.Component<TextProps, any> {
  public render() {
    return (
      <StyledText>
        {this.props.children}
      </StyledText>
    )
  }
}

export default Text

而且我有一个编译错误:TS2304 找不到名称“翻译”

我的 tsconfig:

{
  "compilerOptions": {
    "baseUrl": ".",
    "lib": ["es2015", "es2016", "DOM"],
    "outDir": "./dist/",
    "module": "commonjs",
    "target": "es5",
    "sourceMap": true,
    "moduleResolution": "node",
    "jsx": "react"
  },
  "typeRoots": [
    "node_modules/@types"
  ],
  "types": [
    "core-js",
    "webpack"
  ],
  "exclude": [
    "node_modules"
  ],
  "compileOnSave": true,
  "allowJs": true
}

任何未连接到 store 的组件都不会给出这个异常,任何 with 总是给出。哪里有问题?

标签: typescriptreact-redux

解决方案


对于原始Translate组件类,Translate作为值是指类本身,而Translate作为类型是指类的实例类型。相反,connect将新的组件类作为值返回,而 的结果connect不能用作类型。默认导出有点模糊。为了使问题更清楚,假设您写道:

const Translate2 = connect(mapStateToProps)(Translate);
type TextProps = {
  children: React.ReactElement<Translate2> | React.ReactElement<Translate2[]>;
}

这里Translate2只是一个值,而不是一个类型。

如果你真的想要连接组件的实例类型,你可以使用InstanceType<typeof Translate>. 但是,type 参数React.ReactElement应该是组件的 props 类型(即TranslateProps),而不是组件实例类型。所以导入TranslateProps和使用它来代替Translate. 但是,声明 prop 的类型似乎没有什么好处children(而不是依赖于 default ReactNode),因为:

  1. 您没有利用实现中的类型信息。
  2. 在调用站点,所有 JSX 元素的类型都为JSX.Element, which extends ,无论 JSX 元素的实际组件类型如何React.ReactElement<any>,都可以分配给React.ReactElement<T>任何JSX 元素。T因此,您正在检查这children是一个 JSX 元素或 JSX 元素数组(与其他类型的ReactNodes 相比,例如字符串),但您没有得到任何检查组件类型是否正确。

因此,最好的解决方案可能是只删除childrenfrom的声明TextProps


推荐阅读