【问题标题】:Create a type constructed with values of an object创建一个用对象的值构造的类型
【发布时间】:2019-02-10 09:05:56
【问题描述】:

假设我有一个这样的对象:

const MenuOptions = {
    Project: ["new", "open", "close"],
    File: ["create", "edit"]
    // ...
}

对象的值都是唯一的。

我还想定义一种方法来允许用户点击菜单选项:

function clickOnMenuOption(option: string) { ... }

参数option的值只能是new/open/close/create/edit/...之一。

是否可以基于MenuOptions定义类型MenuOption

type MenuOption = ???

【问题讨论】:

  • 您能说出MenuOptions 变量的典型用法吗?

标签: typescript typescript-typings


【解决方案1】:

如果你只是像上面那样声明MenuOptions,编译器会倾向于将值类型推断为string[],而不是文字元组。如果您需要访问这些文字,那么您将需要更改声明对象的方式。当 TypeScript 3.4 于 2019 年 3 月发布时,您将能够使用 const context 来提示编译器推断可能的最窄类型,如下所示:

const MenuOptions = {
  Project: ["new", "open", "close"],
  File: ["create", "edit"]
  // ...
} as const; // only works in TS3.4+

在此之前,您可以使用如下辅助函数来指导推理:

type Narrowable = string | number | boolean | undefined | null | void | {};   
const tuple = <T extends Narrowable[]>(...t: T)=> t;    

const MenuOptions = {
  Project: tuple("new", "open", "close"),
  File: tuple("create", "edit")
  // ...
};

在任何一种情况下,您想要的类型都在上面给出为

type MenuOption = (typeof MenuOptions)[keyof typeof MenuOptions][number];

让我们将其分解为步骤并为中间类型命名。你取的是MenuOptions的类型:

type TypeofMenuOptions = typeof MenuOptions;
// type TypeofMenuOptions = {
//   Project: ["new", "open", "close"];
//   File: ["create", "edit"];
// }

查找其值类型的联合

type MenuOptionsValues = TypeofMenuOptions[keyof TypeofMenuOptions];
// type MenuOptionsValues = ["new", "open", "close"] | ["create", "edit"]

并查找其数字索引属性(如果您有一个类型 (A | B)[K],则它被评估为 A[K] | B[K]

type MenuOption = MenuOptionsValues[number];
// type MenuOption = "new" | "open" | "close" | "create" | "edit"

这让你得到了你正在寻找的字符串文字的联合。

好的,希望对您有所帮助。祝你好运!

【讨论】:

    【解决方案2】:

    我不知道您对 TS 的体验如何,但您似乎犯了典型的 TS 新手错误(将类型与值混淆),如果我错了,请见谅。

    惯用的 TS 代码应如下所示:

    type Option = "new" | "open" | "close" | "create" | "edit"
    
    interface MenuOptions {
        Project: Option[],
        File: Option[]
    }
    
    const menuOptions: MenuOptions = {
        Project: ["new", "open", "close"],
        File: ["create", "edit"]
        // ...
    }
    
    function clickOnMenuOption(option: Option) {  }
    

    【讨论】:

    【解决方案3】:

    您可以使用 TypeScript Enums。它们最适合声明常量。

    enum MenuOption {
        New = "new",
        Open = "open",
        Close = "close",
        Create = "create",
        Edit = "edit"
    }
    const MenuOptions = {
        Project: [MenuOption.New, MenuOption.Open, MenuOption.Close],
        File: [MenuOption.Create, MenuOption.Edit]
    }
    function clickOnMenuOption(option: MenuOption) { //... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 2017-04-13
      • 1970-01-01
      • 2011-05-12
      相关资源
      最近更新 更多