2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TypeScript:constructorの引数でクラス変数の定義を省略する方法

Posted at

はいさい!ちゅらデータぬオースティンやいびーん!

概要

TypeScriptでclass構文を書く時に、constructor関数の引数にpublicprotectedおよびprivateの接頭辞を使うと、同時にインスタンス変数の定義ができるので、その手法を紹介します。

背景

AngularServiceの説明を読んでいたのですが、不思議な書き方を見て気になりました。

export class HeroService {
  private heroes: Hero[] = [];

  constructor(
    private backend: BackendService, // これです
    private logger: Logger) { }

  getHeroes() {
    this.backend // しかもこうやって定義していないはずのクラス変数を使っているし
      .getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }
}

どういうことだろうと思い、TypeScriptのドキュメントを調べました。

その結果を本記事で備忘録代わりにまとめます。

コンストラクター割り当て(Constructor Assignment)

このTypeScriptの構文をConstructor Assignmentと言っています。

TypeScriptならではの速記手法です。

例えば通常、こう書くでしょう。

class MyObject {
    private name: string;

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

    public getName(): string {
        return this.name;
    }
}

const obj = new MyObject("austin");
console.log(obj.getName()); // "austin"

しかし、同じことが以下のような省略記述で表現できます。

class MyObject {
    constructor(private name: string) {}

    public getName(): string {
        return this.name;
    }
}

const obj = new MyObject("austin");
console.log(obj.getName());

かなりすっきりしますね。

ぱっと見てAngularの魔法に見えたのが実はちゃんとしたTypeScriptだったので安心しました。

Angularはちゃんとルールを守る優等生

publicも、protectedも同様に使える

privateのみならず、publicprotectedで同様な記述法ができます。

public

class MyObject {
    constructor(public name: string) {}
}

const obj = new MyObject("austin");
console.log(obj.name);

protected

class MyObject {
    constructor(protected name: string) {}
}

class ExtendedObject extends MyObject {
    get objName(): string {
        return this.name;
    }
}

const obj = new ExtendedObject("austin");
console.log(obj.objName);
console.log(obj.name); // TS Error 

まとめ

以上、クラス構文のconstructorメソッドでクラス・インスタンス変数を定義する速記法を紹介しました。

使うかどうかはいいとして、見た時に、「こういうことをやっているのだな」とわかればいいのかなと思います。

冗長なコードは必ずしも悪いコードではありません。

見てすぐにわかるようなコードが何よりもいいコードであるのです。

なので、筆者としてはこの手記法を推奨するというよりは、プロジェクトによって最もわかりやすい書き方を優先するべきだと考えています。

脱線ですが、パフォーマンスにこだわって読みやすさを犠牲にするスタイルは世の中にあります。いわゆる パフォーマンス至上主義 という考え方です。

筆者は真っ向からその考え方は間違っていると思います。

例えループが一つ増えたとしても、それによってわかりやすく書けるのであれば、ループを一つ増やしましょう。

(但し、ループの中のループ、いわゆるnested loopは避けましょう!)

数ヶ月後の、そのコードを書いた自分が、感謝してくれますよ。数ヶ月後の自分を思いやりましょう。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?