Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 类型脚本:访问组件属性类型_Reactjs_Typescript - Fatal编程技术网

Reactjs 类型脚本:访问组件属性类型

Reactjs 类型脚本:访问组件属性类型,reactjs,typescript,Reactjs,Typescript,npm包@types/react允许我们在TypeScript应用程序中使用react。 我们将组件定义为 type Props = {...} type State = {...} export default class MyComponent extends React.Component<Props, State> { } 但是我已经从该文件导入了MyComponent。此组件已包含有关其使用的道具的信息(由于React.component中的类型变量) 问题是如何从组

npm包
@types/react
允许我们在TypeScript应用程序中使用react。 我们将组件定义为

type Props = {...}

type State = {...}

export default class MyComponent extends React.Component<Props, State> {
}
但是我已经从该文件导入了
MyComponent
。此组件已包含有关其使用的道具的信息(由于
React.component
中的类型变量)

问题是如何从组件类本身访问该信息,而不显式地导出/导入道具的类型

我想要像这样的东西:

import MyComponent from './MyComponent'

type Props = MyComponent.Props // <= here access the component prop types

export default class MyContainer extends React.Component<Props, {}> {}
从“./MyComponent”导入MyComponent

type Props=MyComponent.Props//从组件获取属性类型

type Props = typeof MyComponent.defaultProps;

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;


你可以问问自己,为什么我从defaultProps而不是propTypes中选择typeof。为了解释这一点,让我们看看定义文件

  interface ComponentClass<P> {
        new(props?: P, context?: any): Component<P, ComponentState>;
        propTypes?: ValidationMap<P>;
        contextTypes?: ValidationMap<any>;
        childContextTypes?: ValidationMap<any>;
        defaultProps?: P;
        displayName?: string;
    }
接口组件类

{ 新(道具?:P,上下文?:任意):组件; propTypes?:ValidationMap

; contextTypes?:ValidationMap; childContextTypes?:ValidationMap; defaultProps?:P; displayName?:字符串; }


正如您所看到的,PropType被包装在ValidationMap中,获取原始类型并不容易。幸运的是,给定React组件,DefaultProp具有原始类型

import React, { ComponentType, StatelessComponent } from 'react';

const MyComponent: StatelessComponent<{ foo: string }> = props => <div>{props.foo}</div>;
用法如下所示:

// { foo: string; }
type MyComponentProps = React.GetComponentProps<typeof MyComponent>;
/{foo:string;}
键入MyComponentProps=React.GetComponentProps;

我最初在中发布了此内容。

从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>;
接口MyComponentProps{bar:string;}
声明常量MyComponent:React.Component;
接口MyComponentClassProps{bar:string;}
声明常量MyComponentClass:React.ComponentClass;
接口MyStatelessComponentProps{bar:string;}
declare const MyStatelessComponent:React.StatelessComponent;
我们可以定义这些帮助程序:

type GetComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P> ? P : never
type GetComponentProps=T扩展React.ComponentType | React.Component?P:从来没有
并像这样使用它们:

// $ExpectType MyComponentProps
type MyComponentPropsExtracted = GetComponentProps<typeof MyComponent>

// $ExpectType MyComponentClassProps
type MyComponentClassPropsExtracted = GetComponentProps<typeof MyComponentClass>

// $ExpectType MyStatelessComponentProps
type MyStatelessComponentPropsExtracted = GetComponentProps<typeof MyStatelessComponent>
/$ExpectType MyComponentProps
类型myComponentPropseTracted=GetComponentProps
//$ExpectType MyComponentClassProps
类型myComponentClassPropseTracted=GetComponentProps
//$ExpectType MyStatelessComponentProps
键入myStatelessComponentPropseTracted=GetComponentProps

更新2018-12-31:现在可通过
React.ComponentProps
2019:注意到上述所有答案都已过时,因此这里是一个新答案


查找类型 对于较新的TS版本,您可以使用查找类型

type ViewProps = View['props']
尽管非常方便,但这将仅适用于类组件


反应,反应 React-typedefs附带一个实用程序,用于从任何组件中提取道具类型

type ViewProps = React.ComponentProps<typeof View>

type InputProps = React.ComponentProps<'input'>
type ViewProps=React.ComponentProps
类型InputProps=React.ComponentProps
这有点冗长,但与类型查找解决方案不同:

  • 开发者的意图更加明确
  • 这将适用于功能组件和类组件

所有这些都使这个解决方案成为了未来最可靠的解决方案:如果你决定从类迁移到钩子,你就不需要重构任何客户机代码。

这是我关于如何从组件中获取道具的解决方案

type Props = typeof MyComponent.defaultProps;

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;



类型可扩展={
FC:React.FC;
C:反应组分;
CC:React.ComponentClass;
F:(…args:any)=>any;
}
类型PropsOfFC={
[K]在C[“propTypes”]]的键中:C[“propTypes”][K]扩展了React.Validator
P
:K
};
类型PropsOfF=参数[0]
类型PropsOfC=C.Component?P:从来没有;
类型PropsOfCC=C扩展了React.ComponentClass?P:从来没有;
类型道具=
C扩展可扩展[“FC”]?Propsofc:
C扩展可扩展[“C”]?PropsOfC:
C扩展可扩展[“CC”]?PropsOfCC:
C扩展可扩展[“F”]?PropsOfF:任何;
如果您使用功能组件、类组件或样式化组件,该解决方案将对您有所帮助。
如何使用:

type Props = PropsOf<typeof YourComponent>
类型Props=PropsOf

您可以将此添加到“react.d.ts”

酷!谢谢虽然这不是一种获取类型的显式方法,但它目前仍然有效(直到作者重构实现)。不幸的是,这不再有效,因为
defaultProps
现在有一种类型是
Partial

@OliverJosephAsh,这是正确的。如果您确实需要,您可以使用模块扩充来扩展react类型,以放置虚拟类型,从而允许您获取道具类型。在
Module Augmentation
部分下查看typescript新手,他们可能也会被我错过的东西绊倒:React.ComponentProps将仅在类型表达式内部定义-因此类型的右侧=,或者在通常放置接口或类型的任何地方,比如键入函数的参数如果将其与泛型一起使用,则泛型必须如下所示:
T extensed React.FC | React.ComponentClass
,然后您将能够执行此操作:
type PropType=React.ComponentProps你好。从2019年起,您应该使用此解决方案。其他解决方案可以工作,但不是最新和最经得起未来考验的解决方案:您甚至可以通过在那里传递字符串
React.ComponentProps
来获得本机元素的道具,如
。谢谢:)不幸的是,这不适用于像
typeof View这样的泛型组件!但是,它不考虑
defaultProps
。这个是:
键入MyCompProps=JSX.LibraryManagedAttributes
。查看如何在通用接口中编写类似的内容。。。儿童:(props:React.ComponentProps)=>TComponent;?其中t组件扩展了React.reactNode可能
PropsOfFC
可以是
参数[0]
type Props = PropsOf<typeof YourComponent>