Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Template Literal Typesであそぶ

Template Literal Typesであそぶ

Template Literal Typesはinferを組みあわせると色々遊べるのです。
Fukuoka.ts #3 の発表資料です。

参考資料
https://github.com/sindresorhus/type-fest

C0e40025e5098e025a249b0cda428434?s=128

m-yoshiro

August 23, 2021
Tweet

Transcript

  1. Template Literal Typesで あそぶ 松本 芳郎 / 株式会社マネーフォワード Fukuoka TS

    #3
  2. 自己紹介 松本芳郎 • 株式会社マネーフォワード 経費本部 • フロントエンドエンジニア • 前職ではデザイナーでした •

    Twitter @bennkyougirai
  3. 発表内容 Template Literal Types で遊ぶ!

  4. Template literal Typeとは

  5. Template literal Typeを利用してできること • JSのテンプレートリテラルと同じ書式で Literal Types を作成できる

  6. Template literal Typeを利用してできること • JSのテンプレートリテラルと同じ書式で Literal Types を作成できる • Literal

    Typesから一部の文字列を抽出したりできる • String.splitみたいな型も作れる Inferと組み合わせることで、
  7. (1) Literal Typesから番号だけ抽出する • TS Playground → sample // =>

    "39" type Result1 = IdNumber<'id-39'> type IdNumber<T extends string> = T extends `id-${infer U}` ? U extends `${number}` ? U : '' : ''
  8. (1) Literal Typesから番号だけ抽出する • TS Playground → sample // =>

    "39" type Result1 = IdNumber<'id-39'> type IdNumber<T extends string> = T extends `id-${infer U}` ? U extends `${number}` ? U : '' : '' ① Literal Typesのなかでinferを使う ② U はnumberであることを期待する
  9. (2) Literal Typesを分割してArrayを作る • TS Playground → sample type Split<S

    extends string> = S extends `${infer Head}${infer Tail}` ? [Head, ...Split<Tail>] : S extends "" ? [] : [S]; // => ['H', 'e', 'l', 'l', 'o'] type Result = Split<'Hello'>
  10. (2) Literal Typesを分割してArrayを作る • TS Playground → sample type Split<S

    extends string> = S extends `${infer Head}${infer Tail}` ? [Head, ...Split<Tail>] : S extends "" ? [] : [S]; // => ['H', 'e', 'l', 'l', 'o'] type Result = Split<'Hello'> ① 文字を分割するために inferを2つ使う ② 再帰させて文字を 全て走査する
  11. おまけ: Splitを使って文字数をカウント • TS Playground → sample type ArrayLength<Arr extends

    any[]> = Arr['length'] type StrLength<T extends string> = ArrayLength<Split<T>> // => 5 type Result2 = StrLength<'Hello'>
  12. (3) Camelcase → Snakecase // => my-friend-forever type Result =

    CamelToSnake<'myFriendForever'>; • TS Playground → sample
  13. (3) Camelcase → Snakecase • TS Playground → sample //

    1. 隣あう2文字を使ってCamelCaseかどうか判定する type IsCamelCase<First extends string, Second extends string> = Second extends "" ? false : First extends Lowercase<First> ? Second extends Capitalize<Second> ? true : false : false;
  14. (3) Camelcase → Snakecase // 2. IsCamelCaseを利用してハイフンを挿入していく type CamelToSnake<T extends

    string, Prev extends string = ''> = T extends `${infer Head}${infer Rest}` ? Rest extends string ? Rest extends "" ? `${Prev}${Head}` : IsCamelCase<Head, Rest> extends true ? CamelToSnake<Rest, `${Lowercase<Prev>}${Head}-`> : CamelToSnake<Rest, `${Lowercase<Prev>}${Head}`> : T : T
  15. ちなみに • LowercaseやCapitalizeなどはTypeScriptがビルトインで提供してる ◦ https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html#intrinsic-string-ma nipulation-types ◦

  16. コツ • inferとTemplate Literal Types を組み合わせて推量対象の構造を作る • Arrayとことで自由度がます • 再帰を使う

  17. 最後に注意点 • 再帰を多用するので、パフォーマンスに影響ある可能性が。 • (検証してません)

  18. 参考資料 • https://github.com/sindresorhus/type-fest

  19. ご静聴ありがとうございました。