$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

TypeScriptの型を手に馴染ませるためにやっていること

最近TypeScriptが好きで勉強していっている。しかしなかなか型定義周りが手に馴染まず、少し複雑な型定義を読んだり、自分でユーティリティ型を定義したりすることが難しかった。

そこで型を手に馴染ませるために色々学習をしてみたので、やっていることをメモしておく。

まずざっとTypeScriptの型概要を学ぶ

まずTypeScriptでの型を簡単に学ぶには以下の2つの資料がわかりやすかった。

ひたすら型演習をする

資料を読むだけでは全く手に馴染まないと思ったので、その後ひたすら型演習をしている。

まずは TypeScriptの型演習 - Qiita 。これは先程の型初級、型入門の記事を書いた人が演習問題を作っているため同じ流れで学習でき、さらに解説編も充実しているので、手を動かしながら学ぶのに最適であった。これを自分で二周解いてみた。

1周目に比べて、2周目では解ける問題が増え、解く速度も上がった。いい感じに復習効果で定着してきているので、周回してみたのは良かったと思う。もう1周くらいやってみても良さそう。

さらにtype-challengesの演習問題も解いてみている。こちらはまだ1周目のmediumまで。こっちも何回か周回してみると良さそう。

面白かった話題

union distribution

union distributionは頻出なんだけど、めちゃくちゃ難しかった。https://qiita.com/uhyo/items/da21e2b3c10c8a03952f#conditional-type%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Bunion-distribution にわかりやすい解説がある。

自分の中では、union型でforループやfilter、mapが出来て便利だね、という理解に落ち着いた(全然理解が正確では無いと思うけど...)。

-?を使ってフィールドをundefinedで無くす

こういう書き方が出来る。

type Type1<Obj> = {
  [Key in keyof Obj]-?: Obj[Key]
};
type Type2 = Type1<{
  hoge?: number;
  fuga: string;
  piyo?: undefined;
}>;

// 以下のような定義になる
// type Type2 = {
//     hoge: number;
//     fuga: string;
//     piyo: never;
// }

型レベルで検証する型を作れる

https://github.com/type-challenges/type-challenges/blob/f9b3bb0b5f7e9095be840fe3cba154f6f0566693/utils/index.d.ts が面白かった。こういう型を作ることで、

type ExpectHogeAndFugaEqual = Expect<Equal<Hoge, Fuga>>;

のように書いておくと、HogeとFugaの型が一致するなら型チェックが通り、HogeとFugaの型が一致しないなら型エラーで落ちてくれる。

まとめ

今回はTypeScriptの型を手に馴染ませるためにやっていることについてメモしてみた。徐々に型定義ファイルを読めるようになってきていて、自分でもちょっとした型を作れるようにもなってきているので、このまま演習を続けていきたい。

VSCodeのFindで今マッチしている場所にボーダーを引いて見やすくする

VSCodeでFindしている時に、マッチしているwordは背景色が変わって分かるのだけど、今どこにフォーカスしているかが分かりづらかった。これが特に問題が起こるのがReplaceをしようとしている時で、Replaceするたびに今どこ?とマッチ箇所を探していた。これだと時間がかかって困る。

調べてみるとTheme Color | Visual Studio Code Extension APIに書かれているように、自分のsettings.json内で自分用に色を調整し、見やすくカスタマイズ出来ることが分かった。これでFindの現在のマッチ箇所を見やすくしてみる。

Findの色のカスタマイズは

  • editor.findMatchBackground: Color of the current search match.
  • editor.findMatchHighlightBackground: Color of the other search matches. The color must not be opaque so as not to hide underlying decorations.
  • editor.findRangeHighlightBackground: Color the range limiting the search (Enable 'Find in Selection' in the find widget). The color must not be opaque so as not to hide underlying decorations.
  • editor.findMatchBorder: Border color of the current search match.
  • editor.findMatchHighlightBorder: Border color of the other search matches.
  • editor.findRangeHighlightBorder: Border color the range limiting the search (Enable 'Find in Selection' in the find widget).

あたりで設定できる。最初は背景色を調整しようと思ったのだが、同時に文字色を変える方法がわからず、逆に見づらくなってしまったので、borderの色を調整してみた。設定は以下の通り。

  "workbench.colorCustomizations": {
    "[Default Dark+]": {
      "editor.findMatchBorder": "#FDFF0C"
    }
  },

これでDefault Dark+テーマで現在のマッチ箇所に黄色のborderが引かれる。

Image from Gyazo

もうちょっとborderの辺りにpaddingがほしいな〜と思うものの、これで前よりはだいぶ見やすくなって便利ですね。

VSCodeの置換でEmacs風の挙動を再現する

個人的にEmacsの置換のy/nで一つずつ置換するかしないか決められるUXが好きなので、VSCodeの置換でも近しいことが出来るように設定してみた。以下のような設定をすると、Replaceのインプットにフォーカス中にcmd+yでReplace実行、cmd+nでスキップということが出来る。便利。

keybindings.json

  // replaceでy/nでreplaceするかしないか選べることを模倣
  {
    "key": "cmd+y",
    "command": "editor.action.replaceOne",
    "when": "editorFocus && findWidgetVisible && replaceInputFocussed"
  },
  {
    "key": "cmd+n",
    "command": "editor.action.nextMatchFindAction",
    "when": "editorFocus && findWidgetVisible && replaceInputFocussed"
  }