元组中的只读扩展数组

问题描述 投票:0回答:3

我有一些本不想执行的 TypeScript 代码,但它却执行了,为什么?

let a:[boolean, ... readonly string[]] = [true, '1', '2', '3'];

a[0] = false;
a[1] = 'one'; //no error, but it should be error
typescript
3个回答
1
投票

您的代码没有产生错误的原因是,尽管您有注释,

a
的类型会立即被编译器减少为完全可变类型
[boolean, ...string[]]

let a: [boolean, ... readonly string[]] = [true, '1', '2', '3'];

type A = typeof a;
// type A = [boolean, ...string[]]

因此

a
的所有元素都不是只读的。这就是所问问题的答案。


明显的后续问题是“为什么它会被简化为完全可变的类型?”。不幸的是,我找不到任何权威来源,所以我在这里所说的一切都只是猜测。来了:

类型

[T, ...A]
是将 A 类型的数组
spread
到以
t
类型的值开头的数组文字的末尾时获得的类型。以下函数编译没有错误的事实证明了这一点:

function f<T, A extends readonly any[]>(t: T, a: A): [T, ...A] {
    return [t, ...a]
}

如果我有一个只读字符串数组并将其传播到数组文字的末尾,则生成的数组将不是只读的:

const strs: readonly string[] = ["x", "y"]
const result = f(true, strs);
// const result: [boolean, ...string[]]

这就是我的猜测。如果有人找到任何证实或反驳这一点的规范来源(例如 TS 文档或 GitHub 问题),我很有兴趣了解它。

Playground 代码链接


0
投票

它之所以有效,是因为

readonly
只是各个元素本身。数组本身仍然是可变的。

如果你这样做了

let a:readonly [boolean, ... readonly string[]] = [true, '1', '2', '3'];

a[0] = false; // error
a[1] = 'one'; //error

然后,是的,它会出错,因为您已将数组本身标记为只读,而不仅仅是其某些值。


0
投票

扩展数组/元组只是有序地列出该数组的元素。

它只是从数组中取出值,而不实际修改/传输推断的特征

let xs = [1,2,3,4]

let ys = [...xs] // [1,2,3,4]

因此当我们这样做时

let a:[boolean, ... readonly string[]] = [true, '1', '2', '3'];

我们只是说从

readonly string array
中提取所有值,而不是使这些值成为
readonly

这就是行为。

© www.soinside.com 2019 - 2024. All rights reserved.