我試圖編寫更高階的組件來檢查用戶是否已通過身份驗證。我使用15.5.4做出反應,並@類型/反應15.0.21,和我(簡化)代碼如下:類型安全高階React組件和無狀態功能組件
import * as React from 'react';
interface IAuthProps {
authenticated: boolean
}
function authenticated1<Props extends Object>(wrapped: React.ComponentClass<Props> | React.SFC<Props>):
React.SFC<Props & IAuthProps> {
return (props: Props & IAuthProps): React.ReactElement<any> => {
if (props.authenticated) {
return React.createElement(wrapped, props);
} else {
return <h1>Unauthorized!</h1>
}
}
}
然而,在編譯調用失敗createElement
:
TS2345:Argument of type 'ComponentClass<Props> | StatelessComponent<Props>' is not assignable to parameter of type 'ComponentClass<Props>'.
Type 'StatelessComponent<Props>' is not assignable to type 'ComponentClass<Props>'.
Type 'StatelessComponent<Props>' provides no match for the signature 'new (props?: Props | undefined, context?: any): Component<Props, ComponentState>'
由於@types/react
將React.createElement
聲明爲超載函數,並且Typescript can't resolve overloads with union types錯誤並不讓人驚訝。
然而@types/react
提供了在工會每種合格的過載(SFCEelement
繼承ReactElement
所以返回類型兼容):
function createElement<P>(
type: ComponentClass<P>,
props?: Attributes & P,
...children: ReactNode[]): ReactElement<P>;
function createElement<P>(
type: SFC<P>,
props?: Attributes & P,
...children: ReactNode[]): SFCElement<P>;
爲了使代碼編譯我只是需要強制打字稿考慮要麼爲聯合類型的相應分支重載,但我不知道如何做到這一點。
如何區分ComponentClass
和SFC
以使Typescript爲類型檢查選擇相應的過載?
PS:目前我只是迫使它通過傳遞wrapped as React.ComponentClass<Props>
這是安全的挑頭超載,因爲超載都叫出它接受兩個參數類型相同的運行時功能,但我寧願不喜歡在這裏「作弊」,而是讓系統保證安全。