在TS中的const assertion:

另一件要记住的事情是常量上下文不会立即 将表达式转换为完全不可变的.

我不能理解TS为什么不能使它不可变.理想情况下,它应该抛出错误.

let arr = [1, 2, 3, 4];
let foo = {
  name: "foo",
  contents: arr,
} as const;
foo.name = "bar"; // error!
foo.contents = []; // error!
foo.contents.push(5); // ...works!

如果我们在foo对象内将数组值作为文字添加,则它是有效的:

let foo = {
  name: "foo",
  contents: [1, 2, 3, 4],
} as const;

foo.name = "bar"; // error!
foo.contents = []; // error!
foo.contents.push(5); // NOW THROW ERROR

这是如何工作的,don’t immediately convert and expression到底是什么意思?

推荐答案

Typescript 应用的"不变性"是shallow and type-level.它不会强制实现深度不变性,也不会改变运行时的JavaScript行为.TypeScrip的类型系统旨在提供编译时类型判断,不会影响运行时行为.

在您的第一个示例中,foo.name变为只读,因为它是foo的直接属性.foo.contents也是只读的,防止您将其重新分配给不同的array.然而,常量断言并没有使arr的内容(以及扩展foo.contents,因为它引用了arr)不是完全不变的.这意味着您仍然可以通过将元素推入其中或更改其元素(如果它们是对象)来修改arr(因此也可以修改foo.contents).

在您的第二个示例中,顶层对foo及其属性的处理方式类似.名称为只读,无法重新分配内容.之所以会出现差异,是因为您直接将数组文字放在了foo内.执行此操作时,TypeScrip会将内容类型推断为只读元组(readonly [1, 2, 3, 4]),这使得数组的每个元素也是只读的.它看起来像是深度不变性,但实际上它是类型脚本在常量上下文中处理文字的结果-它使数组文字的元素不可变,因为它将它们视为元组.

您也可以让第一个示例抛出,只需将开头的arr也设为const:

let arr = [1, 2, 3, 4] as const;
let foo = {
  name: "foo",
  contents: arr,
} as const;
foo.name = "bar"; // error!
foo.contents = []; // error!
foo.contents.push(5); // error!

Typescript相关问答推荐

您可以创建一个类型来表示打字员吗

参数类型undefined不能分配给参数类型字符串|未定义

如何缩小变量访问的对象属性范围?

如何消除在Next.js中使用Reaction上下文的延迟?

为什么我的一个合成函数不能推断类型?

已解决:如何使用值类型限制泛型键?

如何以Angular 导入其他组件S配置文件

使用TypeScrip的类型继承

如何在使用条件类型时使用void

如何在不违反挂钩规则的情况下动态更改显示内容(带有状态)?

在抽象类属性定义中扩展泛型类型

重写返回任何

来自枚举的<;复选框和组件列表

仅当类型为联合类型时映射属性类型

TypeScript:如何使用泛型和子类型创建泛型默认函数?

基于参数的 TS 返回类型

使用 fp-ts 时如何使用 TypeScript 序列化任务执行?

我是否应该在 Next.js 中的服务器组件中获取秘密数据的所有函数中使用使用服务器?

使用嵌套属性和动态执行时,Typescript 给出交集而不是并集

在 TypeScript 中实现类型级别深度优先搜索