0Pricing
React Academy · Lezione

Componenti polimorfici con la prop 'as'

Tipizzi la prop 'as' affinché un Button venga renderizzato come o , mantenendo i tipi corretti delle props.

Componenti polimorfici con la prop 'as' è una lezione React Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento React Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso React Academy include 4 lezioni in totale.

Che cos'è un componente polimorfico

Un componente polimorfico esegue il rendering come elementi o componenti HTML diversi in base a una prop as, ad esempio un Button che viene renderizzato come <a> o <button> mantenendo i tipi TypeScript corretti.

Prop as semplice (senza TypeScript)

Un'implementazione polimorfica di base senza generics: perde la sicurezza dei tipi, ma mostra il concetto.

function Box({ as: Tag = 'div', children, ...props }) {
  return <Tag {...props}>{children}</Tag>;
}

// Usage:
<Box as="section" className="hero">...</Box>
<Box as="article">...</Box>

Prop as tipizzata con i generics

Aggiunga un parametro di tipo generico per inferire le props corrette per qualunque elemento venga usato da as.

type PolymorphicProps<E extends React.ElementType> = {
  as?: E;
} & Omit<React.ComponentPropsWithoutRef<E>, 'as'>;

function Box<E extends React.ElementType = 'div'>({
  as,
  ...props
}: PolymorphicProps<E>) {
  const Tag = as ?? 'div';
  return <Tag {...props} />;
}

Supporto a ref

Aggiunga il supporto a forwardRef preservando la tipizzazione polimorfica.

type PolymorphicRef<E extends React.ElementType> = React.ComponentPropsWithRef<E>['ref'];

type PolymorphicPropsWithRef<E extends React.ElementType, P = {}> = P &
  Omit<React.ComponentPropsWithRef<E>, keyof P> & { as?: E };

const Button = React.forwardRef(
  <E extends React.ElementType = 'button'>(
    { as, ...props }: PolymorphicPropsWithRef<E>,
    ref: PolymorphicRef<E>
  ) => {
    const Tag = as ?? 'button';
    return <Tag ref={ref} {...props} />;
  }
);

L'inferenza di TypeScript in azione

Quando imposta as='a', TypeScript sa che il componente accetta props specifiche degli anchor, come href e target, ma non quelle specifiche dei pulsanti, come disabled.

// TypeScript allows href because as='a':
<Box as="a" href="https://example.com">Link</Box>

// TypeScript errors if you pass href to a div:
<Box as="div" href="...">Error!</Box> // TS: href is not a valid div prop

Estendere con props personalizzate

Aggiunga props specifiche del componente accanto alla base polimorfica includendole nella definizione del tipo.

type TextProps<E extends React.ElementType> = PolymorphicProps<E> & {
  size?: 'sm' | 'md' | 'lg';
  weight?: 'normal' | 'bold';
};

function Text<E extends React.ElementType = 'p'>({
  as,
  size = 'md',
  weight = 'normal',
  className,
  ...props
}: TextProps<E>) {
  const Tag = as ?? 'p';
  return (
    <Tag
      className={[`text-${size}`, `font-${weight}`, className].filter(Boolean).join(' ')}
      {...props}
    />
  );
}

Caso d'uso reale: Link renderizzato come RouterLink

Un Button che viene renderizzato come Link di React Router quando viene fornita to, oppure come semplice pulsante in caso contrario.

import { Link } from 'react-router-dom';

type ButtonProps =
  | { to: string; href?: never } & React.ComponentPropsWithoutRef<typeof Link>
  | { href: string; to?: never } & React.ComponentPropsWithoutRef<'a'>
  | { to?: never; href?: never } & React.ComponentPropsWithoutRef<'button'>;

function Button({ to, href, ...props }: ButtonProps) {
  if (to) return <Link to={to} {...props} />;
  if (href) return <a href={href} {...props} />;
  return <button type="button" {...props} />;
}

Componente Text per un design system

Un componente polimorfico Text che per impostazione predefinita usa <p>, ma può essere renderizzato come h1–h6, span o label.

<Text as="h1" size="xl">Page Title</Text>
<Text as="span" weight="bold">Inline bold</Text>
<Text as="label" htmlFor="email">Email</Text> // htmlFor is valid because as='label'

Vincoli sulla prop as

Utilizzi extends React.ElementType per accettare sia stringhe di elementi HTML ('div', 'a') sia componenti React.

function Card<E extends React.ElementType = 'div'>({ as, ...props }: PolymorphicProps<E>) {
  const Tag = as ?? 'div';
  return <Tag {...props} />;
}

// Works with HTML elements:
<Card as="section" aria-label="Products" />
// Works with React components:
<Card as={motion.div} animate={{ opacity: 1 }} />

Evitare gli errori più comuni

Non distribuisca la prop as sull'elemento, perché non è un attributo HTML valido. La estragga sempre prima di distribuire le props rimanenti.

// Bad:
function Box({ as: Tag = 'div', ...props }) {
  return <Tag as={...} {...props} />; // 'as' attribute on div is invalid HTML
}

// Good:
function Box({ as: Tag = 'div', ...props }) {
  return <Tag {...props} />; // 'as' is used to pick Tag, not passed to element
}

Considerazioni sulle prestazioni

I componenti polimorfici hanno un overhead minimo in termini di prestazioni: la prop as è semplicemente una variabile che contiene una stringa del tipo di elemento o un riferimento a un componente.

Verifica rapida

Perché è necessario estrarre la prop as prima di distribuire le props rimanenti sull'elemento in un componente polimorfico?

Riepilogo

I componenti polimorfici usano una prop generica as?: E extends React.ElementType per eseguire il rendering come qualunque elemento mantenendo le props TypeScript corrette. Estragga as prima di distribuire le props rimanenti. Utilizzi React.ComponentPropsWithoutRef per includere nel tipo tutti gli attributi specifici dell'elemento.

Domande Frequenti

La lezione «Componenti polimorfici con la prop 'as'» è gratuita?

Sì — il testo completo di «Componenti polimorfici con la prop 'as'» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso React Academy, passa a CoddyKit PRO. Il corso React Academy include 4 lezioni in totale.

Cosa imparerò in «Componenti polimorfici con la prop 'as'»?

Tipizzi la prop 'as' affinché un Button venga renderizzato come o , mantenendo i tipi corretti delle props. Eserciti React Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare React Academy?

Non è richiesta alcuna esperienza precedente. React Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Componenti polimorfici con la prop 'as'»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione React Academy?

Sì. Ogni lezione React Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Unioni discriminate per le varianti dei componenti
  2. Tipi condizionali e mappati in React
  3. Componenti polimorfici con la prop 'as'
  4. Form type-safe e contratti delle risposte API
← Torna a React Academy