Javascript 如何在功能组件中使用React-Typescript键入任何参数
我有一个现有的javascript组件:Javascript 如何在功能组件中使用React-Typescript键入任何参数,javascript,reactjs,typescript,types,react-props,Javascript,Reactjs,Typescript,Types,React Props,我有一个现有的javascript组件: const RenderState = ({ state, else: elseChild = undefined, ...states }) => { if (state && states[state]) return states[state] if (elseChild) return elseChild return null } export default RenderState import Reac
const RenderState = ({ state, else: elseChild = undefined, ...states }) => {
if (state && states[state]) return states[state]
if (elseChild) return elseChild
return null
}
export default RenderState
import React from 'react'
import RenderState from './RenderState'
const MyComp = () => {
const [state, setState] = React.useState<string | null>(null)
<>
<Button onClick={()=>{setState(null)}}>Default</Button>
<Button onClick={()=>{setState('custom')}}>Custom</Button>
<RenderState
state={state}
custom={(<p>Some custom content here...</p>)}
else={(<p>Some default content here...</p>)}
/>
</>
}
我正在尝试将其转换为typscript,到目前为止:
import React from 'react'
interface Props {
state: string
else?: JSX.Element
any: JSX.Element
}
const RenderState: React.FC<Props> = ({ state, else: elseChild = undefined, ...states }) => {
if (state && states[state]) return states[state]
if (elseChild) return elseChild
return null
}
export default RenderState
像你这样的人需要在你的类型上添加索引签名。 一个天真的方法是
interface Props {
state: string
else?: JSX.Element
[key: string]: JSX.Element
}
但是,这不会编译,因为接口上的索引签名要求所有命名属性状态和其他属性都与之兼容
相反,您可以以类型交叉的形式重写它:
type Props = {
state: string
else?: JSX.Element
} & Record<string, JSX.Element>
这个看起来好多了。但是我们如何使其可重用,以便同一组件可以与不同的可能键列表一起使用呢?让我们把它变成通用的
最后的代码是:
它揭示了我们的类型定义中的一个缺陷。我们需要确保state值不包括state和else文本,以避免类型冲突
更新类型为
type Props<Key extends string> = {
state: Exclude<Key, "state" | "else"> | null
else?: JSX.Element
} & Record<Key, JSX.Element>
像你这样的人需要在你的类型上添加索引签名。 一个天真的方法是
interface Props {
state: string
else?: JSX.Element
[key: string]: JSX.Element
}
但是,这不会编译,因为接口上的索引签名要求所有命名属性状态和其他属性都与之兼容
相反,您可以以类型交叉的形式重写它:
type Props = {
state: string
else?: JSX.Element
} & Record<string, JSX.Element>
这个看起来好多了。但是我们如何使其可重用,以便同一组件可以与不同的可能键列表一起使用呢?让我们把它变成通用的
最后的代码是:
它揭示了我们的类型定义中的一个缺陷。我们需要确保state值不包括state和else文本,以避免类型冲突
更新类型为
type Props<Key extends string> = {
state: Exclude<Key, "state" | "else"> | null
else?: JSX.Element
} & Record<Key, JSX.Element>
函数RenderStateprops:Props{…}这是否必须是关键的,并且与上面的匹配,我不这么认为,但是a将具有相同的效果?这需要一些调整。我不得不将states[state]替换为states[state as string],因为键抛出了类型错误:类型“Key”不能用于索引类型“Pick”。就跟,对。它不必匹配generic type definition>states[state as string]中的键。我在响应中编辑了类型定义,以使其更加健壮,并正确地支持这种没有类型的场景assertions@amakhrov我开始悬赏50磅,尽快给你。非常感谢你!函数RenderStateprops:Props{…}这是否必须是关键的,并且与上面的匹配,我不这么认为,但是a将具有相同的效果?这需要一些调整。我不得不将states[state]替换为states[state as string],因为键抛出了类型错误:类型“Key”不能用于索引类型“Pick”。就跟,对。它不必匹配generic type definition>states[state as string]中的键。我在响应中编辑了类型定义,以使其更加健壮,并正确地支持这种没有类型的场景assertions@amakhrov我开始悬赏50磅,尽快给你。非常感谢你!那些名字对我来说似乎很糟糕。最好不要使用现有的JS/TS关键字作为自己的关键字…这些对我来说似乎是糟糕的道具名称。最好不要使用现有的JS/TS关键字作为自己的关键字。。。
const {state, else: elseEl, ...rest} = props;
rest[props] // TS error here
type Props<Key extends string> = {
state: Exclude<Key, "state" | "else"> | null
else?: JSX.Element
} & Record<Key, JSX.Element>
const {state, else: elseEl, ...rest} = props;
rest[props]