LoginSignup
23
20

More than 3 years have passed since last update.

YYTypeScript#6「JSのプロジェクトにTypeScriptを入れるときの知見」「aspida.jsはAPIクライアントを自動生成するツール」「WebStormとPrettierの相性悪い?」「TypeScript 3.7では何が変わる」「関数型のテストの書き方」「TypeScriptのエディタはVS CodeかIntelliJか」

Posted at

これは2019年10月25日に開催したTypeScriptイベントYYTypeScript#6のイベントレポートです。

YYTypeScriptは一言で「TypeScripterの部室」です。発表者の話を聞く「一方向的な勉強会」とは真逆で、TypeScriptについて、雑に・ゆるく・ワイワイ話しながらTypeScripter同士の交流を深める「双方向的な座談会」の形式になります。集まった人たちで「今日話たいこと」「聞きたいこと」をいくつか挙げていき、それをテーマに雑談していきます。

今回の配信動画

過去回の配信動画YouTubeプレイリスト「YYTypeScript」
前回YYTypeScript#5「TSの好きな機能って何?」「enumは避けるべきか」「TSを選んだ理由を教えて」「業務で犯した型がらみの失敗談」「ソースマップも含めてnpm publishすべき?」「関数で書く派ですか?クラスで書く派ですか?」 - Qiita

雑談

JavaScriptのプロジェクトにTypeScriptを入れるときの知見を聞きたい (えあんぬ)

  • allowJSの知見など知りたい。
  • 1,900ファイルぐらいあるけっこうでかいプロジェクト
    • 1900ファイルあるプロジェクトでJSで書くのもしんどそう。。
  • ts化して型安全にしたい
  • ts化したらエラーが多すぎてつらい

  • noImplicitAny: falseをセットする

  • allowJS: true?

  • // @ts-ignore とコードに書くと、次の行のコンパイラチェックを抑制できる

    • ファイル単位での記述になるので、どうしてもやむを得ない時に、ピンポイントで使える
  • そんなにファイル数がないプロジェクトで

    • tsconfigで設定をかなりゆるめにして、1ファイルずつTSに移行した
  • noImplicitAnyはできればやりたくない

    • 既存コード用のtsconfigと、新規コード用のtsconfigをわけるとか?
      • パッケージルートの tsconfig.jsonroot: true にして、ディレクトリ内部でextendsできます、たしか
  • Migrating from JavaScript · TypeScript

  • tslintで型アノテーションを強制する

    • CIで型アノテーションがなければ落とす
    • commitlintで、lintで失敗したらコミットさせない、という手もあるかも
      • commitlintいいですよね

aspida.jsについて聞く (ふぃろまぎ)

  • aspida.js (アスピーダ JS)
  • 型定義を記述しておけば、静的に型付けされたAPIクライアントの実行コードを自動生成してくれるツールです。
  • 型定義ファイルだけでなく、実際に動作するtypescriptコードが生成されます。
  • スキーマファイルってどんな?
    • TypeScriptでinterfaceを書いていく。
  • 興味ある人で開発に参加してくれる方募集中だそうです。
    • ASTとかの知見が有る方は、特に歓迎したいそうです
  • スキーマ定義があれば、サーバサイドも自動生成できそう。
  • APIクライアントを自分で作ろうとすると、ラッパーを書く必要があるが、aspida.jsはそれをやってくれる
  • TypeScriptのinterfaceでIDLが書けたらいいなと思っていた。

Webstormとprettierの相性悪い? (やました リモート)

Webstormを使っているんですが、formatをsave時に使いたくsuinさんの記事をQiitaで見つけ設定しました。でも、prettierが激遅ぷんぷん丸で困ってます

...

TypeScript 3.7では何が変わっているのか、どんな機能が増えているのか (れおりん)

function getSafe<TObject, P0 extends keyof TObject, A1 extends GSArrEl<P0, TObject>, P2 extends keyof A1, P3 extends keyof A1[P2], A4 extends GSArrEl<P3, A1[P2]>>(obj: TObject, p0: P0, a1: number, p2: P2, p3: P3, a4: number): A4;
  • Nullish Coalescing ??
    • || と何がちがう?
      • ||0とか''でも、右辺が評価される
      • nullundefinedのときだけ。
  • Assertion Functions
    • type predicate の強い版?
function assertString(value: unknown): asserts value is string {
    if (typeof value !== 'string') {
        throw new Error('...')
    }
}

assertString(value) //=> exceptionが発生しうる

value.toUpperCase() // コンパイルが通る (valueがstringだとわかっているので)

