React Academy · leksjon

Generiske komponenter og utility-typer

Skriv gjenbrukbare generiske komponenter, og bruk PropsWithChildren, ComponentProps og Omit.

Leksjon 3 av 413 trinn

Generiske komponenter og utility-typer er en gratis leksjon i React Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i React Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i React Academy inneholder totalt 4 leksjoner.

Hvorfor generiske komponenter?

Generiske komponenter tilpasser seg ulike datatyper samtidig som de beholder full typesikkerhet – for eksempel en typet liste, velger eller tabell som fungerer med alle datastrukturer.

En enkel generisk liste

Bruk typeparameteren T på funksjonen for å lage en listekomponent som gjengir elementer av alle typer.

interface ListProps<T> {
  items: T[];
  renderItem: (item: T, index: number) => React.ReactNode;
  keyExtractor: (item: T) => string;
}

function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
  return (
    <ul>
      {items.map((item, i) => (
        <li key={keyExtractor(item)}>{renderItem(item, i)}</li>
      ))}
    </ul>
  );
}

Begrensning av generiske typer

Bruk extends for å legge til begrensninger, slik at TypeScript vet hvilke egenskaper typen må ha.

interface SelectProps<T extends { id: string; label: string }> {
  options: T[];
  value: T | null;
  onChange: (option: T) => void;
}

function Select<T extends { id: string; label: string }>(
  { options, value, onChange }: SelectProps<T>
) {
  return (
    <select value={value?.id} onChange={e => onChange(options.find(o => o.id === e.target.value)!)}>
      {options.map(o => <option key={o.id} value={o.id}>{o.label}</option>)}
    </select>
  );
}

PropsWithChildren

React.PropsWithChildren<P> legger children?: React.ReactNode til enhver props-type – nyttig for wrapper-komponenter.

function Card({ title, children }: React.PropsWithChildren<{ title: string }>) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

ComponentProps

React.ComponentProps<typeof Component> trekker ut propsene til en eksisterende komponent. Dette er nyttig når De vil utvide eller pakke inn komponenten.

import { Button } from './Button';

type ExtendedButtonProps = React.ComponentProps<typeof Button> & {
  loading?: boolean;
};

function LoadingButton({ loading, children, ...props }: ExtendedButtonProps) {
  return (
    <Button {...props} disabled={loading || props.disabled}>
      {loading ? <Spinner /> : children}
    </Button>
  );
}

ComponentPropsWithoutRef

React.ComponentPropsWithoutRef<'input'> trekker ut props for HTML-elementet uten ref-propen – ideelt for innpakking av HTML-elementer.

type InputProps = React.ComponentPropsWithoutRef<'input'> & {
  label: string;
  error?: string;
};

function FormInput({ label, error, ...inputProps }: InputProps) {
  return (
    <div>
      <label>{label}</label>
      <input {...inputProps} />
      {error && <span className="error">{error}</span>}
    </div>
  );
}

Omit og Pick

Bruk Omit<T, Keys> for å fjerne bestemte props og Pick<T, Keys> for å beholde bare bestemte props fra en eksisterende type.

interface UserCardProps {
  id: string;
  name: string;
  email: string;
  avatar: string;
  role: string;
}

// Only expose non-sensitive fields:
type PublicUserCardProps = Omit<UserCardProps, 'email' | 'role'>;
// Or pick exactly what you need:
type AvatarProps = Pick<UserCardProps, 'name' | 'avatar'>;

Partial og Required

Partial<T> gjør alle props valgfrie, noe som er nyttig i oppdateringsskjemaer. Required<T> gjør alle props obligatoriske.

interface UserFormData { name: string; email: string; bio: string; }

// For update: only send changed fields
type UserUpdatePayload = Partial<UserFormData>;

// For create: all fields are mandatory
type UserCreatePayload = Required<UserFormData>;

Record for typede ordbøker

Record<Keys, Value> oppretter en objekttype med bestemte nøkkeltyper, noe som er nyttig for oppslagstabeller og oversettelser.

type Status = 'idle' | 'loading' | 'success' | 'error';

const statusLabels: Record<Status, string> = {
  idle: 'Ready',
  loading: 'Loading...',
  success: 'Done!',
  error: 'Something went wrong',
};

ReturnType for hook-typer

Bruk ReturnType<typeof useMyHook> for å utlede returtypen til en egendefinert hook uten å duplisere typen manuelt.

function useCounter(initial: number) {
  const [count, setCount] = useState(initial);
  return { count, increment: () => setCount(c => c + 1) };
}

type CounterHook = ReturnType<typeof useCounter>;
// { count: number; increment: () => void }

Generisk tabellkomponent

En fullstendig typesikker datatabell som fungerer med alle radstrukturer, utleder kolonnenøkler og fortsatt tilbyr autoutfylling.

interface Column<T> {
  key: keyof T;
  header: string;
  render?: (value: T[keyof T], row: T) => React.ReactNode;
}

function DataTable<T extends object>({ data, columns }: { data: T[]; columns: Column<T>[] }) {
  return (
    <table>
      <thead><tr>{columns.map(c => <th key={String(c.key)}>{c.header}</th>)}</tr></thead>
      <tbody>{data.map((row, i) => (
        <tr key={i}>{columns.map(c => <td key={String(c.key)}>{c.render ? c.render(row[c.key], row) : String(row[c.key])}</td>)}</tr>
      ))}</tbody>
    </table>
  );
}

Hurtigsjekk

Hvilken utility-type fjerner angitte nøkler fra et eksisterende TypeScript-grensesnitt?

Oppsummering

Generiske komponenter bruker typeparametere for å beholde typesikkerheten på tvers av datastrukturer. Utility-typer som Omit, Pick, Partial, ComponentProps og PropsWithChildren eliminerer manuell typeduplisering og gjør komponent-API-er mer komponerbare.

Gratis å komme i gang

Lær deg React med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
88
Leksjoner
324

Ofte stilte spørsmål

Er leksjonen «Generiske komponenter og utility-typer» gratis?

Ja – hele teksten i «Generiske komponenter og utility-typer» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av React Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i React Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Generiske komponenter og utility-typer»?

Skriv gjenbrukbare generiske komponenter, og bruk PropsWithChildren, ComponentProps og Omit. Du øver på React Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med React Academy?

Ingen tidligere erfaring er nødvendig. React Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Generiske komponenter og utility-typer»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne React Academy-leksjonen?

Ja. Alle React Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Type props og returtyper for komponenter
  2. Type events og refs i TypeScript
  3. Generiske komponenter og utility-typer
  4. Type Context og egendefinerte hooks
← Tilbake til React Academy