2017-01-26 10 views
2

このようDeepReadonlyタイプを作成することが可能である:DeepReadonlyオブジェクト活字体

type DeepReadonly<T> = { 
    readonly [P in keyof T]: DeepReadonly<T[P]>; 
}; 

interface A { 
    B: { C: number; }; 
    D: { E: number; }[]; 
} 

const myDeepReadonlyObject: DeepReadonly<A> = { 
    B: { C: 1 }, 
    D: [ { E: 2 } ], 
} 

myDeepReadonlyObject.B = { C: 2 }; // error :) 
myDeepReadonlyObject.B.C = 2; // error :) 

これは素晴らしいです。 BB.Cの両方が読み取り専用です。私は...しかしDを変更しようとすると

// I'd like this to be an error 
myDeepReadonlyObject.D[0] = { E: 3 }; // no error :(

にはどうすれば DeepReadonlyは、ネストされた配列が読み取り専用にもあるように書くべき?

+0

'console.log(myDeepReadonlyObject.D [0]);'あなたはどのタイプのタイスクリプトを使用していますか? –

+0

私はtsconfigに "noImplicitAny"フラグを設定しました。しかし、依然として疑問が残っています。私はそれをもっと明確に更新しました。ありがとう。おかげさまで –

答えて

1

あなたは読み取り専用の配列持つことができます。

interface ReadonlyArray<T> extends Array<T> { 
    readonly [n: number]: T; 
} 
let a = [] as ReadonlyArray<string>; 
a[0] = "moo"; // error: Index signature in type 'ReadonlyArray<string>' only permits reading 

をしかし、あなたはあなたのソリューションとそれを使用することはできません。

interface A { 
    B: { C: number; }; 
    D: ReadonlyArray<{ E: number; }>; 
} 

myDeepReadonlyObject.D[0] = { E: 3 }; // still fine 

DのタイプはDeepReadonly<ReadonlyArray<{ E: number; }>>であり、それはReadonlyArrayを許可しません。

私はあなたがそれを使ってオブジェクトを持つオブジェクトにすることはできないと思っていますが、あなたが一般的なインタフェース/タイプを必要とし、特定のものではない場合は、オブジェクトのためのものです。代わりに、一般的な1 DeepReadonly

interface A { 
    readonly B: { readonly C: number; }; 
    D: ReadonlyArray<{ E: number; }>; 
} 

const myDeepReadonlyObject = { 
    B: { C: 1 }, 
    D: [{ E: 2 }], 
} as A; 

myDeepReadonlyObject.B = { C: 2 }; // error 
myDeepReadonlyObject.B.C = 2; // error 
myDeepReadonlyObject1.D[0] = { E: 3 }; // error 

をしかし、それはそれ(A)に特定のインターフェイスを持っています
たとえば、これは正常に動作します。

もう1つのオプションは、組み込みの定義ファイルが付属しているImmutable.jsを使用することです。使いやすいです。

+0

これはまだ現実的ではないようだ。誰でも作品があれば分かりますか? –