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

Typescript: DRY definition of string union and full array with the same item type

如其他地方所示(例如),很容易从元组定义联合类型:

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

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

Typescripts 建议首先转换为 unknown - 它有效但它看起来令人困惑并且有点破坏类型安全数组常量的全部目的:

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

除了上面的双重转换之外,有没有更好的方法可以同时拥有 Item[]Item 联合类型的完整选项列表而不重复实际选项?

你想做的是type-unsafe。鉴于

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

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

arrayParameter.push('foo');

这会很好,因为参数仍然是 Item[]。但是原始类型现在不正确,因为变异的 arr 不再是 ["foo", "bar"] as const - 相反,它有 3 个项目。

如果您想将数组用作通用 Item[],请先对数组进行切片(或以其他方式进行浅拷贝)。没有其他方法可以做到这一点 type-safe.

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

如果您的函数将 readonly string[] this 作为输入,那么您可以传递现有的 arr,我知道您可能没有控制权或更改函数签名,但将其丢弃以防万一

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


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

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