関数型で書いているときのテストの仕方について (えあんぬ)

  • 手続き型と関数型はどうちがうの?
    • 手続き型は、どうやって処理するかを書いていく
    • 関数型は、より宣言的で、関数と関数を組み合わせて作っていくかんじ
      • 関数合成という考え方がある
      • 関数型プログラミングは、関数が第一級市民
    • 元々JavaScriptの作者が、関数型言語作りたかった人らしいから、JSは最初から関数型っぽい言語設計になってるっぽいですね
    • 参照透過性
      • 引数が同じだったら、何度やっても同じ結果が得られる
  • functionだけexportすることがあるが、functionが依存するfunctionをモックにするのかどうか
    • requireに噛んで依存先をモックにするライブラリがあるけど、
      • ちょっとツール依存な気がする
    • 外部にexportする目的には、interface or type を TS で書いて、実装はそれぞれexportしてテストはそれをimportしてテストでいいと思う
    • ports and adapters デザインパターン(ヘキサゴナルアーキテクチャ)とか、インターフェース分離とか、DIP(依存性逆流)とか使うと、外に見せるものを限定しつつ、関数を全部テストするみたいなこともしやすいですね
    • 引数に関数を持つものをテストするときは、jest.fn() でモック作って雑にテストすれば大体いいような気がする
  • 関数が依存する関数で、取り替えたい部分はカリー化するとか、引数で渡すとかするといいかも。
  • DBを参照したり副作用をもっている関数は、引数で渡すといいと思う
    • 副作用がなければくっついたままテストしてもいいと思う
  • 関数とクラスの使い分けに悩んでる
    • 依存物をもたせるならクラスでもいいのでは
  • カリー化って?
    • オブジェクト指向のビルダーパータンみたいに、段階的に関数を組み立てていける
const add = (v1: int) => (v2: int) => (v3: int) => v1 + v2 + v3

add(1)(2)(3) // => 6

const threePlus = add(1)(2)

threePlus(4) // => 7
threePlus(10) // => 13

カリー化とは違うけど、こういうファクトリーというか、段階的に組み立てる書き方は便利な気がしてる:

export interface HogePort {
  read(name: string) => Promise<string>
}

export const createHoge = (context: string): HogePort => {
  const read: HogePort['read'] = async (name) => {
    // ... なんかすごいしょり
    return `${name} ${context}`
  }

  return { read }
}

// カリー化とは違うけど、こういうファクトリーというか、段階的に組み立てる書き方は便利な気がしてる


const createCommandRunner = (conf: Config) => (command: Command) => command.run(conf)

// テスト時のコード
const command = new HogeCommand()
const test = createCommandRunner(testConf)
test.run(command)

// 本番環境のコード
const prod = createCommandRunner(prodConf)
prod.run(command)

クラスの設計について (かきうち)

メールを送るクラス
使う側からBodyを渡す
結果を受け取りたい

・・・

メールとメールを送るクラスを分けるといいかも。

const email = { subject: '...', body: '...' }
emailSender.send(email)

中途半端なメールを作るなら、それこそBuilderパターンとか、カリー化がいいかも。

const createMail = (subject: string) =>
                   (sender: string) =>
                   (body: string) =>
                   (receiver: string) => new Mail(subject, receiver, sender, body)

const sendTo = createMail('hoge')('example@gmail.com')('fuga')

const mailList = users.map(user => sendTo(user.mail))
interface Mail {
  subject: string
  sender: string
  // ...
}

export function createMailSender(mail: Partial<Mail>) {
  // 全部そろってたら、完成版MailSenderを返す
  // そろってなかったら、Builderを返す
  // とか……
  // - conditional typeとか使えたら夢が広がりそう
}

TypeScriptのエディタはVS CodeかIntelliJか (れおりん)

何がいいのか、どういう違いがあるのか?

  • VS Code使ってる勢: 3
  • WebStorm勢: 2
  • IntelliJ勢: 3

・・・

  • WebStormだとprettier重い
  • VSCode は無料で誰でも使えるから、環境統一に便利だと思ってたり
  • IntelliJ全員買えるくらいだといいんですけど、なかなかそうはいかなですもんね
  • あと、個人的な偏見かもしれないけど、設定を全くしてない状態では、IntelliJ よりも、VSCode が使いやすい気がする
  • VS Codeは起動が速いので、TSしか触らないときはVS Code
  • VS Codeは Live Shareのプラグインが良く出来てて、ペアプロするならこれになっちゃいました
  • JavaとかScalaとかやってるチームや人は、慣れてるIntelliJ でいいような気もする

参加してよかったこと(参加者の感想)

  • クラスや関数をどう作るかについての議論が楽しかった + 自分の感覚を言語化することができて良かったです
  • aspida.js の存在を知れたこと
  • カリー化の説明聞けたこと
  • カリー化を知らなかった。便利良さそうだから使ってみよう!!
  • プログラム好きな人が集まってる雰囲気を感じられたこと
  • 1900ファイルあるJavaScriptのプロジェクトにTypeScriptを入れる話は生々しくて面白かった

YYTypeScriptは毎週やってます

YYTypeScriptについてワイワイ話したい方は、YYTypeScriptのイベント情報をチェックしてみて下さい。

以上、YYTypeScriptのレポートでした。次回もワイワイやっていきたいと思います! では、また来週!

23
20
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
23
20