【问题标题】:Get string literal types from Array of objects从对象数组中获取字符串文字类型
【发布时间】:2022-01-13 13:56:43
【问题描述】:

所以来自:

export interface Category{
  val: string;
  icon: string
}
const categoryArray: Category[] = [
  {
    val: 'business',
    icon: 'store'
  },
  {
    val: 'media',
    icon: 'video'
  },
  {
    val: 'people',
    icon: 'account'
  },

  ... 

我想像这样返回一个 Union 类型:

'business' | 'media' | 'people' ... 

我不知道有什么样的语法或帮助器,也许根本没有。我意识到这种方式可能是倒退的,也许应该使用枚举,但在此之前,我想知道它是可能的。

我想做的一些虚构示例,但我希望解决方案更复杂

type Cats = keysof[] categoryArray 'val'  
type Cats = valuesof categoryArray 'val'

以下是关闭的,但返回string

export type CatsValType = typeof categories[number]['val']

或以下;而不是我需要字符串文字的类型

type ValueOf<T> = T[keyof T];
type KeyTypes = ValueOf<typeof categories[number]> // Returns: `string`

有类似的问题,例如:Is there a `valueof` similar to `keyof` in TypeScript?,但它们不假设对象数组。

和这里的例子:https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html 类似,但我不想返回类型,而是字段的值,所以我得到一个 Union 类型返回。

【问题讨论】:

    标签: typescript typeof union-types keyof


    【解决方案1】:

    如果你可以做到:

    • 数组中的值在运行时不会改变(因为类型信息是 TypeScript 的仅编译时的东西);和

    • 你告诉 TypeScript 它们的值不会通过使用 as const 来改变;和

    1. 不要categoryArray常量类型Category[],因为如果你这样做,结果就是string(因为Category["val"]的类型是string ) 而不是你想要的字符串文字联合类型。

    这是一个示例 (playground link):

    export interface Category{
      val: string;
      icon: string
    }
    const categoryArray = [
      {
        val: 'business',
        icon: 'store'
      },
      {
        val: 'media',
        icon: 'video'
      },
      {
        val: 'people',
        icon: 'account'
      },
    ] as const;
    
    type TheValueUnion = (typeof categoryArray)[number]["val"];
    //   ^? −− "business" | "media" | "people"
    

    其中的关键位是as consttype TheValueUnion = (typeof categoryArray)[number]["val"];,分解如下:

    1. typeof categoryArray 获取 categoryArray 的类型(推断的类型,因为我们没有指定特定的类型)。
    2. [number] 访问由categoryArray 类型上的数字索引的类型的联合。
    3. ["val"] 访问来自 #2 的并集上 val 属性的类型并集,这是您想要的字符串文字类型:"business" | "media" | "people"

    【讨论】:

    • 谢谢,这几乎对我有用,现在的问题是Category 上的任何“可选”属性都变为只读且强制的。我没有在示例中包含任何可选内容,但假设我有一个disabled?: boolean;,它会出错:Property 'disabled' does not exist on type '{ readonly val: "art"; readonly... etc.
    • @TrySpace - 很奇怪,I don't get that,我不确定该错误会出现在哪里,我们没有对上面的Category 做任何事情。你能更新那个游乐场的例子来演示这个问题吗?
    • @TrySpace - 您正尝试在 数组 上使用 disabled。它不在数组上,它在数组 elements 上。
    • 你说得对,这就是我的意思:typescriptlang.org/play?#code/… 我不能有条件地使用disabled 属性,除非它确实在只读对象中定义。
    猜你喜欢
    • 2016-10-24
    • 2023-02-25
    • 2013-07-01
    • 1970-01-01
    • 2021-05-24
    • 2019-04-30
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多