web-dev-qa-db-ja.com

TypeScriptの「instanceof」が「「Foo」は型のみを参照していますが、ここでは値として使用されています」というエラーを表示するのはなぜですか?

このコードを書きました

interface Foo {
    abcdef: number;
}

let x: Foo | string;

if (x instanceof Foo) {
    // ...
}

しかし、TypeScriptは私にこのエラーを与えました:

'Foo' only refers to a type, but is being used as a value here.

なぜこうなった? instanceofは、値に特定の型があるかどうかを確認できると思っていましたが、TypeScriptはこれを好まないようです。

51

どうしたの

問題は、 instanceof がJavaScriptからのコンストラクトであり、JavaScriptではinstanceofが右側のオペランドにvalueを期待していることです。 。具体的には、x instanceof Fooで、JavaScriptはFoo.prototypexのプロトタイプチェーンのどこかに存在するかどうかを確認するためにランタイムチェックを実行します。

ただし、TypeScriptでは、interfacesには出力がありません。つまり、FooFoo.prototypeも実行時に存在しないため、このコードは間違いなく失敗します。

TypeScriptは、これがnever動作する可能性があることを伝えようとしています。 Fooは単なる型であり、値ではありません!

instanceofの代わりに何ができますか?」

type guardsおよびuser-defined type guards を調べることができます。

「しかし、ちょうどinterfaceからclassに切り替えた場合はどうなりますか?」

interfaceからclassに切り替えたいと思われるかもしれませんが、TypeScriptの構造型システム(主にshape based)特定のクラスと同じ形状を持つオブジェクトを作成できます。

class C {
    a: number = 10;
    b: boolean = true;
    c: string = "hello";
}

let x = new C()
let y = {
    a: 10, b: true, c: "hello",
}

// Works!
x = y;
y = x;

この場合、同じタイプのxyがありますが、どちらかでinstanceofを使用しようとすると、反対の結果が得られます。そのため、instanceofreallyではありません。TypeScriptで構造型を利用している場合、型について詳しく説明しません。

62

ダニエル・ローゼンワッサーは正しくてダンディかもしれませんが、彼の答えを修正したい気がします。 xのインスタンスを確認することは完全に可能です。コードスニペットを参照してください。

ただし、x = yを割り当てるのも同様に簡単です。 yはCの形状しかなかったため、xはCのインスタンスではなくなりました。

class C {
a: number = 10;
b: boolean = true;
c: string = "hello";
}

let x = new C()
let y = {
    a: 10, b: true, c: "hello",
}

console.log('x is C? ' + (x instanceof C)) // return true
console.log('y is C? ' + (y instanceof C)) // return false
1