作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
TypeScript 允许我们使用父类(super class)型的变量(TypeScript 数组是协变的)为数组类型的变量添加别名:
const nums: number[] = [];
const things: (number | string)[] = nums;
things.push("foo");
nums[0] *= 3;
console.log(nums[0]); // `NaN` !!
This was asked by someone else on a stale TypeScript issue, but I didn't see any answers.
最佳答案
正如您所指出的,数组协方差是不合理的,可能会导致运行时出错。 TypeScript's Design Non-Goals之一是
- Apply a sound or "provably correct" type system. Instead, strike a balance between correctness and productivity.
S
是类型
T
的子类型,然后是一个值
s
类型
S
也是
T
类型的值.例如,如果您有一个类型为
string
的值,那么您也可以将其用作
string | number
类型的值(因为
string
是任何
string | X
的
X
的子类型)。 TypeScript 中的整个接口(interface)和类层次结构都建立在子类型的概念上。当
S extends T
或
S implements T
, 表示
S
是
T
的子类型.如果没有子类型,TypeScript 将更难使用。
const a = {x: ""}; const b = a; b.x = 1;
.除了原始数据类型,JavaScript 值都是引用。如果您尝试在不传递引用的情况下编写 JavaScript,那将是一种非常不同的语言。如果 TypeScript 强制要求将对象从一个命名变量传递到另一个变量,您必须复制它的所有数据,那么它会更难使用。
const a: {x: string} = {x: "a"};
,我可以跟进
a.x = "b";
没有错误。如果 TypeScript 要求所有别名都是不可变的,那么它会更难使用。
let a: { x: string } = { x: "" }; // subtype
let b: { x: string | number }; // supertype
b = a; // aliasing
b.x = 1; // mutation
a.x.toUpperCase(); // 💣💥 explosion
Playground link to code
--strictFunctionTypes
编译器选项,此时只有方法参数仍然总是双变量检查。
关于typescript - 为什么 TypeScript 数组是协变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60905518/
在我的设置中,我试图有一个界面 Table继承自 Map (因为它主要用作 map 的包装器)。两个类继承自 Table - 本地和全局。全局的将有一个可变的映射,而本地的将有一个只有本地条目的映射。
Rust Nomicon 有 an entire section on variance除了关于 Box 的这一小节,我或多或少地理解了这一点和 Vec在 T 上(共同)变体. Box and Vec
我是一名优秀的程序员,十分优秀!