TSLab【第5回 TypeScript勉強会】関数型の制御!

TSLab
  • URLをコピーしました!

こんにちは!RYOTAです!

当記事をご覧いただきありがとうございます!

当記事はTSLab勉強会(定例会)のレポート記事になります!

目次

はじめに

私が運営しているTSLabの第5回定例会の実施ログとなります。

今回のテーマは関数の型定義!

第4回の内容は下記の記事にまとめていますので気になる方はあわせてご覧くださいませ。

あわせて読みたい
TSLab【第4回 TypeScript勉強会】ついに現れたGenerics!! こんにちは!RYOTAです! 当記事をご覧いただきありがとうございます! 当記事はTSLab勉強会(定例会)のレポート記事になります! 【はじめに】 私が運営しているTSLabの...

ディスカッション内容

関数のオーバーロード

https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads

関数宣言時に複数の引数パターンを多重定義しておくことが出来るらしい…こんなの出来るの知らなかった…

公式のサンプルにあるDate関数の指定はわかりやすいですが、実際の開発現場で使うイメージが湧きませんね。

ただし、一応使う際には注意が必要とのこと!

注意するポイント

  • オーバーロードさせる際はそれぞれ型互換性が無いとダメ
  • 可能な限りオーバーロードではなくユニオン型のパラメータを使う

このオーバーロードですが、ディスカッションした結果「これ実務で使わなくない?」と結論に至りました。実務でもあまり見ないですし、どういったシーンで使うんでしょうね。

分でライブラリとかを開発する時に必要になってくるのかな…?

可変長引数

下記のように引数部分をスプレッド構文にすることで、可変長の引数にすることが出来るようです。

const doubleNumbers = (...test: number[]) => {
  return test.map((v) => v * 2)
}

console.log(doubleNumbers(1, 2, 3, 4, 5, 6))
// -> [ 2, 4, 6, 8, 10, 12 ]

複数引数を渡してあげることで配列として解釈してくれるようですね。

注意するポイント

  • 型注釈はArray<T>または、T[]でなくてはならない

(これもあまり使うことない…?)

constアサーション

例えば下記のように引数を二つ受け取ってそれぞれの積を求める関数があったとします。

スプレット構文で配列を展開する場合、配列の要素数が確定していないので、関数に渡すとエラーを返します。

const multiply = (n1: number, n2: number) => {
  return n1 * n2
}

const testNumbers = [3, 5]

console.log(multiply(...testNumbers))
// エラー: spread 引数には、組の種類を指定するか、rest パラメーターに渡す必要があります。ts(2556)

この時に使えるのが as const 構文です。

変数をreadonlyにするだけでなく、要素数が二つであることが固定されるので、無事に関数に渡すことが出来るようになります。

const multiply = (n1: number, n2: number) => {
  return n1 * n2
}

// as const で readonlyにする
const testArray = [3, 5] as const

console.log(multiply(...testArray))
// ホバーすると、const testArray: readonly [3, 5] となっていることが分かる

(余談)readonlyになるので再代入はもちろん出来ませんね。

const testArray1 = [3, 5]
testArray1[1] = 10
// OK

const testArray2 = [3, 5] as const
testArray2[1] = 10
// エラー: 読み取り専用プロパティであるため、'1' に代入することはできません。ts(2540)

propsの展開

今回のテーマとはちょっと逸れた内容になりますが「マジか!これ早く知りたかったわ!」となった内容がこちら。

例えばReactでidとcontentというpropsを受け取るコンポーネントがあったとします。

type childProps = {
  id: number
  content: string
}

const ChildComponent = (props: childProps) => {
  return (
    <>
      <div>{props.id}</div>
      <div>{props.content}</div>
    </>
  )
}

この場合props.idやprops.contentでアクセスするのが面倒なので、事前に分割代入をしておくことでシンプルに取り扱うことができます。

const ChildComponent = (props: childProps) => {
  // 分割代入
  const { id, content } = props

  return (
    <>
      {/* props. が必要なくなる */}
      <div>{id}</div>
      <div>{content}</div>
    </>
  )
}

ただ、今回教えて貰ったのが分割代入すら必要なく、propsを受け取る段階で展開できるとのこと!……マジか!!

// 受け取る段階で展開して割り当て
const ChildComponent = ({ id, content }: childProps) => {
  return (
    <>
      <div>{id}</div>
      <div>{content}</div>
    </>
  )
}

この記述の仕方の方がいいやん!次からこの形で書いていきます!

void型の返り値

今回一番驚いたのがこの項目。。。

voidって値が返らない型なんですが、このように値が返って来ちゃうっぽい。(マジか。おいマジか。)

type voidFunc = () => void

const returnVoidFunc: voidFunc = () => {
  return '残念。値が返るぞw'
}

console.log(returnVoidFunc())
// -> 残念。値が返るぞw

一応、関数に直接注釈を付けてあげると大丈夫っぽいですね。

const returnVoidFunc = (): void => {
  return '残念。値が返るぞw'
  // エラー: 型 'string' を型 'void' に割り当てることはできません。ts(2322)
}

何でこんな仕様になってるのか分かりませんが、これ知ってないと危ないですね、、、

さいごに

いや〜。だいぶ内容が難しくなってきましたね。笑

前回・今回の内容は普段使わない(?)内容が多かったのでより一層難しく感じましたね!

ユースケースと一緒じゃないとイメージがし難くなってきたので、勉強会の内容も少し工夫しないとなと感じました!

内容が深くなってくるにつれ、学びが多くて楽しくなってきた!

引き続きガンガン学習していきましょう!

以上!最後までご覧くださりありがとうございました!

一緒にTypeScriptを学びたい方はぜひ下記のアカウントからご連絡ください!

TSLab

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次