打字稿:具有相同项目类型的字符串联合和完整数组的DRY定义

问题描述

如其他地方所示(例如TypeScript String Union to String Array),可以很容易地从元组中定义联合类型:

const arr = ["foo","bar"] as const
const Item = typeof arr[number]

不幸的是,我无法在需要arr的地方使用Item[]-arr的类型为readonly ["foo","bar"],甚至直接类型转换也会导致打字错误TS2352。

Typescripts建议首先转换为unkNown-它可以工作,但看起来令人困惑,并且有损于类型安全数组常量的整个目的:

const _arr: Item[] = (arr as unkNown) as Item[]

除了双重强制转换之外,是否有更好的方法可以同时包含Item[]Item联合类型的完整选项列表,而无需重复实际选项?

解决方法

您要执行的操作是类型不安全。给定

const arr = ["foo","bar"] as const

如果您在某处使用时可以输入与arr相同的Item[],然后(例如)将其传递给接受Item[]作为参数的函数,则该函数可以然后做:

arrayParameter.push('foo');

,因为参数仍将保持为Item[],这将是非常好的。但是原来的类型现在不正确,因为突变的arr不再是["foo","bar"] as const了-它具有3个项目。

如果要将其用作通用Item[],请先切片(或以其他方式进行浅表复制)数组。没有其他方法可以做到类型安全。

const arr = ['foo','bar'] as const;
type Item = typeof arr[number];
const arrItems: Item[] = arr.slice();
,

如果您的函数将readonly string[]用作输入,那么您可以传递现有的arr,我知道您可能没有控件或更改了函数签名,但是只要有帮助就扔掉它

const tuple = ['foo','bar'] as const


function println(arr: readonly string[]) {
  console.log(arr)
}

println(tuple)
println(['a','b','c'])