繁体   English   中英

嵌套对象属性的 Typescript 泛型类型

[英]Typescript generic type for nested object properties

我想实现这样的事情,以便可以推断出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

那么有没有办法让打字稿一一运行它们并一一推断组件?

谢谢

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

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>) => {}

操场

Comp - 推断组件

Item - 推断的字典项、 component&props对象

Components - 推断整个参数。

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

PS我希望有人能提出更好的解决方案,其中额外的道具也将无效

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM