reactjs - Kuinka rajoitan React-lasten tyypin TypeScriptissä käyttämällä uudelleen TypeScript 2.3:ssa lisättyä tukea?
Yritän hyödyntää äskettäin lisättyä tukea lasten tyypittämiseen TypeScript-kääntäjässä ja @types/reactissä, mutta minulla on vaikeuksia. Käytän TypeScriptin versiota 2.3.4.
Sano, että minulla on koodi, joka näyttää tältä:
interface TabbedViewProps {children?: Tab[]}
export class TabbedView extends React.Component<TabbedViewProps, undefined> {
render(): JSX.Element {
return <div>TabbedView</div>;
}
}
interface TabProps {name: string}
export class Tab extends React.Component<TabProps, undefined> {
render(): JSX.Element {
return <div>Tab</div>
}
}
Kun yritän käyttää näitä komponentteja näin:
return <TabbedView>
<Tab name="Creatures">
<div>Creatures!</div>
</Tab>
<Tab name="Combat">
<div>Combat!</div>
</Tab>
</TabbedView>;
Saan seuraavan virheilmoituksen:
ERROR in ./src/typescript/PlayerView.tsx
(27,12): error TS2322: Type '{ children: Element[]; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<TabbedView> & Readonly<{ children?: ReactNode; }> ...'.
Type '{ children: Element[]; }' is not assignable to type 'Readonly<TabbedViewProps>'.
Types of property 'children' are incompatible.
Type 'Element[]' is not assignable to type 'Tab[] | undefined'.
Type 'Element[]' is not assignable to type 'Tab[]'.
Type 'Element' is not assignable to type 'Tab'.
Property 'render' is missing in type 'Element'.
Näyttää siltä, että se päättelee lasten tyypin vain Element[]:ksi Tab[]:n sijaan, vaikka se on ainoa käyttämäni lasten tyyppi.
MUOKKAA: Olisi myös täysin sopivaa rajoittaa children-propsien rajapintaa sen sijaan, että rajoitettaisiin suoraan lasten komponenttien tyyppiä, koska ainoa mitä minun tarvitsee tehdä, on ottaa tietyt propsit irti lasten komponenteista.
Vastaus #1
Muokkaus 2: Käy ilmi, että tämä lähestymistapa estää varoituksen, mutta kommenttien mukaan TabProps ei ole tarkistettu oikein.
Sinun pitäisi yrittää asettaa interface TabbedViewProps:n lapset näin
interface TabbedViewProps { children?: React.ReactElement<TabProps>[] }
Tässä ei ole tarkoitus kertoa TabbedView -komponentillesi, että sillä on taulukko Tab-elementtejä, vaan sen sijaan kertoa TabbedView -komponentillesi, että sillä on taulukko element-elementtejä, jotka ottavat tietyt ominaisuudet. Tapauksessasi TabProps.
Muokkaa (kiitos Mateille):
interface TabbedViewProps {
children?: React.ReactElement<TabProps>[] | React.ReactElement<TabProps>
}
Vastaus #2
Kuten jo mainittiin, TabbedView.children määritellään seuraavasti:
children: React.ReactElement<TabProps> | React.ReactElement<TabProps>[];
Poistaa virheen, mutta ei tarkista lasten tyyppejä oikein. Toisin sanoen voit silti antaa lapsia, jotka eivät ole TabProps, TabbedView-komponentille ilman virhettä, joten tämä olisi myös voimassa:
return (
<TabbedView>
<Tab name="Creatures">
<div>Creatures!</div>
</Tab>
<Tab name="Combat">
<div>Combat!</div>
</Tab>
<NotTabButValidToo />
</TabbedView>
);
Mitä voisit sen sijaan tehdä, on julistaa prop, sanotaan vaikka tabs: TabProps[], jotta voit välittää alas propsit, joita tarvitset näiden Tabien luomiseen, sen sijaan että välität niiden JSX:n, ja renderöidä ne sisälle TabbedViewiin:
interface TabbedViewProps {
children?: never;
tabs?: TabProps[];
}
...
const TabbedView: React.FC<TabbedViewProps> = ({ tabs }) => {
return (
...
{ tabs.map(tab => <Tab key={ ... } { ...tab } />) }
...
);
};
