Reactjs 类型脚本:访问组件属性类型
npm包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中的类型变量) 问题是如何从组
@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>