react 组件props的特定类型不导出 在开发当中,我们如何获取react组件的props属性呢

222 阅读4分钟

react 组件props的特定类型不导出

  • 在开发当中,我们为了保证我们的props 的完整性,也保证代码后续不会因为props的类型而导致不必要的错误,这个时候我们通常就会给props定义类型

    这是一个简单的props的接口类型,定义了我们props当中需要接受参数的类型

    interface SortProps {
        title: React.ReactNode, 
        bottom: ReactNode,
        sortList: Array<SortItem>,
        sortType:SortType,
        hoverUnderLine:boolean | string
    }
    
  • 通常,我们在项目当中开发的组件,我们都可以选择导出或者不导出我们的props类型(这完全取决于我们的一个需求)

    像我的话,我一般会在组件的上方定义组件的props类型,或者是在组件导出的使用使用propTypes(www.npmjs.com/package/pro…) 定义组件的props 属性,然后导出

    ,因为在我们使用组件的时候,有的时候需要扩展组件的props属性,比如一些高阶组件,我们可以定义可配置的props,然后高阶组件内部会定义基本的props,然后将两者结合起来使用。

  • 但是,在别人的组件库当中,如果别人不导出他的组件类型,但是ts 有会自动检查你传入的参数类型,如果是简单的参数,可以使用基本的数据类型可以,但是类型只要足够复杂,就会产生让我们很难受的问题了。

    type Icon = `${IconCollections}:${string}`;
    

这里umiJS 内部通过icon插件生成的Icon 组件里面props 的类型

IconCollections 是一个图标集的类型,可以理解为一个枚举类型(这个枚举的数量还是有点大,里面使用了 | 运算符, 而不是 enum 枚举符)

这个类型umi没有把他进行导出,所以我们使用的时候只能这样传

  • 这里用ant 图标举个例子

      <Icon icon="ant-design:search-outlined" className="w-6 h-6" />
    

    我们需要传这种图标集加字符串的形式,就很离谱,因为我们有的时候想要传一个变量进去(图标大部分时候都写死的,或者是不同的图标封装成不同的组件),这个时候如何来定义这个变量的类型呢,我们基本上定义不了,你定义字符串无法分配,你可以定义成字符串:字符串,但是这种数据格式你觉得对吗?肯定不行,因为前面使用了特定的类型变量,要不你就把人家的枚举值一个个写一份在你本地,你可不要想着你去修改人家的源文件呀,人家的这个文件是临时文件,是项目初始化的时候为了后续直接拿到结果,所以你即使这次修改了,你下次呢,还要去修改一次?

    • 既然我们不能修改,只能想办法获取到里面的props类型了,那如何获取了,不要忘了react 的组件实质上就是一个函数,所以我们只需要获取这个函数参数的类型不就可以了吗

      React 给我们提供了方法去获取组件的props类型

      //Icon 是umi 内置的图标组件(用起来有点恶心)
      type iconName = React.ComponentProps<typeof Icon>
       // iconName 就是返回的组件props类型
      

      如果我们想要获取类型对象上的具体某个属性的类型,就可以使用[],填写属性名的方式,去获取

    • 接下来就让我们来看看react是如何实现的吧,其实也很简单,只要你知道infer 这个关键字,我相信没有react的帮助,你也可以

      infer 是用来获取我们变量的类型的(需要配合extends使用)

          type ComponentProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = T extends
              JSXElementConstructor<infer P> ? P
              : T extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[T]
              : {};
      

      让我们来解读一下这段代码

    • 首先我们需要传递一个类型为jsx元素的类型,作为泛型T,然后跟着一个extends的三目,如果这个泛型T 是继承ljsx 元素构造方法的话,就会返回这个p,而infer的作用就是将jsx 构造函数里面的泛型(也就是props的类型)赋值给了p,所以我们就可以拿到组件props的类型了