我刚刚开始学习 TypeScript,我对 any
的性质有点困惑。看看这个:
var x: any = 1;
var y = 1;
x = y;
y = x; // why does this not cause a compile-time error?
起初我将 any
理解为没有任何 promise 的类型——这就是为什么第一个赋值是合理的——但似乎在其他情况下(第二个赋值),它可以是具有所有可能的 promise 的类型。
例如,这段 insanity 也编译得很好:
undefined.foo
那是因为 undefined
被假定为 any
,这是一种 promise 一切的类型。嗯。
对比一下
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);
每当我有一个生成未类型化的东西的函数时,我希望在我可以将它用于任何事情之前我需要转换它。
所以我的问题是:
- 有没有类似于
any
,类似于上面的unknown
,那是标准的? - 如果是这样,为什么
any
如此突出而另一个如此隐藏? - 这个问题有人提出过吗?是否有任何人都可以链接到的讨论?
最佳答案
对于第一个问题,unknown
等价于 {}
,即空类型。当无法计算其他类型时,编译器有时会生成 {}
(例如,在 ['foo', 42]
中,元素类型为 {}
在它成为 string|number
添加联合类型之前)。
接下来,any
经常被提及的原因是关于 TypeScript 的典型提示是它有太多类型强制,而不是太少。 JavaScript 程序员似乎并不是一直都在编写类型转换。显然这是一个品味问题,但事实就是如此。
这在很大程度上是设计使然,因为 TypeScript 的核心场景是采用现有的 JavaScript 片段,并根据需要添加尽可能多的类型信息,而不会出现大量错误。每当 TypeScript 发现无法推断其类型的没有类型注释的内容时,它将使用 any
因为这是让大多数 JavaScript 编译无误的类型。
undefined.foo
问题在 1.1 版中得到修复。它现在可以正确报告错误(TypeScript 中 undefined
和 null
的确切处理是一个有趣但单独的讨论)。
正如史蒂夫提到的,noImplicitAny
可以提供帮助。当没有显式类型注释的 any
类型时,它会引发错误。
关于TypeScript:从任何到一切的隐式转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27081405/