【问题标题】:Define type based on value of keys in an object根据对象中键的值定义类型
【发布时间】:2021-10-19 05:48:04
【问题描述】:

我正在添加一个具有以下结构的 Select 组件。

type Option = {
  value: string | number
  label: string;
  icon?: string
}
type SelectProps = {
  labelKey?: string;
  iconKey?: string;
  valueKe?: string;
  options: Option[]
}

function Select({
  labelKey = 'label',
  iconKey = 'icon',
  valueKey= 'value',
  groupBy = 'groupBy',
  options// need to type Option
}: SelectProps) {
  // some logic to render options
  // options.map(option => (<li key={option[valueKey]}>{option[labelKey]}</li>))
}

这里,options 是一系列选项,我试图让用户灵活地提供用于标签、图标等的键,这样用户就不需要一直映射数据。

目前,Option 类型具有硬编码键,例如 labelvalueicon,但我想根据传递给 labelKeyvalueKeyiconKey 等的值创建此类型. 例如,如果用户传递了labelKey="name" 属性,那么Option 类型应该允许以下数据:

[ { 
  name: 'Product',
  value: 'product',
  icon: 'product'
}]

到目前为止,我已经尝试了以下实现,但它将所有键的类型设置为字符串。

type OptionKeys = {labelKey: string, valueKey: string, iconKey: string}
type Option<T extends OptionKeys> = {
    [label in T["labelKey" | "valueKey" | "iconKey"]]: string // all the types are string
}

type SelectProps<T extends OptionKeys = {
    labelKey: 'label',
    valueKey: 'value',
    iconKey: 'icon'
}> = {
    labelKey?: string
    valueKey?: string;
    iconKey?: string;
    options: Option<T>[]
}

这里,Option 的键具有 string 类型的值,但我想根据键定义类型。例如,如果键是labelKey,我希望它的值是number | string 等等。

我在这里看到的一个选项是通过使 Select 组件通用化来从外部接受 OptionType,但在这种情况下,我需要重构我的组件并希望暂时避免这种重构。

如何更新我的类型以处理这种情况?

【问题讨论】:

    标签: reactjs typescript typescript-generics


    【解决方案1】:

    使用这篇博文中的FromEntries 类型:https://dev.to/svehla/typescript-object-fromentries-389c

    定义SelectProps类型如下:

    type SelectProps<LK, VK, IK> = {
        labelKey?: LK
        valueKey?: VK
        iconKey?: IK
        options: FromEntries<[
            [LK, string], 
            [VK, string | number], 
            [IK, string | undefined]
        ]>
    }
    

    我们在选项中有三个键,标签键 (LK) 是 string,值键 (VK) 是 string | number 和图标键 (IK)是string | undefined

    现在我们定义Select函数如下:

    function Select<
        LK extends string = 'label', 
        VK extends string = 'value', 
        IK extends string = 'icon'
    >(props: SelectProps<LK, VK, IK>) {}
    

    将默认键名放在函数本身而不是SelectProps 类型上很重要。我不知道为什么。

    Full playground link

    【讨论】:

      猜你喜欢
      • 2018-12-12
      • 2018-06-19
      • 2019-06-19
      • 2018-07-03
      • 2019-11-27
      • 1970-01-01
      • 2021-12-08
      • 2022-01-05
      • 2020-02-14
      相关资源
      最近更新 更多