reactjs - React HOC, bir sınıf bileşeni olarak Typescript hatası veriyor ama bir fonksiyon bileşeni olarak vermiyor
typescript - v3.9.7
Bileşene ek özellikler geçiren bir HOC'um var:
import React from 'react';
interface IWithOwner {
owner: string;
}
type IWithoutOwner<T extends IWithOwner> = Omit<T, keyof IWithOwner> & {owner?: never};
// CORRECT
export function withOwnerOne<TProps extends IWithOwner>(Component: React.ComponentType<TProps>) {
const ComponentWithOwner: React.FunctionComponent<IWithoutOwner<TProps>> = (props) => {
return (
<Component
owner="Tom"
{...props}
/>
);
}
return ComponentWithOwner;
}
// ERROR
export function withOwnerTwo<TProps extends IWithOwner>(Component: React.ComponentType<TProps>) {
return class extends React.Component<IWithoutOwner<TProps>> {
render() {
return (
// '{ owner: string; } & Readonly<IWithoutOwner<TProps>> & Readonly<{ children?: ReactNode; }>'
// is assignable to the constraint of type 'TProps', but 'TProps' could be
// instantiated with a different subtype of constraint 'IWithOwner'.
<Component
owner="Tom"
{...this.props}
/>
)
}
}
}
withOwnerOne fonksiyon bileşeni kullanan doğru çalışıyor. Sınıf bileşeni kullanan withOwnerTwo ise bir hata veriyor. Neden farklı çalışıyorlar?
Oyun alanı linki
Fonksiyonlarla aynı durum doğru çalışıyor
Cevap #1
Sorunun props türünde olduğunu düşünüyorum.
İlk örnekte, FunctionComponent, props türü şudur: IWithoutOwner<TProps> & { children?: ReactNode };
interface IWithOwner {
owner: string;
}
type IWithoutOwner<T extends IWithOwner> = Omit<T, keyof IWithOwner> & {
owner?: never;
};
function withOwnerTwo<TProps extends IWithOwner>(
Component: React.ComponentType<TProps>
) {
const ComponentWithOwner: React.FunctionComponent<IWithoutOwner<TProps>> = (
props
) => {
// React.PropsWithChildren<IWithoutOwner<TProps>> --> IWithoutOwner<TProps> & { children?: ReactNode };
const x = props;
return <Component owner="Dmitry" {...props} />;
};
return ComponentWithOwner;
}
İkincisi, props biraz farklı bir tipe sahiptir:
Readonly<IWithoutOwner<TProps>> & Readonly<{children?: React.ReactNode;}>function withOwnerOne<TProps extends IWithOwner>(
Component: React.ComponentType<TProps>
) {
class Wrapper extends React.Component<IWithoutOwner<TProps>> {
render() {
//Readonly<IWithoutOwner<TProps>> & Readonly<{children?: React.ReactNode;}>
const props = this.props;
return <Component owner="Dmitry" {...props} />;
}
}
return Wrapper;
}
Şimdi, sorunun Readonly değiştiricisinde olduğunu düşünebilirsiniz. Readonly hataya neden olmaz. Hatanın kontravaryanstan kaynaklandığına kuvvetle inanıyorum.
Çünkü props türü bileşen bağlamından alınır ve props generiği yukarıdaki bileşenlerde farklı konumlara yerleştirilmiştir.
Eleştiriye açığım, bu yüzden hatalarımı belirtmekten çekinmeyin.
Kovaryans/varyans/invariyans - benim için çok karmaşık bir konu, anlamaktan çok hissediyorum. Bu yüzden doğru yolu gösterirseniz mutlu olurum.
