【问题标题】:How can you extract the inferred string literal types for a function signature?如何提取函数签名的推断字符串文字类型?
【发布时间】:2021-10-09 21:23:45
【问题描述】:

我正在尝试了解从枚举转移到字符串文字的情况。

一个挂起点是利用这些键的功能。

例如,如果我使用枚举,我可能会有类似的东西:

enum Role {
  Standard = "Standard",
  Admin = "Admin",
}

type Standard = {
  role: Role.Standard
  name: string
  age: number
}

type Admin = {
  role: Role.Admin
  name: string
  securityLevel: "Normal" | "Elevated" | "High"
}

type Employee = Admin | Standard

然后,我编写了一个仅基于角色执行某些操作的辅助函数:

function doSomething(role: Role){ /*...*/ )

在这种情况下,我几乎肯定会从员工那里提取角色,但值得注意的是,我只是将一个字符串传递给函数。

是否可以使用字符串文字来做到这一点?我能得到的最好的方法是传入一个具有角色的对象:

type Standard = {
  role: "Standard"
  name: string
  age: number
}

type Admin = {
  role: "Admin"
  name: string
  securityLevel: "Normal" | "Elevated" | "High"
}

type Employee = Admin | Standard

function doSomething(e: Pick<Employee, "role">){
  return e.role === "Admin"
}

doSomething({role: "Admin"}) // compiles
doSomething({role: "Executive"}) // doesn't compile

我正在寻找写法:

doSomething("Admin") // compiles
doSomething("Executive") // doesn't compile

或者,如果这不是曾经需要的东西......我想更好地理解 - 我相当有信心我以前使用 Enums 作为函数中的类型。

更新一种可能的替代方法是以某种方式提取字符串文字,然后在构成 Employee 的类型的定义中使用它,例如,

type RoleStrings = "Standard" | "Admin"
type Standard = {
  role: /* what goes here to say it's the string "Standard" that's _tied_ to the type `RoleStrings`? */
  name: string
  age: number
}

type Admin = {
  role: /* what goes here to say it's the string "Admin" that's _tied_ to the type `RoleStrings`? */
  name: string
  securityLevel: "Normal" | "Elevated" | "High"
}

如果我能做到,那么这将变得微不足道:

function doSomething(role: RoleStrings){/*...*/)

更新 2

我想我有一个我喜欢的解决方案:

type RoleStrings = Employee['role']
function doSomething(role: RoleStrings){/*...*/}

这实现了我的目标,即派生允许的字符串并确保 for 函数尽可能直接,而不需要 Employee(即使它是 Pick)对象。

【问题讨论】:

    标签: typescript enums string-literals


    【解决方案1】:

    您可以使用keyof typeof 来获取表示键并集的类型:

    function doSomething(role: keyof typeof Role){ /*...*/ }
    

    playground

    如果您根本不想使用enum,那么您可以使用联合:

    function doSomething(role: "Standard" | "Admin"){ /*...*/ }
    

    playground

    【讨论】:

    • 同意那行得通如果 我使用enum 方法,但我实际上试图 这样做。请注意,在我的第二个示例中,没有 Role 枚举。
    • 在这种情况下,您可以只使用字符串文字的联合:"Standard" | "Admin"
    • 知道了——这就是我害怕的。这意味着我需要重复自己并可能使类型不同步。
    【解决方案2】:

    给定:

    type Standard = {
      role: "Standard"
      name: string
      age: number
    }
    
    type Admin = {
      role: "Admin"
      name: string
      securityLevel: "Normal" | "Elevated" | "High"
    }
    
    type Employee = Admin | Standard
    

    我找到的最干净的答案是:

    type RoleStrings = Employee['role']
    function doSomething(role: RoleStrings){/*...*/}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多