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

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

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) 型からスキルへの昇華