我有以下代码:
interface X {
type : string;
val : number;
}
class X1 implements X {
type : string;
val : number;
}
var p1 : X[] = [{type:'a', val:8}];
for (var n in p1) {
var p2 : X1 = p1[n];
}
var p3 : X1 = p1[0];
p2和p3都声明为类型X1,并使用类型X的值进行初始化。
编译器很乐意接受p2的声明,但它抱怨p3说“无法将'X'转换为'X1'”。
为什么会出现这种差异?
答案 0 :(得分:6)
实施X
的所有内容都应该可以转换为X
,但不一定能转换为X1
。
这里有更多细节。下面的代码显示了一个简单的示例。从本质上讲,如果你有类型X
(接口)的东西,它可以由X1
(类)或X2
(类)实现。
虽然你可以降级类型(从实现到接口),但你无法升级类型(从接口到特定的实现),因为你不能保证你拥有的是兼容的。
另一种看待这种情况的方法是,你可以制作一些 less 特定的东西,但是你不能制作一些更多特定的东西。
interface X {
type : string;
val : number;
}
class X1 implements X {
type : string;
val : number;
}
class X2 implements X {
type: string;
val: number;
myMethod() {
}
}
var x1 = new X1();
var x2 = new X2();
var exampleA: X = x1; // happy
var exampleB: X = x2; // happy
var exampleC: X1 = exampleA; // Not happy...
所有这一切的结果是你需要施展它:
var exampleC: X1 = <X1>exampleA; // happy...
但要小心,因为你可以这样做,这实际上不起作用:
var exampleC: X2 = <X2>exampleA; // seems happy...
exampleC.myMethod(); // oh dear!
<强>更新强>
关于这段代码......
for (var n in p1) {
var p2 : X1 = p1[n];
}
在JavaScript中,这不等同于foreach
循环。通常用于迭代对象和when you use it on an array it will only show explicitly set indexes (not all items)中的属性。要遍历数组,您应该使用:
for (var i = 0; i < p1.length; i++) {
var p2 : X1 = p1[i]; // same warning as before
}
那么TypeScript如何将p1[n]
分配给X1
变量呢?有趣的问题和答案就在这里......
如果您将鼠标悬停在p1[n]
上,则会看到X[]
的类型 - 这是p1
的类型,而不是p1[n]
的类型。如果您查看此示例,则会发现p1[n]
的类型为any
:
var example = p1['test']; // I used 'test' because n is a string.
因为它是any
类型,编译器允许您告诉它将其视为X1
。因此,您正在从any
转换为X1
,而不是从X
转换为X1
。