Diskriminoidut unionit komponenttivarianteille
Mallintakaa varianttipropsit diskriminoiduilla unioneilla, jotta TypeScript valvoo kelvollisia propsiyhdistelmiä.
Diskriminoidut unionit komponenttivarianteille on ilmainen React Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu React Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. React Academy-kurssilla on yhteensä 4 oppituntia.
Variant-propsien ongelma
Komponentilla, jossa on eri tiloja varten valinnaisia propseja, kuten painikkeella, joka voi olla joko linkki tai painike, voi olla virheellisiä prop-yhdistelmiä. TypeScript ei pysty havaitsemaan niitä ilman discriminated union -tyyppejä.
Mikä on discriminated union?
Discriminated union on tyyppien unioni, jonka jäsenillä on yhteinen literaalityyppinen kenttä (discriminant). TypeScript rajaa tyypin tämän kentän arvon perusteella.
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number };
function area(shape: Shape): number {
if (shape.kind === 'circle') return Math.PI * shape.radius ** 2;
return shape.width * shape.height; // TS knows width/height exist here
}Button- ja Link-variantti
Mallinna polymorfinen komponentti as- tai variant-kentän discriminated unionilla, jotta kunkin tapauksen oikeat propsit voidaan varmistaa.
type ButtonProps =
| { as: 'button'; onClick: () => void; disabled?: boolean; children: React.ReactNode }
| { as: 'a'; href: string; target?: string; children: React.ReactNode };
function ActionButton(props: ButtonProps) {
if (props.as === 'button') {
return <button onClick={props.onClick} disabled={props.disabled}>{props.children}</button>;
}
return <a href={props.href} target={props.target}>{props.children}</a>;
}Alert-komponentin variantit
Mallinna Alert siten, että jokainen severity-tyyppi edellyttää erilaisia tietoja.
type AlertProps =
| { type: 'success'; message: string }
| { type: 'error'; message: string; onRetry: () => void }
| { type: 'warning'; message: string; details?: string };
function Alert(props: AlertProps) {
if (props.type === 'error') {
return (
<div className="alert error">
<p>{props.message}</p>
<button onClick={props.onRetry}>Retry</button>
</div>
);
}
return <div className={`alert ${props.type}`}>{props.message}</div>;
}Tyyppien rajaaminen tapahtumankäsittelijöissä
Discriminated unionit toimivat myös tapahtumavetoisen datan kanssa – ne sopivat erinomaisesti tilakoneisiin tai action-pohjaiseen tilanhallintaan.
type LoadingState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function DataView<T>({ state }: { state: LoadingState<T> }) {
if (state.status === 'loading') return <Spinner />;
if (state.status === 'error') return <p>{state.error.message}</p>;
if (state.status === 'success') return <pre>{JSON.stringify(state.data)}</pre>;
return null;
}Kattavuustarkistukset never-tyypillä
Lisää oletushaaraan never-tarkistus, jotta TypeScript ilmoittaa virheestä, jos unioniin lisätään uusi jäsen mutta sitä ei käsitellä.
function assertNever(x: never): never {
throw new Error('Unhandled case: ' + x);
}
function renderIcon(type: AlertProps['type']) {
switch (type) {
case 'success': return <CheckIcon />;
case 'error': return <XIcon />;
case 'warning': return <WarnIcon />;
default: return assertNever(type); // TS error if a case is missing
}
}Discriminated unionit API-vastauksille
Mallinna API-vastausten rakenteet discriminated union -tyyppeinä, jotta kutsuja voi käsitellä onnistumis- ja virhepolut ilman tyyppimuunnoksia.
type ApiResult<T> =
| { ok: true; data: T }
| { ok: false; error: string; code: number };
async function fetchUser(id: string): Promise<ApiResult<User>> {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) return { ok: false, error: 'Not found', code: res.status };
return { ok: true, data: await res.json() };
}Type guardit tyyppien rajaamiseen
Käytä mukautettuja type guard -tarkistuksia unionien rajaamiseen monimutkaisemmissa tilanteissa, joissa discriminant ei ole yksinkertainen yhtäsuuruustarkistus.
function isSuccess<T>(result: ApiResult<T>): result is { ok: true; data: T } {
return result.ok === true;
}
const result = await fetchUser('1');
if (isSuccess(result)) {
console.log(result.data.name); // TS knows data exists
}Valinnaisten propsien sekamelskan välttäminen
Ilman discriminated union -tyyppejä komponentteihin kertyy valinnaisia propseja, jotka ovat sallittuja vain tietyissä yhdistelmissä – lopputulos on sekava ja tyypittämätön. Discriminated unionit poistavat mahdottomat tilat.
// Bad: optional prop soup — invalid combos allowed:
interface BadProps {
href?: string;
onClick?: () => void;
disabled?: boolean;
}
// Good: only valid combos via discriminated union:
type GoodProps =
| { as: 'a'; href: string }
| { as: 'button'; onClick: () => void; disabled?: boolean };Unionien koostaminen
Lisää unionin kaikille jäsenille yhteiset propsit käyttämällä &-operaattoria (intersection).
type BaseProps = { className?: string; children: React.ReactNode };
type ButtonVariant =
| (BaseProps & { variant: 'primary'; onClick: () => void })
| (BaseProps & { variant: 'link'; href: string });Erottelu ajonaikana
React käyttää discriminant-kenttää ajonaikana oikean käyttöliittymän renderöintiin. TypeScript käyttää sitä käännösaikana oikean prop-käytön varmistamiseen. Molemmat tasot ovat suojattuja.
Pikatarkistus
Mikä on discriminant discriminated unionissa?
Kertaus
Discriminated unionit mallintavat komponentteja, joilla on toisensa poissulkevat prop-joukot ja yhteinen literaalityyppinen discriminant-kenttä. Käytä never-tyyppiä oletushaarassa kattavuustarkistuksiin. Ne poistavat valinnaisten propsien sallimat virheelliset prop-yhdistelmät ja tekevät komponenteista itsensä dokumentoivia ja tyyppiturvallisia.
Opi React tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 88
- Oppitunnit
- 324
Usein kysytyt kysymykset
Onko oppitunti ”Diskriminoidut unionit komponenttivarianteille” ilmainen?
Kyllä – oppitunnin ”Diskriminoidut unionit komponenttivarianteille” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko React Academy-kurssin, päivitä CoddyKit PROhon. React Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Diskriminoidut unionit komponenttivarianteille”?
Mallintakaa varianttipropsit diskriminoiduilla unioneilla, jotta TypeScript valvoo kelvollisia propsiyhdistelmiä. Harjoittelet React Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni React Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin React Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.
Kuinka kauan ”Diskriminoidut unionit komponenttivarianteille”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä React Academy-oppitunnilla?
Kyllä. Jokainen React Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Diskriminoidut unionit komponenttivarianteille
- Ehdolliset ja mappautuvat tyypit Reactissa
- Polymorfiset komponentit 'as'-propilla
- Tyyppiturvalliset lomakkeet ja API-vastaussopimukset