web-dev-qa-db-ja.com

TypeScriptで動的に追加されたクラスプロパティを宣言します

TypeScriptのプロパティ名、値、値のタイプを知らなくても、クラスのインスタンスにプロパティを割り当てたい。次のexample.tsスクリプトがあると仮定します。

// This could be a server response and could look totally diffent another time...
const someJson:string = '{ "foo": "bar", "bar": "baz" }'

class MyClass {
  someProperty:boolean

  constructor( json:string ) {
    const parsedJson:any = JSON.parse( json )

    Object.keys( parsedJson ).forEach(
      ( key:string ) => {
        this[ key ] = parsedJson[ key ]
      }
    )

    this['someProperty'] = true
  }
}

const myInstance = new MyClass( someJson )

// Works fine, logs `true`.
console.log( myInstance.someProperty )

// Error: Property 'foo' does not exist on type 'MyClass'.
console.log( myInstance.foo )

// Error: Property 'bar' does not exist on type 'MyClass'.
console.log( myInstance.bar )

TypeScriptコンパイラが動的に追加されたプロパティについて文句を言わず、代わりにそれらを任意のタイプの"key": valueペアとして処理することを確認するにはどうすればよいですか。 tscmyInstance.somePropertyのタイプがbooleanである必要があることを確認したいのですが、実行せずに定義されていなくてもmyInstance.whateverを取得できるようにしたいコンパイラエラーに。

これを明確にするドキュメントは見つかりませんでした。たぶん私は英語を母国語としないからでしょう。ですから、答えは単純にしてください。

編集:

次のようなものがあったことを覚えていますが、それが機能することはありませんでした。

interface IMyClass {
  [name:string]: any
}
9
headacheCoder

問題は、実行時に新しいプロパティを追加していて、コンパイラがそれを知る方法がないことです。

プロパティ名を事前に知っている場合は、次のことができます。

type Json = {
    foo: string;
    bar: string;
}

...

const myInstance = new MyClass(someJson) as MyClass & Json;
console.log(myInstance.foo) // no error

編集

事前にプロパティがわからない場合は、これを行うことはできません。

console.log(myInstance.foo);

fooが受信したjsonの一部であることがわかっているので、おそらく次のようになります。

let key = getKeySomehow();
console.log(myInstance[key]);

そして、これはコンパイラからのエラーなしで機能するはずです。それに関する唯一の問題は、コンパイラが戻り値の型を知らないことであり、それはanyになります。

だからあなたはこれを行うことができます:

const myInstance = new MyClass(someJson) as MyClass & { [key: string]: string };
let foo = myInstance["foo"]; // type of foo is string
let someProperty = myInstance["someProperty"]; // type of someProperty is boolean

2回目の編集

あなたは小道具を知っていますが、クラスでは知らないので、あなたは次のことができます:

type ExtendedProperties<T> = { [P in keyof T]: T[P] };
function MyClassFactory<T>(json: string): MyClass & ExtendedProperties<T> {
    return new MyClass(json) as MyClass & ExtendedProperties<T>;
}

次に、次のように使用します。

type Json = {
    foo: string;
    bar: string;
};
const myInstance = MyClassFactory<Json>(someJson);

これはTypeScript2.1以降でのみ機能することに注意してください。

10
Nitzan Tomer