简体   繁体   English

TypeScript:将接口转换为类

[英]TypeScript: Convert interface to class

I have the following code: 我有以下代码:

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];

Both p2 and p3 are declared as having type X1 and are initialized with a value of type X. p2和p3都声明为具有X1类型,并使用X类型的值进行初始化。

The compiler happily accepts the declaration of p2, but it complains about p3 saying "Cannot convert 'X' to 'X1'". 编译器欣然接受p2的声明,但抱怨p3说“无法将'X'转换为'X1'”。

Why this difference? 为什么会有这种差异?

Everything that implements X should be convertible to X , but not necessarily convertible to X1 . 实现X都应可以转换为X ,但不一定可以转换为X1

Here is more detail. 这里有更多细节。 The code below shows a simple example. 下面的代码显示了一个简单的示例。 Essentially, if you have something of type X (interface) it could be implemented by either X1 (class) or X2 (class). 本质上,如果您具有X类型(接口),则可以通过X1 (类)或X2 (类)实现。

While you can downgrade a type (from the implementation down to the interface) you can't upgrade a type (from the interface to a specific implementation) because you can't guarantee that what you have is compatible. 尽管可以将类型降级(从实现降级到接口),但是不能升级类型(从接口降级到特定实现),因为您不能保证所拥有的是兼容的。

Another way of looking at this is that you can make something less specific than it is, but you can't make something more specific than it is. 另一种看待这种情况的方式是,您可以使某些事情不那么具体,但是不能做出比其具体的事情。

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...

The upshot of all of this is that you need to cast it: 所有这些的结果是您需要强制转换:

var exampleC: X1 = <X1>exampleA; // happy...

But be cautious, because you could do this, which wouldn't actually work: 但请谨慎,因为您可以执行此操作,但这实际上不起作用:

var exampleC: X2 = <X2>exampleA; // seems happy...
exampleC.myMethod(); // oh dear!

Update 更新

In respect of this piece of code... 关于这段代码...

for (var n in p1) {
    var p2 : X1 = p1[n];
}

In JavaScript this isn't equivalent to a foreach loop. 在JavaScript中,这并不等同于foreach循环。 What this is normally used for is iterating over properties in an object and when you use it on an array it will only show explicitly set indexes (not all items) . 这通常用于迭代对象中的属性,并且在数组上使用它时,它将仅显示显式设置的索引(并非所有项) To iterate over an array, you should be using: 要遍历数组,您应该使用:

for (var i = 0; i < p1.length; i++) {
    var p2 : X1 = p1[i]; // same warning as before
}

So how come TypeScript allows p1[n] to be allocated to an X1 variable? 那么TypeScript如何允许将p1[n]分配给X1变量? Interesting question and the answer lies here... 有趣的问题和答案就在这里...

If you hover over p1[n] you'll see a type of X[] - this is the type of p1 , not the type of p1[n] . 如果将鼠标悬停在p1[n] ,则会看到X[]的类型-这是p1的类型,而不是p1[n]的类型。 If you check this example, you'll find that p1[n] is of type any : 如果检查此示例,您会发现p1[n]的类型为any

var example = p1['test']; // I used 'test' because n is a string.

Because it is of type any the compiler allows you to tell it to treat it as an X1 . 因为它是any类型的,编译器都允许您告诉它将其视为X1 So you are converting from any to X1 not from X to X1 as you might have thought. 那么,你是从转换anyX1不是从XX1 ,你可能会想到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM