## 経緯
[[🦉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"
}
}
}
```