6

次のコードがあります。

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' に変換できません」と文句を言います。

この違いはなぜですか?

4

1 に答える 1

14

実装Xするものはすべて に変換できる必要がありますXが、必ずしも に変換できるとは限りませんX1

ここに詳細があります。以下のコードは、簡単な例を示しています。基本的に、タイプ (インターフェース) がある場合、それは(クラス) または(クラス) のXいずれかによって実装できます。X1X2

型を (実装からインターフェースに) ダウングレードすることはできますが、型を (インターフェースから特定の実装に) アップグレードすることはできません。

別の見方をすれば、実際よりも具体的でないものを作成することはできますが、実際よりも具体的なものを作成することはできません。

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

foreachJavaScript では、これはループと同等ではありません。これが通常使用されるのは、オブジェクト内のプロパティを反復することであり、配列で使用すると、明示的に設定されたインデックスのみが表示されます (すべてのアイテムではありません)。配列を反復処理するには、次を使用する必要があります。

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ています。X1XX1

于 2013-02-20T13:25:37.373 に答える