TypeScript:从任何东西到任何东西的隐式演员?

时间:2014-11-22 19:15:03

标签: typescript

我只是在学习TypeScript,而且我对any的性质感到有些困惑。看看这个:

var x: any = 1;
var y = 1;
x = y;
y = x; // why does this not cause a compile-time error?

起初我理解any是没有任何承诺的类型 - 这就是为什么第一个赋值是合理的 - 但看起来在其他上下文(第二个赋值)中,它可以是一个类型所有可以想象的承诺。

例如,这件疯狂事件也可以很好地编译:

undefined.foo

那是因为undefined被认为是any,这是一种承诺一切的类型。嗯。

将此与

对比
var a : HTMLElement = new HTMLDivElement();
var b = new HTMLDivElement();
a = b;
b = a; // doesn't compile. phew.

在这里,我们可以得到一些强烈类型语言中更通用的东西:一个错误,作为一个显式的强制转换:

b = <HTMLDivElement>a; // ah, you mean it's really a div...

在大多数使用any的情况下,我会期待类似unknown的内容,定义为

interface unknown { }

将是更好的选择。

我首先遇到此问题,因为我的代码使用eval来解析json。 eval返回any,这意味着TypeScript认为您可以使用它完成所有操作,而无需任何强制转换。

我认为这显然是错的。将该问题与其他类型语言的工厂进行比较,例如C#:

(MyType)Activator.Create(typeof(MyType)) // cast is needed

或C ++:

// cast is needed in C++ (not in C, though I think it really should...)
(MyType*)malloc(size); 

每当我有一个产生无类型的函数的函数时,我希望在我可以将它用于任何事情之前我需要先抛出它。

所以我的问题是:

  1. 类似于any,类似于上面的unknown,是否是标准的?
  2. 如果是这样,为什么any如此突出,另一个如此隐藏?
  3. 这个问题是在某处提出的吗?有没有人可以链接的讨论?

2 个答案:

答案 0 :(得分:8)

对于第一个问题,等同于unknown的是{},空类型。当没有其他类型可以计算时,编译器有时会产生{}(例如,在['foo', 42]中,元素类型为{}之前,它变为string|number并添加了union类型)。

接下来,经常提到any的原因是,关于TypeScript的典型抱怨是它具有太多类型的强制执行,而不是太少。 JavaScript程序员似乎并不是一直在编写类型转换器。显然这是一个品味问题,但事实就是如此。

这一切都在设计上,因为TypeScript的核心方案是获取现有的JavaScript,并根据需要添加尽可能多的类型信息,而不会产生大量的吨数和大量的错误。每当TypeScript看到没有类型注释但无法推断其类型的内容时,它将使用any,因为这是允许大多数JavaScript编译而没有错误的类型。

版本1.1中修复了undefined.foo。它现在可以正确报告错误(TypeScript中undefinednull的确切处理是一个有趣但独立的讨论。)

史蒂夫提到,noImplicitAny可以提供帮助。当某些类型any没有明确的类型注释时,它会引发错误。

答案 1 :(得分:7)

any类型是一种特殊类型。在可能的情况下,除非您想利用动态类型,否则应避免使用any类型。

any类型是一种简短的说法......

  

将此变量视为与任何其他类型兼容。

所以你可以将它分配给一个字符串,一个数字,一个数组,一个对象,一个具有任何结构的接口......任何东西都可以。

因此,不要将其视为any类型,如果我将其分配给字符串,请将其视为“字符串

您可以通过传递any编译器标志(或将项目设置设置为使用此标志)来避免意外使用--noImplicitAny类型。