以下の内容はhttps://nakaoka3.hatenablog.com/より取得しました。


小説で学ぶ、集合から理解するTypeScriptのリテラル型【初心者向け】

去年、TypeScriptの型についての小説を書いて、そのまま放置していた。せっかくなので、少し直して公開しておこうと思う。

プログラミング初心者、TypeScriptの初心者の読者を想定した内容になっている。


登場人物

  • 私:高校2年生の女子。プログラミングと数学が好き。
  • デルタ:高校1年生の男子。プログラミング初心者。

ある日の放課後、私が高校の図書館の自習室に入ると、デルタがノートパソコンを広げたまま、手を止めて画面を見ているのが目に入った。

「なにか困りごと?」

「先輩、ちょうどいいところに来ましたね。ちょっとTypeScriptのコードを書いていたらエラーが発生していて困ってたんです」

私はデルタのノートパソコンの画面を見た。

「型のエラーが出てるね」

デルタに指示を出し、コードを修正するとエラーは消えた。

「デルタってコンパイルエラーとか、型のことわかってる?」

「わかってますよ。文字列だったら stringとか、数だったら number とか、変数につけるヒントみたいなイメージですよね」

「他には?」私は否定せずに聞く。

「後は……真偽値のbooleanとか」

デルタは宙を見つめながらTypeScriptの型を思い出そうとしていた。

「まあ、具体例は他にも色々あるよ。string, number, boolean はプリミティブ型だけど、それ以外にも配列やオブジェクトもあるよね。ほかにはanyやneverとか」

「……そういえば! TypeScriptの型について、一つどうしても納得できないものがあって...…」

デルタはパソコンのエディタを開き、次のコードを書いた。

const s: "foo" = "foo";

「TypeScriptって、こういう書き方ができますよね? これって不思議じゃないですか。型を書くところに具体的な値が書けてしまうように見えるのが、納得できないんです」

「たしかに少し分かりづらいね。確認だけど、次の定数にはどんな値を代入することができる?」

const x : number = ???

「1とか、2とか」

「そうだね。3でもいいし、4でもいい。100でもいいし、-1000でもいい」

「数ならなんでもいいってことですね。最小値と最大値はありますけど」

「その通り。では次は?」

const isOk: boolean = ???

「trueかfalseですね」

「その通り。それ以外の値は入らない。型というのは、その値がある集合の要素であるということを保証するものなんだ」

「集合って、数学の集合ですか?」

「そう。数学の集合風に表記するとこのように書ける」

私はノートを取り出し、次のように書いた。

boolean = { true, false }

「2つしかないので、外延的に書くことができるね。numberの場合はそうはいかないので、内包的に書こう。厳密な範囲までは覚えていないから、こんな感じでどうだろうか」

number = { n | 最小値から最大値までの浮動小数点で表せる数 }

「先ほどデルタは型のことをヒントのようなイメージといったけど、集合のイメージのほうが正しい」

「なるほど。型が集合だとは考えたことがなかったです」

「では、リテラル型に話を戻そう。このリテラル型を集合論の記法で書けるだろうか」

type T = "foo"

私はデルタの前にノートとペンを差し出す。デルタはペンを手に取り、少しだけ考えてから手を動かした。

{ "foo" }

「こうでしょうか」

「その通り。このリテラル型は foo という文字列のみを許容する型だ。したがってただ一つの要素 "foo" を持つ集合とみなすことができるんだ」

「あ、そういうことなんですね。型のところに値が来るのが納得できなかったんですけど、そういう書き方なだけで集合なんですね」

リテラル型が集合だということがわかれば、Union型も理解しやすいだろう」

「Union型ってなんでしたっけ」

「Union型は集合の言葉でいうと、和集合のことだ」

「和集合って…」デルタはノートにペンを走らせ、和集合のベン図を書いた。「……このことですよね」

「そうだ。和集合が2つ以上の集合を合成してできた型であるように、Union型は2つ以上の型を合成してできた型だ。| で型を並べて書くことで Union型を定義できる。このUnion型がどういう意味か、説明できる?」

type Status = "success" | "loading" | "error"

「"success", "loading", "error" のいずれかってことですよね。あ、なるほどこれはリテラル型という要素が一つしかない集合の和集合を作っているんですね」

こうしてデルタはTypeScriptのリテラル型を理解することができ、その応用としてUnion型の記法についても理解することができた。

そして私はデルタにTypeScriptの型を説明しながら、プログラミングと数学の関係に美しさを感じていた。

(おわり)


見ての通り、数学ガールのパロディだ。数学ガールなら、この後ミルカさんが現れてより数学的な話をしてくれるのだろう。カリー=ハワード同型対応に続けるなど、より高度な内容に踏み込んでくれたら面白くなりそうだ。

AIでコーディングすることが当たり前となった今、TypeScriptの型について理解していなくてもTypeScriptのコードを書く事ができてしまう。しかし型について理解するとプログラミングについての理解がかなり深まるので、TypeScriptを触る人には理解してほしい。

大規模言語モデル講座2025を受講している

大規模言語モデル講座2025(東京大学松尾・岩澤研究室)を受講し始めた。同僚のこの分野に詳しいエンジニアからおすすめされ、ちょうどLLMを活用したアプリケーション開発に取り組んでいるので受講することに決めた。講義は基礎編・応用編の前後編に分かれていて、応用編から受講している。応用編の全8回のうち4回が終わったところで、折り返し地点に到達している。

weblab.t.u-tokyo.ac.jp

アーカイブ動画で少しずつ学べる

毎週2時間決まった時間に受講するのはハードルが高いかなと思っていた。しかし参加してみるとアーカイブ動画を自分の好きな時間に見ることができる。出席アンケートの提出や課題の提出期限があるが、講義から1週間後までなので、毎日少しずつやったり、週末にまとめてやることができる。そのためフルタイムで働いている自分のような人でも毎週受講できている。

基礎編の動画を見ることができる

基礎編の講義のアーカイブ動画も見ることができるので、応用編の動画に加えて、基礎編の動画も見ている。基礎編にはプロンプティング、事前学習、スケール則、ファインチューニング、強化学習などの内容が含まれていて、動画を見ると学びが多かった。

これまでキーワードとしか知らなかった概念の関係性が見え、頭のなかに地図ができた

これまでキーワードとしてしか知らなかったものが、大規模言語モデルの研究や開発の中でどういう立ち位置にあるものなのか分かったのが良かった。

例えばLoRAといえば画像生成AIに関係する概念かなとぼんやり思っていたものが、ファインチューニングのなかでもPEFT(パラメータ効率的なファインチューニング)であることがわかり、事後学習⊃ファインチューニング⊃PEFT⊃LoRAというような概念同士の関係性の理解が深まった。

世の中のLLMのニュースやLLMを活用したプロダクトについても、知識を得ることで少しずつ理解の解像度が高まっていくのが面白い。

すぐに応用できそうな知識も学べている

研究者向けの内容で、実務でWebサービスやモバイルアプリの開発をしている人間には向かないのではないかという心配があった。実際にはその心配は当てはまらず、講義の内容は包括的で、専門家以外でも理解できるように配慮して講義が用意されているのが伺えた。

アプリケーション開発に活用しやすいような内容も多く学べた。例えばプロンプティングにおけるfew-shot、many-shotやLLM-as-a-Judgeなどは、アプリケーションにLLMを組み込んでいるエンジニアなら知識を活用する機会はいくらでもありそうだった。

年末年始の休みがあるので、残りの講義動画を見たり演習で手を動かして学ぶ時間がありそうだ。来年もこの講座があるのかはわからないけど、AIに関心があるけど理解が足りないと感じているソフトウェアエンジニアにはおすすめの講座だ。

自分用の音声読み上げブラウザ拡張機能を作った

個人で契約している Claude Code やCodex を使えるのに使わないのはもったいないので、いろいろ作ってみている。

ブラウザの拡張機能でテキストを読み上げるものを入れているが、言語やモデルの切り替えがスムーズにできず使い勝手が悪かった。そこで使いやすい自分用の拡張機能を作ることにした

Google Text to Speech APIを使用して選択されたテキストの音声読み上げを行う拡張機能が完成した。

こうやって自分用のソフトウェアを作るのが、Claude CodeやCodexのようなコーディングAIのによって簡単にできるようになったのがいい。ブラウザの拡張機能は手軽に作れるので、自分用のソフトウェアを作るのにはちょうどいいと思う。

これまでChrome拡張機能を作ったことがなかったので、どういう構成のプロジェクトにしたらいいかとかは全く知識がなかった。 AIが作ったファイルを見て、こういうファイルが必要なんだという構成が知れて学びにもなった。

完成したものを実際に使っていくと、もうちょっとこうしたものができるな、こうした方がいいなというアイデアが湧いてきて、少しずつ機能が増えていった。

言語の選択を手動でやるのではなく選択された言語を検知して読み上げる機能を作りたいと思った。 言語の検出にはGemini APIを使用した。こういうのはLLMが得意なタスクだろう。既存のAPIキーにGeminiの権限を与えることで、導入済みのAPIキーをそのまま使えるというのも良かった。

さらに次はテキストを選択するのではなく記事を自動で検出して読み上げてほしいと思うようになった。 1から実装するのは大変なので Readability というライブラリを導入した。

ライブラリを導入することによってビルドする必要が出てきたので、ビルドできるようにした。GeminiのAPIを叩くのもこれまではAPIのエンドポイントを直接叩いていたが、これを機にGoogleSDKを使用することにした。

こうして一通りほしい機能がそろったものは完成した。 せっかくGeminiを導入したので、他の機能も付け加えることにした。 記事を短歌の形に要約したり、ラップのように韻を踏んだ形で要約する機能を追加することにした。

以下の画像のような要約を生成して読み上げる機能が完成した。韻を踏む機能のクオリティはまだ改善の余地がありそうだ。

韻を踏んで要約

短歌にして要約

この記事を韻を踏んで要約して読み上げ

AIは並行して働く

ほとんどの場合、人間は複数のタスクがあっても結局のところ一つずつタスクに取り組むしかない。眼の前のことを片付けて、次のことをする。それがこれまでのソフトウェア開発の仕事に対する認識だった。

一方でAIコーディングエージェントを使えば複数のタスクを並行して進められる。複数の独立した開発環境で別々のAIコーディングエージェントを働かせたらいい。並行して進められる作業はなるべく並行して進めたほうがより効率的だ。そのためには依存が多いタスクを優先的にこなして、独立した複数のタスクがある状態にするというような工夫が求められる。例えばAPIの設計を固めればフロントエンドとバックエンドの実装を同時に進められる。

最近は一人で作業をしていても、まるでチームでタスクを進めるときのように考えている。「このタスクをAIにやらせている間に、関係ない他のタスクもAIにやらせよう」というように。しかも並行してタスクを進められるAIエージェントの"頭数"は、大したことのないコストでいくらでも増やせる。AIにも当然コストはかかるけど、人を増やすコストと比べるととんでもなく安い。

とはいえ、タスクを割り振ったり、チェックする人間の目は簡単には増やせない。理屈の上ではいくらでも並列で進められるけど、現実的にはタスクを管理する人間がボトルネックになっている。AIに大部分の作業をやらせているにもかかわらず、今のところは暇になるどころか忙しくなっている。

でももしAIがタスクの割り振りや成果物のチェックまでできるようになったら……?

Cloud Codeのカスタムコマンドを使用して PR のタイトルと説明を更新できるようにした

PRを更新するカスタムスラッシュコマンド

Custom Commandという機能がある。あらかじめ作っておいた指示をコマンドで呼び出せる機能だ。

ghコマンドを使うと CLIでPRのタイトルと説明を更新できるので ~/.claude/commands/update-pr.md にPRのタイトルと説明を更新する指示を書いたmarkdownファイルを追加して、/update-pr で呼び出せるようにした。

---
allowed_tools: [Bash]
description: "現在のブランチのプルリクエストのタイトルと説明を、変更の差分に基づいて適切に更新します"
---

# プルリクエストの更新

現在のブランチに対応するプルリクエストを見つけて、以下の手順でタイトルと説明を更新してください:

1. **現在のブランチ確認**: `git branch --show-current` で現在のブランチを確認
2. **プルリクエスト確認**: `gh pr view` で現在のブランチのプルリクエストを確認(存在しない場合はエラーメッセージを表示)
3. **変更の差分確認**: `gh pr diff` で変更内容を確認
4. **既存のタイトル確認**: 既存のプルリクエストにタイトルが十分に内容を反映した内容に設定されている場合は、そのタイトルを変更しない
5. **タイトルと説明の生成**:
   - 既存のタイトルがないか適切でない場合: 差分の内容から適切な日本語のタイトルを生成
   - 説明: 差分の内容を分析し、変更内容の要約を日本語で作成(機能追加、バグ修正、リファクタリングなどを明記)
6. **プルリクエスト更新**: `gh pr edit --title "<title>" --body "<description>"` でプルリクエストを更新

**注意事項**:
- 説明は変更の内容を分かりやすく日本語で要約する
- コミットメッセージの履歴も参考にする
- プルリクエストが存在しない場合は、その旨を伝える
- リポジトリにPRのテンプレートがある場合はそのテンプレートを使用する

このカスタムコマンド自体、Claude に生成してもらったもので、あまり手を加えていないため、改善の余地はあると思う。

背景

AIを使ったコーディングでもこれまでの開発スタイルで重要だと思われていたことは、変わらずに重要だということが分かってきた。

なので適度な粒度でプリクエストを使って、レビューをしてマージをしていきたい。

AIを使うと大量のコードを書くことができる。その結果、プルリクエストの数も増える。タイトルや説明を書く作業も増える。

AIを使えば変更内容の概要などある程度のことはできるので、AIにやってもらうことにした。

まとめ

  • 繰り返し行うような作業はスラッシュコマンドにどんどん追加して便利にしていきたい。リファクタリングやテスト用のカスタムスラッシュコマンドがあると便利かもしれない。
  • このことを同僚に話したら似たようなスラッシュコマンドを作っていた。他の人が追加している便利なスラッシュコマンドも知りたい。

はじめての数理論理学 - 読んでる本

『はじめての数理論理学』という本を読み始めた。

図書館で数理論理学の書籍を探していくつか手に取ってみたけど、この本がとっつきやすそうだった。命題論理から始まり、証明法へ続き、後ろの方では意味論、健全性、完全性という言葉が並んでいるのも見えた。

こういうことについて大学などで学んでないから、本を読んで学んでいきたい。

関連する話で、最近発売された『ゼロから始める Lean 言語入門』という書籍も購入した。Leanは定理証明支援系であり、かつ関数型プログラミング言語でもあるものらしい。今すぐ読めるかわからないけど、関心があるうちに買っておいた。そのうち読みたい。

バイブコーディングの面白みのない学び

この1ヶ月くらい、生成AIのコーディングエージェントを活用したwebアプリケーションの開発をしてきたけど、AIを使うからどうこうという学びは少なかったかも。

むしろAI使わない時代の開発で重要だったものは、たいてい重要なままというのに気が付かされることのほうが多かった。

CIを整備してテストやビルドエラーやフォーマッターを自動で確認できるようにしたら便利、とか。リファクタリングして重複しているコードを減らしたら保守性があがる、とか。

こういうのをすべて飛ばして機能の実装を進めることは可能だけど、結局後で痛い目をみるので、ちゃんとやっておいたほうがいい。

当たり前すぎる。体重を減らすのには摂取カロリーを減らしましょう、とか運動と睡眠が健康にいいとかと同じくらい当たり前過ぎて面白みがない。

現在のAIが生成するコードの保守性が高くないというのがわかったから、そこを改善する指示を書いたり、定期的にリファクタリングするタスクをやらせるとかの工夫はあるといいかもしれない。




以上の内容はhttps://nakaoka3.hatenablog.com/より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14