reactjs - Finns det ett sätt att extrahera typen av props för ett JSX-element?


Min avsikt är att extrahera props från ett givet JSX-element, är det möjligt?

Detta var i princip mitt misslyckade försök... Tack på förhand för all hjälp ;)

function getComponentProps<T extends React.ReactElement>(element: T): ExtractProps<T>;

function Component({ name }: { name: string }) {
  return <h1>{name}</h1>;
}

type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends React.ComponentType<infer TProps>
  ? TProps
  : TComponentOrTProps;

const componentProps = getComponentProps(<Component name="jon" />); //type is JSX.Element

Svar #1

För det mesta kan du inte göra detta.

I teori är React.ReactElement-typen generisk med en typparameter P som beror på props. Så om du skulle ha ett starkt typat element skulle du kunna arbeta baklänges.

type ElementProps<T extends React.ReactNode> = T extends React.ReactElement<infer P> ? P : never;

I verkligheten får du endast en korrekt props-typ om du skapar ditt element genom React.createElement istället för JSX.

Alla JSX-element <Component name="John" /> får bara typen JSX.Element vilket uppenbarligen inte har någon information om props, så du kan inte arbeta bakåt från det till en props-typ.

const e1 = React.createElement(
  Component,
  { name: 'John' }
)

type P1 = ElementProps<typeof e1> // type: {name: string}

console.log(getElementProps(e1)); // will log {name: "John"}
const e2 = <Component name="John" />

type P2 = ElementProps<typeof e2>  // type: any

console.log(getElementProps(e2)); // will log {name: "John"}

Lekplatslänk

Det är mycket lättare att närma sig situationen från en annan vinkel. Du kommer att kunna härleda rätt props-typ om din funktion tar en komponent som Component eller div snarare än ett löst element. Du kan använda hjälpverktygstypen ComponentProps för funktions- och klasskomponenter och kartan JSX.IntrinsicElements för inbyggda.

Svar #2

Du kan extrahera typen av Props för vilken komponent som helst med

React.ComponentProps<typeof T>

Du kan hänvisa till detta TS Playground för fler alternativ

import * as React from 'react';

type TProps = {
   name:string;
   age:number;
   isStackoverflow:boolean;
 }

const App = (props:TProps) => <div>Hello World</div>;

//You can extract any components props like this.
type AppProps = React.ComponentProps<typeof App>;

`