【问题标题】:How can I generate a type from the properties values of a typed object in Typescript?如何从 Typescript 中类型化对象的属性值生成类型?
【发布时间】:2021-03-13 22:52:53
【问题描述】:

假设我有一个 interface 描述了一个库,其中的项目看起来像这样:

interface MyItem {
  category: string,
  title: string
}

现在我有一个包含这些 MyItems 的配置文件:

const myLibrary: MyItem[] = [
  {
    category: "dogs",
    title: "Fuzzy quadrupeds" 
  },
  { 
    category: "snakes",
    title: "Slithery reptiles"
  },
  ...
]

现在,我想创建一个包含MyItem[] 中所有category 的类型

如果我这样做: type Category = typeof MyItem[number]["category"]我得到string

如果我从myLibrary(即const myLibrary = [ {...} ])中删除输入并得到我想要的:

这意味着 type Category = typeof MyItem[number]["category"] 为我提供了我想要的 dogs | snakes 联合类型,但当然在我的配置文件中创建新项目时我会丢失类型。

【问题讨论】:

    标签: javascript typescript typescript-typings


    【解决方案1】:

    我们希望限制 myLibrary 中的项目,以便它们必须实现 MyItem,但我们希望以保留特定项目的特定类型且不将类型扩大到仅 MyItem 的方式进行.

    仅通过为常量分配类型很难做到这一点。一种常用的模式是通过恒等函数创建常量。通过函数,我们可以使用extends 语法来确保T extends MyItem[] 同时保持T 特定。

    我必须使用as const 来获取文字类别名称,所以我还必须在函数参数中允许readonly

    interface MyItem {
      category: string,
      title: string
    }
    
    const buildLibrary = <T extends readonly MyItem[]>(library: T): T => library;
    
    const myLibrary = buildLibrary([
      {
        category: "dogs",
        title: "Fuzzy quadrupeds" 
      },
      { 
        category: "snakes",
        title: "Slithery reptiles"
      }
    ] as const);
    
    type Categories = (typeof myLibrary)[number]['category'] // "dogs" | "snakes"
    

    Typescript Playground Link

    【讨论】:

      【解决方案2】:

      不要复杂

      
      type Categorías = 'Food' | 'categoy1' | 'cstegory2'
      
      interface MyItem {
        category: Categories;
        title: string
      }
      
      const myLibrary: MyItem[] = [
        {
          category: "dogs",
          title: "Fuzzy quadrupeds" 
        },
        { 
          category: "snakes",
          title: "Slithery reptiles"
        },
        ...
      

      【讨论】:

      • 是的,这也是我最终所做的!我只是希望有一个更巧妙的解决方案:) 谢谢!
      【解决方案3】:

      如果我没听错的话,你想要这个:How to create enum like type in TypeScript? 然后将 MyItem 指定为

      interface MyItem: {
          category: MyDogSnakeType,
          title: string
      }
      

      【讨论】:

      • 谢谢!我想到了枚举路线,这可能是我最终要走的路。在定义库中可能存在的所有不同项目时,我希望避免单独定义 category
      • 如果有人回答更好的选择,我会感兴趣;)
      猜你喜欢
      • 2022-01-21
      • 2020-03-17
      • 2022-12-18
      • 2020-10-03
      • 2019-06-28
      • 1970-01-01
      相关资源
      最近更新 更多