本文へスキップ

JSONスキーマからTypeScript定義への変換 — Numio

json-schema-to-typescript を使って JSON Schema を TypeScript の interface にコンパイルします。"required" にないプロパティは省略可能になり、additionalProperties が false でないオブジェクトにはインデックスシグネチャが付きます。

API が JSON Schema ファイルを公開しており、それを利用するクライアントコード用に対応する interface がほしい場合。

JSON Schema

TypeScript

こんなときに使えます

  • API が JSON Schema ファイルを公開しており、それを利用するクライアントコード用に対応する interface がほしい場合。
  • スキーマで検証している設定ファイルがあり、設定を読み込む箇所で型チェックを効かせたい場合。

使い方

  1. JSON Schema パネルに JSON Schema を貼り付けます。"title" が interface 名になり、ない場合はルートの名前が MySchema になります。
  2. 入力に合わせてブラウザ内で変換されます。ページに設定項目はなく、バナーコメントも追加されません。
  3. TypeScript パネルから interface をコピーします。ページが Prettier で整形するため、インデントは 2 スペースでセミコロンは付きません。

JSON Schema

{
  "title": "Address",
  "type": "object",
  "properties": {
    "street": { "type": "string", "minLength": 1 },
    "zip": { "type": "string", "pattern": "^[0-9]{5}$" },
    "country": { "enum": ["US", "CA"], "default": "US" },
    "unit": { "type": ["integer", "null"] },
    "lines": { "type": "array", "items": { "type": "string" }, "maxItems": 3 },
    "geo": { "type": "object", "required": ["lat", "lng"],
      "properties": { "lat": { "type": "number" }, "lng": { "type": "number" } } }
  },
  "required": ["street", "zip"]
}

TypeScript の interface

export interface Address {
  street: string
  zip: string
  country?: "US" | "CA"
  unit?: number | null
  lines?: [] | [string] | [string, string] | [string, string, string]
  geo?: {
    lat: number
    lng: number
    [k: string]: unknown
  }
  [k: string]: unknown
}

仕様と制限

"additionalProperties": false のないオブジェクトには [k: string]: unknown が付くため、型上は余分なキーも許容されます。

配列の maxItems は、例の "lines" のようにタプルのユニオン型に展開されます。

#/definitions/Tag のようなローカルの $ref は、別々にエクスポートされる interface になります。

ページは結果をセミコロンなしの設定で Prettier にかけるため、"US" | "CA" のようなユニオン型を囲む冗長な括弧も取り除かれます。

FAQ

null 値はどう型付けされますか?

"type": ["integer", "null"] は (number | null) になります。integer と number はどちらも number に対応します。

[k: string]: unknown を消すにはどうすればよいですか?

各オブジェクトスキーマに "additionalProperties": false を追加すると、インデックスシグネチャは出力されなくなります。

ルートの interface 名はどう決まりますか?

スキーマの "title" を PascalCase にしたものです("Example Schema" なら ExampleSchema)。title がなければ MySchema になります。

スキーマはサーバーに送信されますか?

いいえ。json-schema-to-typescript の compile 関数がこのページのブラウザ内で実行されます。

仕様を確認する