LoginSignup
232
151

More than 5 years have passed since last update.

TypeScriptのclassをオブジェクトで初期化する

Last updated at Posted at 2017-09-29

一般的な初期化方法

TypeScriptにおいてclassの初期化を行う際、多くの場合はconstructorを利用するかと思います。以下のPerson classを例にしてconstructorを使用した初期化処理を見てみましょう。

class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

const takashi = new Person('Takashi', 70);

ここでは、Person classはnameageという2つのプロパティを持っており、constructorにそれぞれの値を渡すことで、各プロパティの初期化を行っています。
これはごく基本的な初期化方法ですが、あらかじめ初期化に使用することのできるオブエジェクトをAPIサーバーなどから受け取っている場合、初期化を行うためのコードが冗長になりがちです。下のコードを見てみましょう。

// 何らかのAPIコールで人の情報を取得
server.getPerson().then(person => {
  // person === {name: 'Takashi', age: 70}

  const takashi = new Person(person.name, person.age);
});

上の例では、各プロパティを別々のパラメータとしてconstructorに渡しているため、コードの記述量が多くなってしまっています。personをパラメータとして直接渡せたらどんなに楽でしょう。それを実現するための手段がPartialです。

Partial

PartialはTypeScript 2.1から導入されたtypeで、Partial<T>と指定した時に、Tが持つ全てのプロパティをオプションとした型として振る舞う性質を持っています。これはどういうことでしょうか。以下の例を見てみましょう。

例えば、次のようなPerson classを定義していると仮定します。

class Person {
  name: string;
  age: number;
}

この際、Partial<Person>を使用すると、Personが持つnameageというプロパティがオプションとなった型として扱われます。つまり、下記コードのabは、同じ型の変数として振る舞います。

const a: Partial<Person>;

const b: { name?: string, age?: number };

// aとbは同様の型として振る舞う

この効果を利用することで、上述したconstructorをより簡潔に記述することができます。

Partialを使ったconstructor

それでは、Partialを利用したconstructorの記述例を見てみましょう。Partialを利用することで、冒頭で記述したPerson classのconstructorは以下のように定義することができます。

class Person {
  name?: string;
  age?: number;

  constructor(init?: Partial<Person>) {
    Object.assign(this, init);
  }
}

見て分かるように、PersonのconstructorにはPartial<Person>のパラメータを渡すように定義しています。こうして渡されたパラメータをObject.assignを使用して自身へと割り当てることで、各プロパティへと値がセットされます。これにより、以下のようにPersonのconstructorに直接オブジェクトをパラメータとして渡すことができます。

const obj = {
  name: 'Takashi',
  age: 70,
};

const takashi = new Person(obj);

console.log(takashi.name); // => 'Takashi'
console.log(takashi.age); // => 70

継承したclassの場合

先ほどの Person classを継承したclass Programmerを定義することを考えてみましょう。この場合でも、constructor内で値をセットすることで、同様にオブジェクトからclassを初期化することが可能です。

class Programmer extends Person {
  salary: number;
  skills: Array<{ lang: string, rate: number }>;

  constructor(init?: Partial<Programmer>) {
    super();
    Object.assign(this, init);
  }
}

Programmerを初期化する例は以下の通りです。

const obj = {
  name: 'Takashi',
  age: 70,
  salary: 200,
  skills: [
    { lang: 'JavaScript', rate: 5 },
    { lang: 'Ruby', rate: 2 },
  ],
};

const takashi = new Programmer(obj);

console.log(takashi.name); // => 'Takashi'
console.log(takashi.age); // => 70
console.log(takashi.salary); // => 200
console.log(takashi.skills); // => [{lang: 'JavaScript', rate: 5}, {lang: 'Ruby', rate: 2}]

このように、Partialを利用することで、オブジェクトから簡単にclassを初期化することができます。やったね! :tada:

参考

TypeScript and field initializers

232
151
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
232
151