有没有办法提取 JSX 元素的props类型?

IT技术 reactjs typescript jsx typescript-typings typescript-generics
2021-05-09 00:11:20

我的目的是从给定的 JSX 元素中提取props,这可能吗?

这几乎是我失败的尝试......在此先感谢您的帮助;)

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
3个回答

在大多数情况下,你不能这样做。

理论上,该React.ReactElement类型是通用与一类参数P取决于props。所以如果你有一个强类型元素,那么你可以逆向工作。

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

现实中,如果通过创建元素,你只会得到一个正确的props类型React.createElement,而不是JSX。

任何 JSX 元素都<Component name="John" />只是获取JSX.Element显然没有关于 props 的信息的类型,所以你不能从那个向后工作到 props 类型。

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"}

游乐场链接

从不同的角度处理情况要容易得多。如果您的函数采用类似Componentdiv而不是已解析元素的组件,您将能够派生出正确的 props 类型您可以将ComponentProps实用程序类型用于函数和类组件,而将JSX.IntrinsicElements映射用于内置组件

您可以使用以下命令提取任何组件的props类型

React.ComponentProps<typeof T>

您可以参考此TS Playground以获取更多选项

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>;

`

这对 来说是不可能的getComponentProps(<Component name="jon" />);,因为写出的 JSX-Elements 总是导致JSX.Element-type 不提供您可以提取的任何其他类型信息。如果您从组件函数本身中提取它是可能的:

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

function getComponentProps<T extends (...args: any[]) => JSX.Element>(element: T): Parameters<T>[0] {
    return null as any;
}

const test = getComponentProps(Component); // { name: string;}

此解决方案使用实用程序类型parameter,它从函数中推断出所有参数。然后我们索引第一个参数,因为 prop 对象是纯 jsx 函数的第一个参数。不过,类组件需要不同的解决方案。