ペロハム大学

ヤルゾー

プロを目指す人のためのTypeScript入門 読書メモ⑥ 第4章(3)

■ 思ったこと

今回特にむずいぞ、気をつけろ!!

■ 第4章 TypeScriptの関数(4.2~4.6.4)

そもそも関数自体に型がある

  • 関数型は(引数リスト) => 返り値の型、最初のほうにこんがらかったとこだ!今ならわかる
    • 引数内なら() => voidでいいのよ
    • 型なので、type文で別名だって付けられるぜ

型省略問題

  • 返り値
    • 型推論があるから省略できるけど、望んだとおりに解釈されるかはちょっと微妙
    • 正直型注釈ある方が分かりやすいし、書いた方がいい派
  • 引数
    • 原則省略できない!が!「逆方向の型推論」が働く場合は書かなくてOK・・なんて!?
    • 通常の型推論は、式から型を推論する
    • その逆なので、式の型が先にわかってれば推論できる…?
    • もっと分かりやすい例!関数型がtypeとかで先に宣言されていたら、式が先にわかってるね?だからその型を基に代入する式は引数が省略できる…宣言したときに型注釈されてるから!!
    • 分かりきったことを何度も書くぐらいだったら省略を許してくれるのだ
    • もいっこ例があるよ、関数引数の時(コールバック関数とかね)も省略してOK。配列の型から推論できる

コールシグネチャという構文がある

  • オブジェクト型の中で使用できる構文、関数型の表現に仕えるものとな?
  • 構文は(引数リスト): 返り値の型、なんかよく見る感じだけど・・?
  • この書き方すれば関数とみなされる、メソッド記法と似てるな
  • なんか、一つのオブジェクト型に対し、プロパティと関数、両方の性質を併せ持つ❤みたいなことができるらしい
  • あんま使わなそうだ・・!

再び登場!関数型の部分型

  • 型のを別の型で代用できるアレですね?・・やばい!ここあんま理解できてないぞ

まずは復習!部分型

  • 2つの型の互換性を表す概念
  • 「型Sが型Tの部分型である」は「S型の値がT型の値」に同じ!
  • 型Sと型Tのプロパティが一個でも一致していれば、部分型関係になる。こいつらは今、プロパティの包括関係にあるのだ
  • 型Tが持つプロパティがすべて型Sにある、かつ!かぶってる部分の型が同じであればOK
  • こうなれば、型Tの代わりに型Sを使ってもいいんだぜ
  • 覚え方は「少ない方ベースに大きいの入れるのはいいけど、大きい方ベースに小さい方は無理!」プロパティが足りないからね
type FooBar = {
  foo: string;
};

type FooBarBaz = {
  foo: string;
  bar: number;
  baz: boolean;
};

const fooBarObj: FooBar = {
  foo: "hi",
};

const fooBarBazObj: FooBarBaz = {
  foo: "hi",
  bar: 1,
  baz: false,
};

// これはいいけど
const okObj: FooBar = fooBarBazObj;

// これはエラーなるよ
// 型 'FooBar' には 型 'FooBarBaz' からの次のプロパティがありません: bar, bazts(2739)
const errObj: FooBarBaz = fooBarObj;
  • ちなみにokObjの中には本来なさそーなbaz: falseもちゃんと入る
  • 型によってデータが削られたりはないってことさ。第1章でやった通り、TypeScripyの型はあくまでエラーチェック用なのだ

再び登場!関数型の部分型(TAKE2)

  • 関数型だって部分型関係になることがある
  • 返り値の型による部分型
    • 返り値の型が部分型関係であればOK
    • しかし、引数が一致していないとダメだぞ!
    • void型同士は引数一致してればすぐ条件満たす
  • 引数の型による部分型
    • 引数の型違っても部分型関係になるよ
    • おなじく、引数の型が部分型関係であればOK
    • おっきい方のオブジェクトに入ったデータををちっさい方のオブジェクトで受け取って必要な部分を使える
  • 引数の数による部分型
    • もう何となくわかった!引数多い関数のオブジェクトに引数少ない関数入れられるんだろ!
    • 余った引数は捨てられる

ジェネリクス関数

  • 型引数(プロパティの型ね)を持つ関数
  • 関数には<型引数リスト>で受け取る予定のオリジナル型名を設定する、こんな感じで関数<オリジナル型引数>(引数): 戻り値
    • 引数、戻り値にはオリジナル型名を使用できる
  • 呼び出す側でオリジナル型引数に具体的な型を設定してあげればよい、stringとかnumberとか
  • つまり、呼び出すたびに異なる型で受け取れる!返せる!
  • 処理に使いたい型は違えど、処理は同じ時にいいかも
  • 因みに、呼び出す側の型引数は省略できる、型推論があるからわざわざ書かなくてもいいとな!?

力試し

  • 関数編
    • FizzBuzzを関数で作り直してみようの巻
    • 回答みると、戻り値に変数使わずに早期リターンしていた。そうだ、早期リターン、また忘れていた・・!
    • 細かく処理を分けよう!
    • letは前も言った通り、中身が変わるので追うのが大変・・だから、影響範囲を狭めることでカバーするのだ。そういう意味でも処理を分けるのは大事!
  • callback編
    • 「T型で受け取り、U型で返す」を読み飛ばして混乱した!ジェネリクスはだいぶ関数の自由度が上がる
    • 今回だと、引数は毎回number[]だけど戻す型は呼び出すごとに変えたり

■ 感想

4章長かった!!かつてまったく分からなかった部分型が多少理解できたが、まだ使いどころが微妙!共変反変の話はまだ理解できる段階になく、すっ飛ばした!!