![](/img/trans.png)
[英]explicit-function-return-type creating functional component react in typescript
[英]How to type any param with React Typescript in Functional Component
我有一個現有的 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 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
我遇到的問題當然是any: JSX.Element
正在尋找一個字面上稱為“any”的道具,而我想允許任何道具作為 JSX 元素,例如以下示例中的custom
這是此組件的示例用例:
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>)}
/>
</>
}
像您這樣的 Sonds 需要在您的類型上使用索引簽名。 一種天真的方法是
interface Props {
state: string
else?: JSX.Element
[key: string]: JSX.Element
}
但是,這不會編譯 - 因為接口上的索引簽名要求所有命名屬性( state
和else
)都與它兼容。
相反,您可以以類型交集的形式重寫它:
type Props = {
state: string
else?: JSX.Element
} & Record<string, JSX.Element>
這仍然不會編譯相同,但給我們一個線索。 如果我們有一組眾所周知的可能值而不是string
,該怎么辦? 下一次迭代將是
type Key = "custom" | "another";
type Props = {
state: Key | null
else?: JSX.Element
} & Record<Key, JSX.Element>
這看起來更好。 但是我們如何使它可重用,以便相同的組件可以與不同的可能鍵列表一起使用? 讓我們讓它通用!
所以最后的代碼:
type Props<Key extends string> = {
state: Key | null
else?: JSX.Element
} & Record<Key, JSX.Element>
您還需要使組件成為通用 function :
function RenderState<Key>(props: Props<Key>) { ... }
並在您的應用程序中使用它:
const [state, setState] = React.useState<"custom" | null>(null);
<RenderState
state={state}
custom={(<p>Some custom content here...</p>)}
else={(<p>Some default content here...</p>)}
/>
編輯 1
這種方法允許在RenderState
中編寫props[props.state]
(結果推斷為JSX.Element
)。 但是,它無法使用 rest 解構進行編譯,如原始代碼片段所示:
const {state, else: elseEl, ...rest} = props;
rest[props] // TS error here
它揭示了我們類型定義中的一個缺陷。 我們需要確保state
值不包含"state"
和"else"
字面量,以避免類型沖突。
更新的類型是
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.