有没有办法提取 JSX 元素的道具类型?
Is there a way to extract the type of the props of a JSX Element?
我的意图是从给定的 JSX 元素中提取属性,这可能吗?
这几乎是我失败的尝试...
在此先感谢您的帮助 ;)
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
这对于 getComponentProps(<Component name="jon" />);
是不可能的,因为写出的 JSX 元素总是导致 JSX.Element
类型,它不提供任何您可以提取的额外类型信息。如果从组件函数本身中提取它是可能的:
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 函数的第一个参数。不过,Class 组件需要不同的解决方案。
您可以使用
提取任何组件的道具类型
React.ComponentProps<typeof T>
您可以参考此TS Playground以获得更多选项
import * as React from 'react';
type TProps = {
name:string;
age:number;
isWhosebug:boolean;
}
const App = (props:TProps) => <div>Hello World</div>;
//You can extract any components props like this.
type AppProps = React.ComponentProps<typeof App>;
`
在大多数情况下,您不能这样做。
在理论中,React.ReactElement
类型是泛型,类型参数P
依赖于道具。因此,如果您要有一个强类型元素,那么您可以向后工作。
type ElementProps<T extends React.ReactNode> = T extends React.ReactElement<infer P> ? P : never;
在 reality 中,只有通过 React.createElement
而不是 JSX 创建元素才能获得正确的道具类型。
任何 JSX 元素 <Component name="John" />
只获取类型 JSX.Element
,它显然没有关于道具的信息,所以你不能从那个向后工作到道具类型。
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"}
从不同的角度来处理情况要容易得多。如果您的函数采用 Component
或 div
之类的组件而不是已解析的元素,您将能够派生出正确的道具类型。您可以对函数和 class 组件使用 ComponentProps
实用程序类型,对内置组件使用 JSX.IntrinsicElements
映射。
我的意图是从给定的 JSX 元素中提取属性,这可能吗?
这几乎是我失败的尝试... 在此先感谢您的帮助 ;)
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
这对于 getComponentProps(<Component name="jon" />);
是不可能的,因为写出的 JSX 元素总是导致 JSX.Element
类型,它不提供任何您可以提取的额外类型信息。如果从组件函数本身中提取它是可能的:
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 函数的第一个参数。不过,Class 组件需要不同的解决方案。
您可以使用
提取任何组件的道具类型React.ComponentProps<typeof T>
您可以参考此TS Playground以获得更多选项
import * as React from 'react';
type TProps = {
name:string;
age:number;
isWhosebug:boolean;
}
const App = (props:TProps) => <div>Hello World</div>;
//You can extract any components props like this.
type AppProps = React.ComponentProps<typeof App>;
`
在大多数情况下,您不能这样做。
在理论中,React.ReactElement
类型是泛型,类型参数P
依赖于道具。因此,如果您要有一个强类型元素,那么您可以向后工作。
type ElementProps<T extends React.ReactNode> = T extends React.ReactElement<infer P> ? P : never;
在 reality 中,只有通过 React.createElement
而不是 JSX 创建元素才能获得正确的道具类型。
任何 JSX 元素 <Component name="John" />
只获取类型 JSX.Element
,它显然没有关于道具的信息,所以你不能从那个向后工作到道具类型。
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"}
从不同的角度来处理情况要容易得多。如果您的函数采用 Component
或 div
之类的组件而不是已解析的元素,您将能够派生出正确的道具类型。您可以对函数和 class 组件使用 ComponentProps
实用程序类型,对内置组件使用 JSX.IntrinsicElements
映射。