[英]What does the "as const" mean in TypeScript and what is its use case?
I am confused about the as const
cast.我对
as const
演员感到困惑。 I checked a few documents and videos but did not understand it fully.我检查了一些文件和视频,但没有完全理解。
My concern is what does the as const
mean in the code below and what is the benefit of using it?我关心的是下面代码中的
as const
是什么意思,使用它有什么好处?
const args = [8, 5] as const;
const angle = Math.atan2(...args);
console.log(angle);
This is known as a const
assertion .这称为
const
断言。 A const
assertion tells the compiler to infer the narrowest * or most specific type it can for an expression. const
断言告诉编译器推断出它可以为表达式推断出的最窄的*或最具体的类型。 If you leave it off, the compiler will use its default type inference behavior, which will possibly result in a wider or more general type.如果您将其关闭,编译器将使用其默认类型推断行为,这可能会导致更广泛或更通用的类型。
Note that it is called an "assertion" and not a "cast".请注意,它被称为“断言”而不是“强制转换”。 The term "cast" is generally to be avoided in TypeScript;
TypeScript 中一般要避免使用“演员”一词; when people say "cast" they often imply some sort of effect that can be observed at runtime, but TypeScript's type system, including type assertions and
const
assertions, is completely erased from the emitted JavaScript.当人们说“cast”时,他们通常暗示可以在运行时观察到的某种效果,但是 TypeScript 的类型系统,包括类型断言和
const
断言,完全从发出的 JavaScript 中删除。 So there is absolutely no difference at runtime between a program that uses as const
and one that does not.因此,使用 as const 的程序和不使用
as const
的程序在运行时绝对没有区别。
At compile time, though, there is a noticeable difference.但是,在编译时,存在明显的差异。 Let's see what happens when you leave out
as const
in the above example:让我们看看在上面的示例中省略
as const
会发生什么:
const args = [8, 5];
// const args: number[]
const angle = Math.atan2(...args); // error! Expected 2 arguments, but got 0 or more.
console.log(angle);
The compiler sees const args = [8, 5];
编译器看到
const args = [8, 5];
and infers the type of number[]
.并推断
number[]
的类型。 That's a mutable array of zero or more elements of type number
.这是一个由零个或多个
number
类型元素组成的可变数组。 The compiler has no idea how many or which elements there are.编译器不知道有多少或哪些元素。 Such an inference is generally reasonable;
这样的推论通常是合理的; often, array contents are meant to be modified in some way.
通常,数组内容意味着要以某种方式进行修改。 If someone wants to write
args.push(17)
or args[0]++
, they'll be happy with a type of number[]
.如果有人想写
args.push(17)
或args[0]++
,他们会对number[]
类型感到满意。
Unfortunately the next line, Math.atan2(...args)
, results in an error.不幸的是,下一行
Math.atan2(...args)
导致错误。 The Math.atan2()
function requires exactly two numeric arguments. Math.atan2()
function 恰好需要两个数字 arguments。 But all the compiler knows about args
is that it's an array of numbers.但是编译器只知道
args
是一个数字数组。 It has completely forgotten that there are two elements, and so the compiler complains that you are calling Math.atan2()
with "0 or more" arguments when it wants exactly two.它完全忘记了有两个元素,因此编译器抱怨您在需要两个元素时使用“0 或更多” arguments 调用
Math.atan2()
。
Compare that to the code with as const
:将其与
as const
的代码进行比较:
const args = [8, 5] as const;
// const args: readonly [8, 5]
const angle = Math.atan2(...args); // okay
console.log(angle);
Now the compiler infers that args
is of type readonly [8, 5]
... a readonly
tuple whose values are exactly the numbers 8
and 5
in that order.现在编译器推断
args
的类型为readonly [8, 5]
... 一个readonly
元组,其值恰好是按该顺序排列的数字8
和5
。 Specifically, args.length
is known to be exactly 2
by the compiler.具体来说,编译器知道
args.length
正好是2
。
And this is enough for the next line with Math.atan2()
to work.这足以让
Math.atan2()
的下一行工作。 The compiler knows that Math.atan2(...args)
is the same as Math.atan2(8, 5)
, which is a valid call.编译器知道
Math.atan2(...args)
与Math.atan2(8, 5)
相同,这是一个有效的调用。
And again: at runtime, there is no difference whatsoever.再说一遍:在运行时,没有任何区别。 Both versions log
1.0121970114513341
to the console.两个版本都将
1.0121970114513341
记录到控制台。 But const
assertions, like the rest of the static type system, are not meant to have effects at runtime.但是
const
断言,如 static 类型系统的 rest,并不意味着在运行时产生影响。 Instead, they let the compiler know more about the intent of the code, and can more accurately tell the difference between correct code and bugs.相反,它们让编译器更多地了解代码的意图,并且可以更准确地分辨出正确代码和错误之间的区别。
Playground link to code Playground 代码链接
* This isn't strictly true for array and tuple types; * 这对于数组和元组类型并不严格; a
readonly
array or tuple is technically wider than a mutable version. readonly
数组或元组在技术上比可变版本更广泛。 A mutable array is considered a subtype of a readonly
array;可变数组被认为是
readonly
数组的子类型; the former is not known to have mutation methods like push()
while the latter does.前者不知道有像
push()
这样的变异方法,而后者有。
In short words, it lets you create fully readonly objects , this is known as const assertion
, at your code as const
means that the array positions values are readonly
, here's an example of how it works:简而言之,它允许您创建完全只读的对象,这被称为
const assertion
,在您的代码as const
意味着数组位置值是readonly
的,这是它如何工作的示例:
const args = [8, 5] as const;
args[0] = 3; // throws "Cannot assign to '0' because it is a read-only
args.push(3); // throws "Property 'push' does not exist on type 'readonly [8, 5]'"
You can see at the last thrown error, that args = [8, 5] as const
is interpreted as args: readonly [8, 5]
, that's because the first declaration is equivalent to a readonly tuple .您可以在最后抛出的错误中看到
args = [8, 5] as const
被解释为args: readonly [8, 5]
,这是因为第一个声明等效于readonly tuple 。
There's a few exceptions for the asserts being 'fully readonly', you can check them here .断言为“完全只读”有一些例外,您可以在此处检查它们。 However, the general benefit is the
readonly
behaviour that is added to all its object attributes .但是,一般好处是添加到其所有 object 属性的
readonly
行为。
const args = [8, 5];
// Without `as const` assert; `args` stills a constant, but you can modify its attributes
args[0] = 3; // -- WORKS
args.push(3); // -- WORKS
// You are only prevented from assigning values directly to your variable
args = 7; // -- THROWS ERROR
For more details, here's a list of other related question/answers that helped me understand the const assertion:有关更多详细信息,以下是帮助我理解 const 断言的其他相关问题/答案的列表:
If you were to write const args = [8, 5]
, nothing would prevent you from then also writing args[0] = 23
or args.push(30)
or anything else to modify that array.如果您要编写
const args = [8, 5]
,那么没有什么可以阻止您同时编写args[0] = 23
或args.push(30)
或其他任何东西来修改该数组。 All you've done is tell TS/JS that the variable named args
points to that specific array, so you can't change what it's referencing (eg you can't do args = "something else"
).您所做的只是告诉 TS/JS 名为
args
的变量指向该特定数组,因此您无法更改它所引用的内容(例如,您无法执行args = "something else"
)。 You can modify the array, you just can't change what its variable is pointing to.您可以修改数组,但不能更改其变量指向的内容。
On the other hand, adding as const
to a declaration now really makes it constant.另一方面,现在将
as const
添加到声明中确实使它成为常量。 The whole thing is read-only, so you can't modify the array at all.整个东西是只读的,所以你根本不能修改数组。
To clarify, as pointed out in the comments:为了澄清,正如评论中指出的那样:
"really makes it constant" could imply that there is some runtime effect when there is none.
“真的让它保持不变”可能意味着当没有运行时效果时会有一些运行时效果。 At runtime, args.push(30) will still modify the array.
在运行时,args.push(30) 仍然会修改数组。 All as const does is make it so that the TypeScript compiler will complain if it sees you doing it.
正如 const 所做的那样,如果 TypeScript 编译器看到你这样做,它就会抱怨。 – jcalz
– 杰卡尔兹
as const
only affects the compiler, and there is an exception to its read-only effect (see the comments). as const
只影响编译器,它的只读效果有一个例外(见注释)。 But in general, that's still the major use difference between const
and as const
.但总的来说,这仍然是
const
和as const
之间的主要使用区别。 One is used to make a reference immutable and the other is used to make what's being referenced immutable.一个用于使引用不可变,另一个用于使引用的内容不可变。
That is a const
assertion.那是一个
const
断言。 Here is a handy post on them , and here is the documentation . 这是关于它们的一个方便的帖子, 这里是文档。
When we construct new literal expressions with const assertions, we can signal to the language that
当我们用 const 断言构造新的文字表达式时,我们可以向语言发出信号:
- no literal types in that expression should be widened (eg no going from "hello" to string)
不应该扩大该表达式中的文字类型(例如,不要从“hello”变为字符串)
- object literals get readonly properties
object 文字获得只读属性
- array literals become readonly tuples
数组文字变成只读元组
With const args = [8, 5] as const;
使用
const args = [8, 5] as const;
, the third bullet applies, and tsc will understand it to mean: ,第三个项目符号适用,并且 tsc 将理解它的意思是:
// Type: readonly [8, 5]
const args = [8, 5] as const;
// Ok
args[0];
args[1];
// Error: Tuple type 'readonly [8, 5]' of length '2' has no element at index '2'.
args[2];
Without the assertion:没有断言:
// Type: number[]
const args = [8, 5];
// Ok
args[0];
args[1];
// Also Ok.
args[2];
as const
when applied to an object or array it makes them immutable (ie making them read-only). as const
应用于 object 或数组时,它使它们不可变(即使它们只读)。 For other literals it prevents type widening.对于其他文字,它可以防止类型扩大。
const args = [8, 5] as const;
args[0] = 10; ❌ Cannot assign to '0' because it is a read-only property.
Few other advantages :其他几个优点:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.