【问题标题】:Typescript generic type for nested object properties嵌套对象属性的打字稿泛型类型
【发布时间】:2021-12-06 02:19:16
【问题描述】:

我想实现这样的事情,以便可以推断出Component 的类型,从而可以自动安全地键入props

type ComponentsType<T extends React.FC<any>> {
  [key: string]: {
    Component: T;
    props?: React.ComponentProps<T>
  };
}

const components: ComponentsType = {
   RedButton: {
      Component: Button,
      props: { // <- this should be automatically typed to take props of Button
        color: 'red'
      }
   },
   BlueButton: {
      Component: Button,
      props: { // <- this should be automatically typed to take props of Button
         color: 'blue'
      }
   },
   FullWidthCard: {
      Component: Card,
      props: { // <- this should be automatically typed to take props of Card
         variant: 'full-width'
      }
   },
}

但上面的输入不起作用,因为通用部分位于对象 AKA components 的根上,而不是在每个属性 AKA RedButtonFullWidthCard 上。

那么有没有办法让 typescript 一个一个地遍历它们并一个个地推断出组件?

谢谢

【问题讨论】:

    标签: reactjs typescript type-inference


    【解决方案1】:

    为了实现预期的行为,您需要从函数参数中推断出每个组件和道具。我的意思是,你需要创建一个额外的函数。

    import React, { FC, ComponentProps } from 'react'
    
    
    const Button: FC<{ color: string }> = (props) => null
    const Card: FC<{ variant: string }> = (props) => null
    
    
    type WithProps<T> =
        T extends Record<infer Key, infer _> ? {
            [P in Key]: T[Key] extends { Component: infer Comp, props: infer PassedProps }
            ? Comp extends React.JSXElementConstructor<infer Prps>
            ? { Component: Comp, props: ComponentProps<Comp> & Record<Exclude<keyof PassedProps, keyof Prps>, never> }
            : never
            : never
        } : never
    
    
    const components = <
        Comp extends React.JSXElementConstructor<any>,
        Item extends { Component: Comp },
        Components extends Record<string, Item>>(dictionary: Components & WithProps<Components>) => {}
    
    

    Playground

    Comp - 推断组件

    Item - 推断字典项,component&amp;props 对象

    Components - 推断出整个论点。

    WithProps - 遍历传递参数的每个对象并检查 props obhect 是否可分配给组件道具。如果是 - 返回道具,否则将所有无效道具否定为never

    components({
        RedButton: {
            Component: Button,
            props: {
                color: 'red'
            }
        },
        BlueButton: {
            Component: Button,
            props: {
                extra_prop:42, // DRAWBACK, no error
                color: 'blue'
            }
        },
        FullWidthCard: {
            Component: Card,
            props: {
                variant_invalid_prop: 'full-width' // expected error
            }
        },
    })
    

    但是有个缺点,这个函数会接受额外的道具,比如extra_prop

    附:我希望有人能提出更好的解决方案,额外的道具也会无效

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 2021-06-19
      • 2019-03-12
      • 2021-12-30
      • 2021-09-10
      • 1970-01-01
      • 2020-12-17
      相关资源
      最近更新 更多