Help us understand the problem. What is going on with this article?

自作Eventクラスに入力補完を適用させる

More than 1 year has passed since last update.

はじめに

TypeScript を使って、Node.jsのアプリケーションを開発しているときに、 入力補完 は活用していることでしょう。
この記事は、 引数が特定の条件である場合の入力補完を効かせる方法 を、 EventEmitter の拡張を題材として執筆しました。

コーディング

作成したコードは walk8243/TypeScript-EventEmitter にあります。

目的の 引数が特定の条件である場合の入力補完を効かせる方法 を実現するために重要となる技術は、 オーバーロード です。
ということで、オーバーロードについて書いていきます。

オーバーロード

詳しく知りたい方は、 TypeScript Deep Dive をご一読ください。

まず、普通にクラスを作成してみます。

class Power {
  get(type: string, index: number) {
    if(type == 'square') {
      return index ^ 2;
    } else {
      throw new Error('type is `square` only.');
    }
  }
}

次に、これにオーバーロードしてみます。

class Power {
  get(type: 'square', index: number): number;
  get(type: string, index: number) {
    if(type == 'square') {
      return index ^ 2;
    } else {
      throw new Error('type is `square` only.');
    }
  }
}

このようにすることで、入力補完として第一引数に square が表示されるようになります。
また、次のように書くこともできます。

class Power {
  get(type: 'square', index: number) {
    if(type == 'square') {
      return index ^ 2;
    } else {
      throw new Error('type is `square` only.');
    }
  }
}

オーバーロードするときのポイントとしては、必ず 処理を行う関数・メソッドを書くこと です。
例え、クラスで親クラスのメソッドをそのまま使う場合であっても、メソッドを書く必要があります。
次に実際にEventEmitterを継承したクラスでもって試してみたいと思います。

EventEmitterの継承

イベントとして、 keyboard, enter, escape, mouse の4つ作成しました。

import { EventEmitter } from 'events';
export class Event extends EventEmitter {
  on(event: 'keyboard', listener: () => void): this; // listenerに引数無しのパターンを作成
  // on(event: 'keyboard', listener: () => void): this; // すべての引数が同じパターンを記述することはできない
  on(event: 'enter' | 'escape', listener: () => void): this; // listenerの引数のパターンが同じなのでまとめる
  on(event: 'mouse', listener: (mouseX: number, mouseY: number) => void): this; // listenerに引数を追加
  on(event: string, listener: (...args: any[]) => void) {
    return super.on(event, listener); // 継承元を呼び出すだけでも処理を書く
  }

  emit(event: 'keyboard' | 'enter' | 'escape'): boolean; // 引数のパターンが同じなのでまとめる
  emit(event: 'mouse', x: number, y: number): boolean; // 引数のパターンが違うので分ける
  emit(event: string, ...args: any[]) {
    return super.emit(event, ...args); // 処理を書く
  }
}

これで以下のように入力補完を使うことができるようになりました。

入力補完1.jpg
入力補完2.jpg

おわりに

基本的に入力補完の効くエディタで開発をしていることと思います。
複数人で開発している場合、誰かが開発したコードを違う人が使うようなケースがあることと思います。
そのような場合、ドキュメントだったり口頭だったりで使い方を伝えてもいいですが、簡単な部分に関しては入力補完で事足りることでしょう。
また、TypeScriptの型定義は、入力補完だけでなく、コンパイルにチェックしてくれるので、デプロイ前にエラーを発見することにも繋がります。
積極的に型定義を行っていきましょう!

オーバーロードのまとめ

型定義をしていく上で、オーバーロードを使う機会は出てくると思うので、最後に使い方をまとめておきます。

  1. 必ず処理を書く。
  2. 型を詳細化するようにオーバーロードする
  3. 全く同じ引数の型パターンでは記述できない
walk8243
ただの乃木オタです。 業務中に感じた良く分からない気持ち悪さを、形にして解決するにはどうしたらいいかを考えながら記事を書いてます。 執筆は握手会の会場でできるからいいですね!
yahoo-japan-corp
Yahoo! JAPAN を運営しています。
https://www.yahoo.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした