Cih*_*man 26 type-assertion typescript
我对as const演员表感到困惑。我检查了一些文件和视频,但没有完全理解。
我担心的是as const下面代码中的含义是什么,使用它有什么好处?
const args = [8, 5] as const;
const angle = Math.atan2(...args);
console.log(angle);
Run Code Online (Sandbox Code Playgroud)
Lui*_*mas 75
简而言之,它可以让您创建完全只读的对象,这const assertion在您的代码中as const意味着数组位置值为readonly,这里是它如何工作的示例:
const args = [8, 5] as const;\nargs[0] = 3; // throws "Cannot assign to \'0\' because it is a read-only \nargs.push(3); // throws "Property \'push\' does not exist on type \'readonly [8, 5]\'" \nRun Code Online (Sandbox Code Playgroud)\n您可以看到最后抛出的错误被args = [8, 5] as const解释为args: readonly [8, 5],这是因为第一个声明相当于一个只读元组。
元组有很多用例,一些例子是:扩展参数、破坏性值等。一般的好处是readonly添加到其所有对象属性的行为:
const args = [8, 5];\n\n// Without `as const` assert; `args` stills a constant, but you can modify its attributes\nargs[0] = 3; // -- WORKS \xe2\x9c\x93\nargs.push(3); // -- WORKS \xe2\x9c\x93\n\n// You are only prevented from assigning values directly to your variable\nargs = 7; // -- THROWS ERROR \xe2\x9c\x96\nRun Code Online (Sandbox Code Playgroud)\n对于“完全只读”的断言,有一些例外情况,您可以在此处检查它们。有关更多详细信息,这里列出了其他相关问题/答案,帮助我理解 const 断言:
\n\njca*_*alz 37
这称为const断言。甲const断言告诉编译器推断最窄*或最具体它可以用于表达类型。如果您不使用它,编译器将使用其默认类型推断行为,这可能会导致更广泛或更通用的类型。
请注意,它被称为“断言”而不是“强制转换”。在 TypeScript 中通常要避免使用术语“cast”;当人们说“强制转换”时,他们通常暗示某种可以在运行时观察到的效果,但 TypeScript 的类型系统,包括类型断言和const断言,已从发出的 JavaScript 中完全删除。因此,使用和不使用的程序在运行时绝对没有区别as const。
但是,在编译时,存在显着差异。让我们看看当你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);
Run Code Online (Sandbox Code Playgroud)
编译器看到const args = [8, 5];并推断number[]. 这是一个包含零个或多个类型元素的可变数组number。编译器不知道有多少或哪些元素。这样的推断通常是合理的;通常,数组内容旨在以某种方式进行修改。如果有人想写args.push(17)或args[0]++,他们会对number[].
不幸的是,下一行 ,Math.atan2(...args)导致错误。该Math.atan2()函数正好需要两个数字参数。但是编译器只知道args它是一个数字数组。它完全忘记了有两个元素,因此编译器抱怨您在调用时Math.atan2()使用了“0 个或多个”参数,而恰好需要两个。
将其与以下代码进行比较as const:
const args = [8, 5] as const;
// const args: readonly [8, 5]
const angle = Math.atan2(...args); // okay
console.log(angle);
Run Code Online (Sandbox Code Playgroud)
现在编译器推断出args它的类型是readonly [8, 5]……一个readonly元组,它的值正好是数字,8并且是5按照这个顺序排列的。具体来说,args.length就是2编译器知道的。
这足以让下一行Math.atan2()工作。编译器知道这Math.atan2(...args)与 相同Math.atan2(8, 5),这是一个有效的调用。
再说一遍:在运行时,没有任何区别。两个版本都登录1.0121970114513341到控制台。但是const断言,与静态类型系统的其余部分一样,并不意味着在运行时产生影响。相反,它们让编译器更多地了解代码的意图,并且可以更准确地分辨正确代码和错误之间的区别。
* 对于数组和元组类型,严格来说并非如此;一个readonly阵列或元组在技术上是宽比可变版本。可变数组被认为是数组的子类型readonly;前者不像push()后者那样有变异方法是众所周知的。
use*_*737 36
如果您要编写const args = [8, 5],那么没有什么可以阻止您也编写args[0] = 23或args.push(30)或其他任何内容来修改该数组。您所做的就是告诉 TS/JS 变量 nameargs指向该特定数组,因此您无法更改它引用的内容(例如,您不能这样做args = "something else")。您可以修改数组,但无法更改其变量指向的内容。
另一方面,as const现在添加到声明中确实可以使其保持不变。整个数组是只读的,因此您根本无法修改数组。
为了澄清,正如评论中指出的:
\n\n\n“真正使其恒定”可能意味着在没有运行时效果的情况下存在一些运行时效果。在运行时,args.push(30) 仍然会修改数组。const 所做的一切都是为了让 TypeScript 编译器看到你这样做时会抱怨。\xe2\x80\x93 jcalz
\n
as const只影响编译器,其只读效果有例外(见注释)。但总的来说,这仍然是const和之间的主要使用差异as const。一个用于使引用不可变,另一个用于使被引用的内容不可变。
Roh*_*dal 16
as const当应用于对象或数组时,它使它们不可变(即使它们只读)。对于其他文字,它可以防止类型扩展。
const args = [8, 5] as const;\n\nargs[0] = 10; \xe2\x9d\x8c Cannot assign to '0' because it is a read-only property.\nRun Code Online (Sandbox Code Playgroud)\n其他一些优点:
\n已经添加了令人惊奇的答案,只是想删除另一个as const可能对某些人有用的示例,并且与其他答案中的示例有点不同:
type Status = "success" | "danger"\n\nfunction foo(status: Status){\n console.log({ status });\n}\n\nconst status = "success";\n\n// \xe2\x9d\x8c Error: Argument of type 'string' is not assignable to parameter of type 'Status'.\nfoo(status);\nRun Code Online (Sandbox Code Playgroud)\n它不起作用的原因是,当打字稿看到 时const status = "success",它会将状态变量的类型推断为字符串,而函数的状态参数的foo类型并不像“字符串”那么广泛,它更加具体,它要么有是“成功”还是“危险”。
要解决此问题,您有两种方法:
\n// #1: Call foo with "success" directly and TypeScript is smart enough to accept it:\nfoo("success");\n// #2: Solution #1 however is not always useable, e.g., when status is received from\n// somewhere else, in that case, we have no other options but using a variable for it\n// That's how it can be done using a variable:\nfoo("success" as const);\nRun Code Online (Sandbox Code Playgroud)\n实际上,这与@jcalz 在他们的精彩回答中所说的没有什么不同:
\n\n\nconst 断言告诉编译器为表达式推断最窄或最具体的类型。
\n
那是一个const断言。这里有一篇关于它们的方便帖子,这里是文档。
当我们用 const 断言构造新的文字表达式时,我们可以向语言发出信号:
- 该表达式中的文字类型不应该被扩展(例如,不要从“hello”到字符串)
- 对象字面量获得只读属性
- 数组文字变成只读元组
使用const args = [8, 5] as const;,第三个项目符号适用,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];
Run Code Online (Sandbox Code Playgroud)
没有断言:
// Type: number[]
const args = [8, 5];
// Ok
args[0];
args[1];
// Also Ok.
args[2];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4680 次 |
| 最近记录: |