aknow2

自分の興味のある事を連々と(プログラミング、モバイルアプリ、プログラミング教育)

TypescriptのInterfaceにはinstanceofは使えない。

Typescriptには、JavaやC#と同じ様にinterfaceがあります。
が、JavaC#と同じ様に扱うと怪我をします。

instanceofでinterfaceは使えない。

最初に私がビックリした事です。JavaC#では'instanceof 'で型をチェックしたり、条件分岐で使えたりします。が、Typescriptでは使えません。 例えば、IActionを定義してActionというクラスで実装して見ます。それをinstaceof IActionでチェックしてみると、、、

interface IAction {
  dosomething(): void;
}

class Action implements IAction {
  dosomething() {
    console.log('hoge');
  }
}

if (Action instanceof IAction) {
  // something to do
}

VScodeを使っていれば、if文の'IAction'の箇所でインテリセンスによってエラーが出ます。

[ts] 'IAction' only refers to a type, but is being used as a value here.

訳すと、IActionは型としてしか参照出来ません、ここでは値として参照されています。。。
これはどういう事でしょうか?JavaC#脳の人にとっては混乱するエラー文です。
instanceof はタイプ、型で検査するのだから合っているのでは?値として参照とはどういう事?
コレが何故ダメなのか、すぐに分かる方法があります。 試しにIActionの例のif文の部分を削除して、Javascriptコンパイルしてみましょう。
すると↓の様になります。

var Action = /** @class */ (function () {
    function Action() {
    }
    Action.prototype.dosomething = function () {
        console.log('hoge');
    };
    return Action;
}());

なんと、Javascript変換すると'IAction'は存在しなくなっています!
これで何故interfaceinstanceofが使えないのか分かった様な気がします。
interfaceinstanceofで比較しようにも、Javascript上に存在しないので比較出来ません。 そして、型とはJavascriptに変換後と評価出来ないもの、値とはJavascriptに変換後も評価可能なものと言えます。

というわけで、どうあがいてもTypescriptのinterfaceではinstaceofを使った型チェックをする事が出来ません。

どうしてもinstanceofを使いたいという人はinterfaceではなくclassを使うしかないでしょう。classはjavascript変換後にも残りますし、Typescript上でも型としても認識されます。抽象classを上手く使えば良いかも。

abstract class BaseAction {
  abstract dosomething(): void;
}

class Action extends BaseAction {
  dosomething() {
    console.log('hoge');
  }
}

if (Action instanceof BaseAction) { // true
  // something to do
}