## 経緯 [[🦉Carnelian]]で設定ファイルを[[Neovim]]っぽくしてみたかった。そのために[[JSON Schema]]で設定を補完できるようにしようという試み。 [[bunx]]を使うので依存関係には追加しない。 ## 環境 | 対象 | バージョン | | -------------------------------- | ---------- | | [[macOS]] | 15.6.1 | | [[ts-json-schema-generator]] | 2.4.0 | | [[Neovim]] | 0.11.3 | | [[vscode-langservers-extracted]] | 4.10.0 | ## シンプルな例で試す ### つくってみる `index.ts` ```ts /** * 動物 */ export interface Animal { /** 名前 */ name: string; /** 年齢 */ age: number; /** 種類 */ species: string[]; } ``` 実行する。 ```console bunx ts-json-schema-generator > config.schema.json ``` 結果。 ```json { "$ref": "#/definitions/Animal", "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "Animal": { "additionalProperties": false, "description": "動物", "properties": { "age": { "description": "年齢", "type": "number" }, "name": { "description": "名前", "type": "string" }, "species": { "description": "種類", "items": { "type": "string" }, "type": "array" } }, "required": [ "name", "age", "species" ], "type": "object" } } } ``` ### つかってみる いい感じ。 ![[2025-08-23-14-08-51.avif]] しっかりチェックしてくれてよい。 ![[2025-08-23-14-10-03.avif]] ## 標準的な型の対応状況 `index.ts` ```ts export interface Pattern { nullable: string | null; optional?: number; union: "apple" | "banana" | "cherry"; intersection: { id: number } & { name: string }; keyValue: { [key: string]: number }; array: string[]; tuple: [number, string, boolean]; } ``` これくらいならちゃんとサポートされてそう。 ```json { "$ref": "#/definitions/Pattern", "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "Pattern": { "additionalProperties": false, "properties": { "array": { "items": { "type": "string" }, "type": "array" }, "intersection": { "additionalProperties": false, "properties": { "id": { "type": "number" }, "name": { "type": "string" } }, "required": [ "id", "name" ], "type": "object" }, "keyValue": { "additionalProperties": { "type": "number" }, "type": "object" }, "nullable": { "type": [ "string", "null" ] }, "optional": { "type": "number" }, "tuple": { "items": [ { "type": "number" }, { "type": "string" }, { "type": "boolean" } ], "maxItems": 3, "minItems": 3, "type": "array" }, "union": { "enum": [ "apple", "banana", "cherry" ], "type": "string" } }, "required": [ "nullable", "union", "intersection", "keyValue", "array", "tuple" ], "type": "object" } } } ``` ## 高度な型の対応状況 よく使う以下4パターンにチャレンジ。 - [[keyof型演算子]] + [[インデックスアクセス型 (TypeScript)|インデックスアクセス型]] - [[Mapped Types]] - [[条件付き型 (TypeScript)|条件付き型]] - [[テンプレートリテラル型]] `index.ts` ```ts /** keyof型演算子 + インデックスアクセス型 */ const fruits = ["apple", "banana", "cherry"] as const; export type Fruit = (typeof fruits)[number]; /** Mapped Types */ type ConditionalType<T> = T extends string ? "string" : "other"; export type CondA = ConditionalType<string>; export type CondB = ConditionalType<"hoge">; export type CondC = ConditionalType<number>; /** 条件付き型 */ type Stringable<T> = { [K in keyof T]: string }; export type MappedType = Stringable<{ a: number; b: boolean }>; /** テンプレートリテラル型 */ export type SuperFruit = `${Fruit} pie` | `${Fruit} juice`; ``` 思いの外対応してた。 ```json { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "CondA": { "const": "string", "description": "Mapped Types", "type": "string" }, "CondB": { "const": "string", "description": "Mapped Types", "type": "string" }, "CondC": { "const": "other", "description": "Mapped Types", "type": "string" }, "Fruit": { "enum": [ "apple", "banana", "cherry" ], "type": "string" }, "MappedType": { "additionalProperties": false, "description": "条件付き型", "properties": { "a": { "type": "string" }, "b": { "type": "string" } }, "required": [ "a", "b" ], "type": "object" }, "SuperFruit": { "description": "テンプレートリテラル型", "enum": [ "apple pie", "banana pie", "cherry pie", "apple juice", "banana juice", "cherry juice" ], "type": "string" } } } ``` ## 対応していない型 [[Parameters (TypeScript)|Parameters]]と[[ReturnType (TypeScript)|ReturnType]]は対応してなさそうだった。よく使うので少し残念。 `index.ts` ```ts function sum(a: number, b: string): string { return String(a + Number(b)); } export type SumParameters = Parameters<typeof sum>; export type SumReturn = ReturnType<typeof sum>; ``` `Failed to correctly infer type` と出てしまう。 ```json { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "SumParameters": { "description": "Failed to correctly infer type" }, "SumReturn": { "description": "Failed to correctly infer type" }, "sum": { "$comment": "(a: number, b: string) => string", "properties": { "namedArgs": { "additionalProperties": false, "properties": { "a": { "type": "number" }, "b": { "type": "string" } }, "required": [ "a", "b" ], "type": "object" } }, "type": "object" } } } ```