DRYな備忘録

Don't Repeat Yourself.

TypeScriptで「プロパティ名 is inaccessible.」とか言われる

問題

下記のコードをコンパイルしようとすると、叱られます

module Unko {
    class Hoge {
        constructor(public a: any, public b: any){}
    }

    export class Fuga {
        constructor(public a: any, private b: any){}
    }

    export class Piyo {
        constructor(a: any, b: any){}
    }
}

var hoge = new Unko.Hoge(1,2);
console.log(hoge.a, hoge.b);

var fuga = new Unko.Fuga(3,4);
console.log(fuga.a, fuga.b);

var piyo = new Unko.Piyo(5,6);
console.log(piyo.a, piyo.b);

以下のように叱られました

% tsc test.ts
test.ts(15,21): error TS2094: The property 'Hoge' does not exist on value of type '{ Fuga: new(a: any, b: any) => Unko.Fuga; Piyo: new(a: any, b: any) => Unko.Piyo; }'.
test.ts(19,26): error TS2107: 'Unko.Fuga.b' is inaccessible.
test.ts(22,18): error TS2094: The property 'a' does not exist on value of type 'Unko.Piyo'.
test.ts(22,26): error TS2094: The property 'b' does not exist on value of type 'Unko.Piyo'.

解説

The property 'Hoge' does not exist

Unkoに'Hoge'プロパティなんて無いよ!

と言っているようです。module宣言の中で定義されたclassexportしないと外部から参照できません。exportしてあげましょう。

'Unko.Fuga.b' is inaccessible.

'Unko.Fuga.b'はアクセスできないよ!

と言っているようです。アクセスレベルかprivateになっているから当然ですね。publicにしてあげましょう。

The property 'a' does not exist

'Unko.Piyo'に'a'なんてプロパティ無いよ!

と言っているようです。TypeScriptではコンストラクタに渡す変数の頭にアクセスレベルを書くと勝手にメンバ変数にしてくれるのでthis.aでアクセスできますが、書かないと単にコンストラクタ関数に渡される引数といっしょです。アクセスレベルを書いてあげるか、コンストラクタの中でthis.a = aなどと書いてバインドしてあげましょう。

参考

コンパイル後のJSはこんな感じです。

var Unko; // モジュールをグローバルに定義して
(function (Unko) {
    var Hoge = (function () {
        function Hoge(a, b) {
            this.a = a;
            this.b = b;
        }
        return Hoge;
    })();
// ← ここでグローバルなモジュール`Unko`のプロパティとして登録してないことが分かります

    var Fuga = (function () {
        function Fuga(a, b) {
            this.a = a;
            this.b = b;
// ← this.bには入れてるので、privateへのアクセス制限はあくまでTypeScript的な問題のようです
        }
        return Fuga;
    })();
    Unko.Fuga = Fuga;
// ← 一方ここは`Unko`のプロパティとして登録してます

    var Piyo = (function () {
        function Piyo(a, b) {
// ← 渡されたa,bは`Piyo`のプロパティとして登録されてないことが分かります
        }
        return Piyo;
    })();
    Unko.Piyo = Piyo;
})(Unko || (Unko = {}));
// 即時実行関数にグローバルに宣言されている`Unko`を渡していることが分かります

var hoge = new Unko.Hoge(1, 2);
console.log(hoge.a, hoge.b);

var fuga = new Unko.Fuga(3, 4);
console.log(fuga.a, fuga.b);

var piyo = new Unko.Piyo(5, 6);
console.log(piyo.a, piyo.b);

雑感

マヂ無理…

仕事しょ…