LoginSignup
11
12

More than 5 years have passed since last update.

TypeScriptでstaticなfactory methodを作る

Posted at

実行環境

$ tsc --version                                                                                                                                                                                                                
Version 2.7.2

コード


interface IUser {
  name: string;
}

class BaseUser implements IUser {
  name: string;

  constructor(initial: Partial<IUser>) {
    (<any>Object).assign(this, initial);
  }

  static createCollection<T extends BaseUser>(
    this: {new(initial): T},
    collectionData
  ): T[] {
    const collection: T[] = [];
    collectionData.forEach(data => {
      const initialData = data as IUser;
      collection.push(new this(initialData));
    });
    return collection;
  }

}

class Manager extends BaseUser {
}

class Programmer extends BaseUser {
}

const array = [
  {name: 'test1'},
  {name: 'test2'},
]

const managers = Manager.createCollection(array)
console.log(managers) // => [ Manager { name: 'test1' }, Manager { name: 'test2' } ]

const programmers = Programmer.createCollection(array)
console.log(programmers) // => [ Programmer { name: 'test1' }, Programmer { name: 'test2' } ]

Userの初期値のオブジェクトの配列などを渡したら、Userクラスインスタンスの配列が返ってきて欲しいときにつかいたいやつ。
肝心のそのstaticメソッドは createCollection
基底クラスなどにこのメソッドを仕込んでおけば、いちいちクラスを渡すこと無く、基底クラスの継承先クラスのインスタンスが返ってきて便利。

 なにをやってるのか

this: {new(initial): T}

functionの第一引数にthisとその型を渡すと、自分でthisの型を決定できる。
https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters

さらに、コンストラクタシグネチャを使って、Tというconcrete classのインスタンスを返すコンストラクタを持つオブジェクト型をthisの型として指定する。

単純に this: T などとすると error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.というエラーがでてしまうので、ちょっと回りくどい感じになってる。

参考issue

この書き方はTypeScriptのissuesを参考にしてる。
https://github.com/Microsoft/TypeScript/issues/5863
issueが長すぎるので、みんな結構staticでいい感じにthisを使うのは苦労してるみたい…

別解

  static createCollection<T extends BaseUser>(
    this: new (initial) => T,
    collectionData
  ): T[] {

こういう書き方でも同じような結果になるけど new (initial) => T の部分がどういう書き方なのか、何故こうなるのかが分からない…ご存じの方いたら教えてください :bow:

11
12
0

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
11
12