简体   繁体   English

打字稿React:访问组件属性类型

[英]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 :注意到上面的所有答案都已经过时了,所以这里是一个新鲜的答案。


Lookup type 查询类型

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 . 尽管非常方便,但这仅适用于类组件


React.ComponentProps React.ComponentProps

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: 这有点冗长,但是与类型查找解决方案不同:

  • the developer intent is more clear 开发人员的意图更加明确
  • this will work with BOTH functional components and class components 这将与功能组件和类组件一起使用

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.

相关问题 使用 Typescript 反应功能组件:Typescript 不理解更改属性类型 - React Functional component with Typescript: Typescript does not understand changing property types 将反应组件作为属性传递给反应组件时如何定义打字稿类型? - How to define typescript types when passing react component as property to a react component? React Class 组件属性中的 TypeScript 错误在类型“Readonly&lt;{}&gt;”上不存在,不确定如何为 state 设置类型 - TypeScript errors in React Class Component property does not exist on type 'Readonly<{}>', not sure how to set types for state 反应 Typescript 组件与多种道具类型 - React Typescript Component with Multiple Prop Types 使用 Typescript 响应样式组件,类型错误 - React styled-component with Typescript, types error 用于React组件的Typescript prop类型的语法? - Syntax for Typescript prop types for React component? Typescript 中动态 React 组件的条件类型 - Conditional types for a dynamic React component in Typescript 无状态React组件的prop类型的Typescript错误 - Typescript error on prop types of stateless React Component React Component 精确 TypeScript 道具类型 - React Component Exact TypeScript Prop Types React typescript 属性“类型”的类型不兼容 - React typescript Types of property 'type' are incompatible
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM