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

TypeScriptの「型」をAIのスキルに 昇華させてみた件について

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Kazuaki Higa Kazuaki Higa
May 22, 2026
520

TypeScriptの「型」をAIのスキルに 昇華させてみた件について

Avatar for Kazuaki Higa

Kazuaki Higa

May 22, 2026

Transcript

  1. X:@higakazuaki9 • 比嘉 一晃(ひが かずあき) • 沖縄県出身 • 株式会社iimon エンジニア ◦

    不動産DXのツールを提供 https://iimon.co.jp/ • 担当業務の技術スタック ◦ vanilla-tsやReact、Django、 AWS、Google Cloud (Firebase)...etc • 経験 ◦ Angular、React、Vue.js、Spring Boot、Django、Fast API、Ruby on Rails…etc • 性格 ◦ 人懐っこい、面倒くさがり、ねこと ビール好き プロフィール
  2. AI回答 解:TypeScript の型体系についてですね。 マスター、以下が知見の全容です。 基本型 number, string, boolean, bigint, symbol

    null, undefined, void, never, any, unknown 複合型 ユニオン型:Type1 | Type2 インターセクション型:Type1 & Type2 リテラル型:"value", 42, true AIの型知識チェック
  3. AIの型知識チェック AI回答(続き) Utility Types Partial<T>, Required<T>, Readonly<T> Record<K, T>, Pick<T,

    K>, Omit<T, K> Exclude<T, U>, Extract<T, U> ReturnType<T>, Parameters<T>, ThisParameterType<T> InstanceType<T>, NonNullable<T> その他 keyof T, typeof 演算子 インデックスシグネチャ:[key: Type]: Value as const, satisfies、オーバーロード、infer キーワード is 型ガード
  4. AI回答 告。知識ベースから回答いたします、マスター。 Awaited Types TypeScript 4.5で追加されたユーティリティ型です。非同期操作 (Promise)の解決値の型を抽出します。ネストされたPromiseにも対応し ており、例えば Awaited<Promise<Promise<string>>> は

    string となり ます。 Template Literal Types TypeScript 4.4で導入された機能です。バッククォート記号を用いて型レベ ルで文字列を操作できます。例として type Greeting = Hello, ${string}!`` のように複数の型を組み合わせた文字列型を作成できます。 AIの型知識チェック
  5. AI回答(続き) 型演算と集合演算 A | B(ユニオン型) ≡ 和集合(A ∪ B) A

    & B(インターセクション型) ≡ 交集合(A ∩ B) never ≡ 空集合(∅) unknown ≡ 全集合 部分型関係 A extends B ≡ A ⊆ B(Aはの部分集合) 例:5 extends number ≡ {5} ⊆ {すべての数値} 部分型は代入可能(リスコフの置換原則) AIの型知識チェック
  6. AI回答(続き) 型の互換性 共変性(Covariance):部分集合なら代入可 反変性(Contravariance):関数パラメータは逆向き 不変性(Invariance):厳密な一致のみ 具体例 type A = number;

    type B = 5 | 10; // Bはより小さい集合 type C = string | number; // Cはより大きい集合 // B extends A は真({5,10} ⊆ {すべての数値}) // A extends C は真({すべての数値} ⊆ {string|number}) AIの型知識チェック
  7. 例えばstringとリテラル ・string function setAlignment(alignment: string): void { // alignment は何でもあり?色々パターンを考慮しないといけない・・・

    } ・リテラル function setAlignment(alignment: "left" | "right" | "center"): void { // alignment は3つの値のみ、処理内容を絞れて予期せぬ処理も予防でき る // 機能拡張もリテラルで管理すれば影響範囲がわかりやすい } 型の表現力とAIの解釈
  8. 例えばstringとリテラル リテラルで絞れば引数を間違えても型エラーで気付ける setAlignment("top") // Argument of type '"top"' is not

    assignable to parameter of type '"left" | "right" | "center"'. AIは特にエラーの有無で判断する傾向がある (エラーが出ていたら必死に直そうとする) →型エラーを適切に出す書き方はAIが処理を正しく理解する手助けとなる 型の表現力とAIの解釈
  9. anyはなんとかしたい ・any const anyValue: any = getValue(); console.log(anyValue.toUpperCase()); // 実行時エラーの可能性あり

    ・unknown + 型ガード const unknownValue: unknown = getValue(); if (typeof unknownValue === "string") { // 型ガードでより安全に処理を書ける console.log(unknownValue.toUpperCase()); } 型の表現力とAIの解釈
  10. anyはなんとかしたい ・any const getPropertyAny = <T>(obj: T, key: string): any

    => {}; // 意図しない処理でもanyだと気づかない・・・ ・制約付きジェネリクス const getProperty = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key]; // 制約(Tのプロパティのみ取得)をつけて安全かつ明確に実装できる 型の表現力とAIの解釈
  11. 型アサーションも使い方によっては危険 // 型ガードなしのアサーションはanyくらい危険・・・ const length = (value as string).length; //

    実行時エラーの可能性あり // たとえば型ガードで安全性を確保する if (typeof value === "string") { const length = value.length; } // satisfies で型検証+値保持、もっと安全かつ意図通りに書ける const config = { timeout: "5000", } satisfies { timeout: string }; config.timeout.length 型の表現力とAIの解釈
  12. 型の表現力とAIの解釈 Discriminated Union(判別可能なユニオン) とneverで完全性検証 type Status = | { status:

    "success"; data: unknown } | { status: "error"; error: string }; const statusCheck = (status: Status) => { switch (status.status) { // 各ケースの処理を網羅的に実装 case "success": return status.data; // 判別可能なので、型推論が効く case "error": return status.error; default: const _: never = status; // neverによってケース漏れを検出できる return _; }}; // 構造体と処理をワンセットで管理、AIによる機能拡張もスムーズ
  13. Mapped Types による DRYな書き方 // 型のバリデーションを手動で書こうとすると漏れる可能性あり・・・ interface UserValidators { idValidator:

    (v: number) => boolean; nameValidator: (v: string) => boolean; emailValidator: (v: string) => boolean; } // マップ型で自動生成、漏れなく確実に検証できる type Validators<T> = { [K in keyof T]: (v: T[K]) => boolean; }; type UserValidators = Validators<User>; Userに対するバリデーションという情報もAIにダイレクトに伝わる 型の表現力とAIの解釈
  14. ROROパターン(Receive an Object, Return an Object) // 単純に引数を受け取る関数だと順番なども考慮しないといけない function findUser(name?:

    string, age?: number, country?: string) { } // ROROパターン interface UserSearchParams { name?: string; age?: number; country?: string; // 型を拡張するだけ、順番など余分な考慮がなくなり事故も防げる tags?: string[]; // 追加 } function findUser(params: UserSearchParams): User { } 引数の追加などがより拡張がしやすい設計となっているため、Objectが複 雑になればなるほど恩恵は大きい(AIも人も誤解しにくくなる) 型の表現力とAIの解釈
  15. narrowingによる型の絞り込み // 二つの型のユニオンをつくったときに type Dog = {name: "wanwan"; run: string;};

    type Cat = {name: "nya-nya-"; meow: string;}; type Animal = Dog | Cat; const animalTest = (animal: Animal) => { if (animal.name === "wanwan") { return animal.run; // ここはDog } return animal.meow; // ここはCatと型推論が効く }; 複雑なオブジェクトほどnarrowingによる絞り込みの恩恵は大きい (一つずつの処理を明確かつシンプルにできて、AIも人も理解しやすい) 型の表現力とAIの解釈
  16. narrowingの注意点 typeofなどではnarrowingできなかったりするので注意 const doc = {name: "wanwan", run: "run"}; const

    cat = {name: "nya-nya-", meow: "meow"}; type Animal = typeof doc | typeof cat; →type Animal = {name: string; run: string;}         | {name: string; meow: string;} constアサーションでリテラルにするなり、narrowingできるようにする const doc = {name: "wanwan", run: "run"} as const; const cat = {name: "nya-nya-", meow: "meow"} as const; type Animal2 = typeof doc | typeof cat; →type Animal2 = {readonly name: "wanwan"; readonly run: "run";}       | {readonly name: "nya-nya-"; readonly meow: "meow";} 型の表現力とAIの解釈
  17. 型の表現力とAIの解釈 ブランド型で構造体を区別する type Cat = {id: number; name: string;}; type

    User = {id: number; name: string;}; const cat: Cat = {id: 1, name: "nya-nya-"}; const adminUser: User = cat; // 意図しない値の代入も通ってしまう (adminユーザーがにゃーにゃーに・・・) TypeScriptは構造的型付けを採用しているので ブランド型で事故が起きないように管理するのも一つの手段 const cat: Cat = {id: 1, name: "nya-nya-", __brand: "cat"}; const adminUser: User = cat; // Type 'Cat' is not assignable to type 'User'. ブランドプロパティで情報量も増えるので、 うまく使えばAIへの仕様や処理内容の理解の向上に繋がる
  18. 実験 パターンA ## 1. 仕様の考察結果(一部抜粋) ### ネコシミュレーションシステムの基本構造 - ネコシミュレーション/た⚪ごっち風ゲーム -

    マルチテナント対応 - リアルタイム状態更新 ### 1.1 個体識別とメタデータ - ブランド型識別子(CatId, FoodId, LocationId) - 基本情報管理 - 品種限定(4種:ペルシャ、シャム、メインクーン、ラグドール) ・・・etc 型の表現力とAIの解釈
  19. 実験 パターンB ## 1. 仕様の考察結果(一部抜粋) ### 猫シミュレーション/管理システム - 複数ネコの動的追跡 -

    時間経過に伴う属性値の変化 ### 1.1 猫個体管理 - 基本情報(ID、名前、品種、年齢、毛色) - adoptionDate(読み取り専用) ・・・etc 型の表現力とAIの解釈
  20. 実験 パターンA ## 2. 型の拡張で実装できそうな追加機能(一部抜粋) ### 2.1 相互作用・社会化機能 - SocialInteraction型(playing-together,

    grooming-partner, territorial-conflict) - CatSocialGraph型(friendships, tensions, familyRelations) ### 2.2 時間軸管理・スケジューリング - TimeWindow型 - ActivitySchedule型 - CircadianRhythm型(品種別スケジュール、timezone対応) ・・・etc 型の表現力とAIの解釈
  21. 実験 パターンB ## 2. 型の拡張で実装できそうな追加機能(一部抜粋) ### Level 1: 基本的な拡張 ####

    A. 健康管理機能の強化 - 病歴・ワクチン・ストレス管理 #### B. 社会的相互作用の追加 - 複数猫飼育時の相互作用追跡 ・・・etc 型の表現力とAIの解釈
  22. 実験 パターンA ## 3. 型定義から見えるリスク(一部抜粋) ### 3.1 状態一貫性リスク(影響度:高) - 属性値の現在値・履歴の非同期化

    - 復帰機能の破損 - 分析データの信憑性喪失 ### 3.2 活動状態遷移リスク(影響度:中) - 状態遷移ルールの未定義 - 物理的に不可能な遷移の許可 - シミュレーション妥当性の低下 ・・・etc 型の表現力とAIの解釈
  23. 実験 パターンB ## 3. 型定義から見えるリスク(一部抜粋) ### カテゴリ1: 型安全性の欠落(影響度:高) #### 1-1

    Activity.type の不整合 - 文字列型で制約なし - 無効な値がランタイムに侵入可能 #### 1-2 Command.action の曖昧性 - コンパイル時検証不可 - 無効なコマンド実行可能 ・・・etc 型の表現力とAIの解釈
  24. 全体的なフロー 1. Catクラス(パターンA)の実装内容をCompiler APIでAST解析 クラス宣言を検出、publicメソッドを抽出、パラメータの型を取得 戻り値の型を取得、JSDocコメントを取得 2. スキル定義(JSON Schema) 18個のメソッド→18個のスキル

    name(メソッド名)、description(JSDoc) input schema(パラメータの型)、output schema(戻り値の型) 3. コード生成 バリデーション、テスト、CLI、APIドキュメント、MCP Tool 型からスキルへの昇華
  25. 1. Catクラスの実装内容をCompiler APIでAST解析 ※ AST 走査による抽出処理を一部抜粋 node.members.forEach((member) => { ・・・略・・・

     // name(メソッド名)抽出 const methodName = member.name.text; // input schema (パラメータ)抽出 const parameters: ParameterInfo[] = member.parameters.map((param) => {let typeString = "object"; if (param.type) {typeString = param.type.getText();} const required = !param.questionToken && !param.initializer; const paramName = param.name ? param.name.getText() : "param"; return {name: paramName, type: typeString, required};}); 型からスキルへの昇華
  26. 1. Catクラスの実装内容をCompiler APIでAST解析 ※ AST 走査による抽出処理を一部抜粋 // output schema(戻り値)抽出 ・・・略・・・

    let returnType = "void"; if (member.type) {returnType = member.type.getText();} // description(JSDoc)抽出 const jsdocComments = ts.getJSDocCommentsAndTags(member); const jsdocComment = jsdocComments.length > 0 ? jsdocComments[0] : undefined; const description = jsdocComment ? jsdocComment.getText().replace(/\/\*\*[\s\*]*|[\s\*]*\*\//g, "").trim() : `Executes ${methodName} method`; 型からスキルへの昇華
  27. 2. スキル定義(JSON Schema) ※ スキル定義生成 一部抜粋 // Union 型を enum

    に変換 if (typeString.includes("|")) { const values = typeString.split("|").map((v) => v.trim()); // 文字列リテラル if (values.every((v) => v.startsWith('"') && v.endsWith('"'))) { return {type: "string", enum: values.map((v) => v.replace(/"/g, ""))};} // 数値リテラル if (values.every((v) => !isNaN(Number(v)))) {return { type: "number", enum: values.map((v) => Number(v))}; }} 型からスキルへの昇華
  28. 2. スキル定義(JSON Schema) ※ スキル定義生成 一部抜粋 // --- Branded Types

    検出 --- if (isBrandedType(type, checker)) { const brandName = extractBrandName(type, checker); return { type: "string", description: `Branded type: ${brandName}`, format: brandName, }; } 型からスキルへの昇華
  29. 2. スキル定義(JSON Schema) ※ スキル定義生成 一部抜粋 // プリミティブ型 if (typeString

    === "string") return { type: "string" }; if (typeString === "number") return { type: "number" }; if (typeString === "boolean") return { type: "boolean" }; if (typeString === "void") return { type: "null" }; if (typeString.includes("[]")) { return { type: "array", description: typeString }; } // デフォルト return { type: "object", description: typeString }; 型からスキルへの昇華
  30. 2. スキル定義(JSON Schema) ※ スキル定義生成 一部抜粋 const properties: { [key:

    string]: unknown } = {}; const required: string[] = []; // methodはAST 走査で抽出したメソッドの情報 method.parameters.forEach((param) => { const schema = typeToJsonSchema(param.type); properties[param.name] = { type: schema.type, description: `Parameter: ${param.name}`, ...(schema.enum && { enum: schema.enum }), }; if (param.required) {required.push(param.name);} }); 型からスキルへの昇華
  31. 2. スキル定義(JSON Schema) ※ スキル定義生成 一部抜粋 // 最終的なスキル定義の返却 return {

    name: method.name, description: method.description, inputSchema: {type: "object", properties, ...(required.length > 0 && { required }),}, outputSchema: method.returnSchema, }; バリデーション、テスト、CLI、APIドキュメント、MCP Tool のスキル定義が完成! 型からスキルへの昇華
  32. 3. コード生成 ※ バリデーションの出力例 一部抜粋 function generateValidation(skills: SkillDefinition[]): string {

    ・・・略・・・ // 必須チェック required.forEach((key) => { lines.push( `if (input.${key} === undefined || input.${key} === null) {` ); lines.push(` errors.push("${key} is required");`); lines.push(` }`); }); 型からスキルへの昇華
  33. 3. コード生成 ※ バリデーションの出力例 一部抜粋 // 型チェック params.forEach(([key, prop]) =>

    { lines.push(``); lines.push(` if (input.${key} !== undefined) {`); if (prop.type === "string") { lines.push(` if (typeof input.${key} !== "string") {`); lines.push(` errors.push("${key} must be a string");`); lines.push(` }`); } else if (prop.type === "number") { lines.push(` if (typeof input.${key} !== "number") {`); lines.push(` errors.push("${key} must be a number");`); lines.push(` }`);・・・ 型からスキルへの昇華
  34. 3. コード生成 ※ 各種コードを生成(18メソッド分) // 1. バリデーション生成 const validationCode =

    generateValidation(skills); const validationFile = path.join(outputDir, "generated_validation.ts"); fs.writeFileSync(validationFile, validationCode); console.log(`✅ [1/5] バリデーション: ${validationFile}`); // 2. テストコード生成 const testCode = generateTests(skills); const testFile = path.join(outputDir, "generated_cat.test.ts"); fs.writeFileSync(testFile, testCode); console.log(`✅ [2/5] テストケース: ${testFile}`); 型からスキルへの昇華
  35. 3. コード生成 ※ 各種コードを生成(18メソッド分) // 3. CLI ツール生成 const cliCode

    = generateCLI(skills); const cliFile = path.join(outputDir, "generated_cat_cli.ts"); fs.writeFileSync(cliFile, cliCode); console.log(`✅ [3/5] CLI ツール: ${cliFile}`); // 4. API ドキュメント生成 const apiDocs = generateAPIDocs(skills); const apiDocsFile = path.join(outputDir, "generated_api_docs.md"); fs.writeFileSync(apiDocsFile, apiDocs); console.log(`✅ [4/5] API ドキュメント: ${apiDocsFile}`); 型からスキルへの昇華
  36. 3. コード生成 ※ 各種コードを生成(18メソッド分) // 5. MCP Tool サーバー生成 const

    mcpServer = generateMCPServer(skills); const mcpFile = path.join(outputDir, "generated_mcp_tools.ts"); fs.writeFileSync(mcpFile, mcpServer); console.log(`✅ [5/5] MCP Tool: ${mcpFile}`); 型からスキルへの昇華
  37. MCP Tool サーバー実行例(getStatus) // CatクラスのgetStatusメソッドを例にみてみる type CatPublicInfo = Pick<CatInfo, "id"

    | "name" | "breed" | "age">; /** satisfies を使った結果返却 */ public getStatus(): CatPublicInfo { return { id: this.info.id, name: this.info.name, breed: this.info.breed, age: this.info.age, } satisfies CatPublicInfo; } 型からスキルへの昇華
  38. ※ mcp inspectorで確認 getStatusはsatisfiesを 利用しているので、 CatPublicInfoに変更が あった場合はAIで検知& 修正、MCPでチェックと 一通りの自動化が可能 そのほかテストやバリ

    デーションチェック、ド キュメント化、CLI化も 自動化できる MCP Tool サーバー実行例(getStatus) 型からスキルへの昇華