为啥 Typescript 允许将“任何”对象类型分配给类对象?

Posted

技术标签:

【中文标题】为啥 Typescript 允许将“任何”对象类型分配给类对象?【英文标题】:Why does Typescript allow to assign an "any" object type to class object?为什么 Typescript 允许将“任何”对象类型分配给类对象? 【发布时间】:2017-09-08 10:44:02 【问题描述】:

我有一个类对象:

groupNameData: GroupNameData = new GroupNameData();

我有一个any 对象

 groupNameDatas: any;

分配 1(class= 任意)

我刚刚将类对象值分配给any对象,比如

this.groupNameDatas = this.groupNameData;

这意味着,this.groupNameDatas (Any) 可以接受任何类型的数据,因为它是一个 any 对象。

作业 2(任何 = 类)

现在我已经反转了分配,比如

this.groupNameData = this.groupNameDatas;// any to class

它也像我的第一个作业示例一样工作。为什么它没有抛出像cannot convert implicitly "any" to "GroupNameData" 这样的错误?

【问题讨论】:

this.groupNameDatas 可以是GroupNameData,因为它的类型是any,它可以是任何类型。 我想你误解了我的问题。实际上我的问题是为什么类对象接受任何对象?有意义吗? @LeonardoChaia,请再看一次我的问题。 如果您了解类型的用途,这似乎很明显。你想要一根香蕉。不如我给你这个魔法盒子里的东西,里面有随机的东西。希望是香蕉 @peeskillet 如果您一直在使用像 C# 这样的静态类型语言,其中从 object 分配给特定类型变量总是需要强制转换,我认为这并不明显。没有理由如此居高临下。 【参考方案1】:

这是预期的行为 (docs)。希望这个样本能澄清它:

let someObj = new MyClass();
// someObj will be of the "MyClass" type.

let anyObject : any;
// since anyObject is typed as any, it can hold any type:
anyObject = 1;
anyObject = "foo";
// including your class:
anyObject = someObj;

// so, if it can hold anything, it's expected that we can assign our custom classes to it:
someObj = anyObj;

但是打字稿如何接受将任何对象分配给类对象?

这就是any 类型的乐趣所在。 Typescript 无法知道您的 any-typed 变量是否包含您的对象的实例。它是任何东西,所以它可以是你的对象的一个​​实例。

【讨论】:

Typescript can't know if your any-typed variable holds an instance of your object or not ,所以它完全覆盖了我的类对象?? 嗯,这就是 javascript 的工作原理。如果你可以在 Javascript 上做,你可以在 Typescript 上做。 所以它和letvar一样吗? If you can do it on Javascript, you can do it on Typescript这就是我问这个的原因? 对不起,还是不明白比较。也许这可能是另一个 SO 问题。【参考方案2】:

如果您查看official documentation,它清楚地表明“任何”都会忽略所有编译时检查。

文档中的相关sn-p:

我们可能需要描述我们在编写应用程序时不知道的变量类型。这些值可能来自动态内容,例如来自用户或第三方库。在这些情况下,我们希望选择退出类型检查并让值通过编译时检查。为此,我们将它们标记为 any 类型:

let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

any 类型是处理现有 JavaScript 的强大方式, 允许您在期间逐渐选择加入和退出类型检查 汇编。您可能希望 Object 扮演类似的角色,因为它 用其他语言做。但是 Object 类型的变量只允许你 为它们分配任何值 - 你不能调用任意方法 它们,甚至是实际存在的:

您是否应该选择使用其他类型,例如数字或字符串 编译时检查开始了,你知道这是不对的。

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

如果您知道该类型的某些部分,则 any 类型也很方便,但是 也许不是全部。例如,您可能有一个数组,但 数组混合了不同的类型:

let list: any[] = [1, true, "free"];

list[1] = 100;

【讨论】:

【参考方案3】:

TypeScript 需要一种不同于传统静态类型语言的思维方式。在 C# 或 Java 等语言中,编译器会给出类型错误,除非程序员提供了足够的信息来让编译器清楚它不应该给出类型错误。在 Typescript 中,只有当程序员提供了足够的信息让编译器知道类型无效时,编译器才会给出类型错误。

Any 的使用会从编译器中获取信息。

Typescript 的创建允许在类型信息允许的情况下,在编译时发现程序中尽可能多的错误的增量添加类型信息。它可以被认为是利用所提供的任何类型信息的“超级 lint”。

多年来,Typescript 已经更接近那些习惯于严格编译时类型检查语言的人们(比如我)所期望的,但它仍然非常“适合”Javascript。

【讨论】:

【参考方案4】:

您可以阅读unknown - 这是any 类型的类型安全对应物。

这是link with the differences。

【讨论】:

以上是关于为啥 Typescript 允许将“任何”对象类型分配给类对象?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Typescript 对象允许这个额外的属性?

为啥 TypeScript 中的类允许使用鸭子类型

为啥允许使用 kebab-case 非标准属性,而不允许使用其他属性?以及如何在 TypeScript 中定义这样的类型?

你能声明一个允许 typescript 中的未知属性的对象字面量类型吗?

为啥 TypeScript 对象不能用泛型类型索引?

为啥在 TypeScript 中的“任何”字段类型变量上使用“字符串”函数时没有编译时错误?