typescript - 连接组件作为子类型(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 总是给出。哪里有问题?
解决方案
对于原始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
),因为:
- 您没有利用实现中的类型信息。
- 在调用站点,所有 JSX 元素的类型都为
JSX.Element
, which extends ,无论 JSX 元素的实际组件类型如何React.ReactElement<any>
,都可以分配给React.ReactElement<T>
任何JSX 元素。T
因此,您正在检查这children
是一个 JSX 元素或 JSX 元素数组(与其他类型的ReactNode
s 相比,例如字符串),但您没有得到任何检查组件类型是否正确。
因此,最好的解决方案可能是只删除children
from的声明TextProps
。