[英]Typescript React: Access component property types
npm package @types/react
allows us to use React inside of our TypeScript apps. npm包
@types/react
允许我们在TypeScript应用程序内部使用React。 We define components as 我们将组件定义为
type Props = {...}
type State = {...}
export default class MyComponent extends React.Component<Props, State> {
}
here we have to declare types for component props and state (in type variables). 在这里,我们必须声明组件属性和状态的类型(在类型变量中)。
After we declared that types, TypeScript uses that to validate the usage of our component (the shape of props passed to it). 在声明了这些类型之后,TypeScript将使用该类型来验证组件的用法(传递给它的道具的形状)。
I want to create a container around such a component. 我想围绕这样的组件创建一个容器。 The container will reuse the props of the component.
容器将重复使用组件的道具。 But in order to create another component with the same props I have to redeclare the types for props again.
但是,为了用相同的道具创建另一个组件,我必须再次声明道具的类型。 Or export them from the original component file and import into container:
或从原始组件文件中导出它们并导入到容器中:
// original file
export type Props = {...}
// container file
import MyComponent, { Props } from './original'
But I'm already importing the MyComponent
from that file. 但是我已经从该文件导入
MyComponent
。 This component already contains information about the props it consumes (thanks to type variables in React.Component
). 这个组件已经包含了消耗道具的信息(感谢在
React.Component
输入变量)。
The question is how do I access that information from the component class itself without explicitly exporting/importing the type for props ? 问题是如何在不显式导出/导入道具类型的情况下从组件类本身访问该信息 ?
I want something like: 我想要类似的东西:
import MyComponent from './MyComponent'
type Props = MyComponent.Props // <= here access the component prop types
export default class MyContainer extends React.Component<Props, {}> {}
2019 : noticed all answers above are quite outdated so here is a fresh one. 2019 :注意到上面的所有答案都已经过时了,所以这里是一个新鲜的答案。
With newer TS versions you can use lookup types. 使用较新的TS版本,您可以使用查找类型。
type ViewProps = View['props']
Despite being very convenient, that will only work with class components . 尽管非常方便,但这仅适用于类组件 。
The React typedefs ship with an utility to extract the type of the props from any component. React typedef附带了一个实用程序,可从任何组件中提取道具的类型。
type ViewProps = React.ComponentProps<typeof View>
type InputProps = React.ComponentProps<'input'>
This is a bit more verbose, but unlike the type lookup solution: 这有点冗长,但是与类型查找解决方案不同:
All this makes this solution the most future-proof one: if you decide to migrate from classes to hooks, you won't need to refactor any client code. 所有这些使该解决方案成为最可靠的解决方案:如果您决定从类迁移到挂钩,则无需重构任何客户端代码。
Starting with TypeScript 2.8, you can use conditional types, eg given: 从TypeScript 2.8开始,可以使用条件类型,例如:
interface MyComponentProps { bar: string; }
declare const MyComponent: React.Component<MyComponentProps>;
interface MyComponentClassProps { bar: string; }
declare const MyComponentClass: React.ComponentClass<MyComponentClassProps>;
interface MyStatelessComponentProps { bar: string; }
declare const MyStatelessComponent: React.StatelessComponent<MyStatelessComponentProps>;
We can define these helpers: 我们可以定义以下助手:
type GetComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P> ? P : never
And use them like so: 并像这样使用它们:
// $ExpectType MyComponentProps
type MyComponentPropsExtracted = GetComponentProps<typeof MyComponent>
// $ExpectType MyComponentClassProps
type MyComponentClassPropsExtracted = GetComponentProps<typeof MyComponentClass>
// $ExpectType MyStatelessComponentProps
type MyStatelessComponentPropsExtracted = GetComponentProps<typeof MyStatelessComponent>
Update 2018-12-31 : this is now available in the official React typings via React.ComponentProps
. 更新2018-12-31 :现在可以通过
React.ComponentProps
在官方的React React.ComponentProps
。
To take a type of properties from component 从组件中获取一种属性
type Props = typeof MyComponent.defaultProps;
You can ask yourself why I'm taking typeof from defaultProps and not from propTypes. 您可以问自己为什么我要从defaultProps而不是propTypes获取typeof。 To explain that lets take a look at the definition file
为了说明这一点,让我们看一下定义文件
interface ComponentClass<P> {
new(props?: P, context?: any): Component<P, ComponentState>;
propTypes?: ValidationMap<P>;
contextTypes?: ValidationMap<any>;
childContextTypes?: ValidationMap<any>;
defaultProps?: P;
displayName?: string;
}
As you can see propTypes are wrapped in ValidationMap and it's not easy to get raw types. 如您所见,propTypes包装在ValidationMap中,获取原始类型并不容易。 Fortunately, defaultProps have raw types
幸运的是,defaultProps具有原始类型
Given a React component: 给定一个React组件:
import React, { ComponentType, StatelessComponent } from 'react';
const MyComponent: StatelessComponent<{ foo: string }> = props => <div>{props.foo}</div>;
You can do: 你可以做:
const getProps = function<Props> (_MyComponent: ComponentType<Props>): Props {
return {} as Props;
};
const props = getProps(MyComponent);
// { foo: string; }
type MyComponentProps = typeof props;
Alternatively, you can augment the React typings to add a GetComponentProps
helper: 另外,您可以增加React类型以添加
GetComponentProps
帮助器:
import React from 'react';
type NonNullable < T > = T & {};
declare module 'react' {
// Add helper for accessing props type of given component. Based off of
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24182.
type GetComponentProps < C extends ComponentType < any > > = NonNullable<C['_doNotUse_props']>;
// We use interface merging to append properties to these types
interface StatelessComponent<P = {}> {
// eslint-disable-next-line camelcase
_doNotUse_props?: P;
}
interface ComponentClass<P = {}> {
// eslint-disable-next-line camelcase
_doNotUse_props?: P;
}
}
Usage looks like this: 用法如下所示:
// { foo: string; }
type MyComponentProps = React.GetComponentProps<typeof MyComponent>;
I originally posted this in https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24182 . 我最初将此内容发布在https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24182中 。
That's my solution of how to get props from component 这是我如何从组件中获取道具的解决方案
type Propsable = {
FC: React.FC;
C: React.Component;
CC: React.ComponentClass<any>;
F: (...args: any) => any;
}
type PropsOfFC<C extends Propsable["FC"]> = {
[K in keyof C["propTypes"]]: C["propTypes"][K] extends React.Validator<infer P>
? P
: K
};
type PropsOfF<C extends Propsable["F"]> = Parameters<C>[0]
type PropsOfC<C extends Propsable["C"]> = C extends React.Component<infer P> ? P : never;
type PropsOfCC<C extends Propsable["CC"]> = C extends React.ComponentClass<infer P> ? P : never;
type PropsOf<C extends ValueOf<Propsable>> =
C extends Propsable["FC"] ? PropsOfFC<C> :
C extends Propsable["C"] ? PropsOfC<C> :
C extends Propsable["CC"] ? PropsOfCC<C> :
C extends Propsable["F"] ? PropsOfF<C> : any;
If you use functional component, class component or styled component that solution should help you. 如果您使用功能组件,类组件或样式化组件,则该解决方案应为您提供帮助。
How to use: 如何使用:
type Props = PropsOf<typeof YourComponent>
You can add this to 'react.d.ts' 您可以将其添加到“ react.d.ts”
You can use import * as
syntax: 您可以使用
import * as
语法:
import * as MC from './MyComponent';
type Props = MC.Props;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.