网站搜索

typescript - 在不使用 “as const” 的情况下将泛型数组参数推断为常量数组


我正在尝试从类型系统中实现某种特定行为,用于 API 设计。该 API 接受一个对象,其中一个属性是字符串数组,而另一个属性应该是该数组的一个元素。然而,我在实现这一点时遇到了困难,因为这样做需要 API 的使用者显式地将数组声明为只读,使用 as const。当使用者必须选择启用它时,这会违背类型安全的初衷。

看看这段代码:

type PaperCompany<Employees extends readonly string[]> = {
  employees: Employees
  topEmployee: Employees[number]
}

function describePaperCompany<Employees extends readonly string[]>(business: PaperCompany<Employees>) {
  // ...
}

describePaperCompany({
  employees: ["michael", "pam", "jim"] as const,
  topEmployee: "stanley" // Error: Type '"stanley"' is not assignable to type '"michael" | "pam" | "jim"'.
})

topEmployee 属性的行为正是我想要的。然而,也有可能在不使用 as const 指令的情况下传递数组,这会导致 topEmployee 的类型被推断为 string,而不是 "michael" | "pam" | "jim"。

假设我实现的 describePaperCompany API 要求 topEmployee 必须是 employees 的一个元素,否则将会失败。我希望类型检查器能强制执行这一点,但要求使用 as const 部分意味着 API 的每个调用者都必须遵守这一强制规则。他们可以简单地省略 as const,这样就不会收到任何类型错误。

如你所见,我已经在类型签名中包含了 readonly 关键字,但类型检查器仍然允许传递非只读类型作为参数。我有什么方法可以在不使用 as const 的情况下实现相同的行为吗?