data / typescript

JSON → TypeScript 型生成

JSONオブジェクトからTypeScriptのinterface・type定義を自動生成します。APIレスポンスの型付けに。入力データはサーバーに送信されません。

// 生成ボタンを押すとTypeScript型定義がここに表示されます

使い方

01
  1. 左側のテキストエリアにJSONをペーストしてください
  2. 生成したい型の名前(デフォルト: Root)を「型名」フィールドに入力します
  3. スタイルを interfacetype から選択します
  4. 「生成」ボタンを押すとTypeScript型定義が右側に表示されます
  5. 「コピー」ボタンでクリップボードにコピーして、そのままコードに貼り付けられます

実装コード

02

コアロジックはブラウザ標準の JSON.parse のみで実装しており、外部ライブラリは一切使用していません。 再帰的に型を推論する inferType 関数と、エントリーポイントとなる generateTypes 関数をそのままコピーしてご利用いただけます。

type JsonValue = string | number | boolean | null | JsonValue[] | Record<string, JsonValue>

function isRecord(v: JsonValue): v is Record<string, JsonValue> {
  return typeof v === 'object' && v !== null && !Array.isArray(v)
}

function inferType(
  value: JsonValue,
  indent: string,
  depth: number,
  rootName: string,
  interfaces: Map<string, string>
): string {
  if (value === null) return 'null'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'string') return 'string'

  if (Array.isArray(value)) {
    if (value.length === 0) return 'unknown[]'
    const elementTypes = value.map(v =>
      inferType(v, indent, depth + 1, rootName, interfaces)
    )
    const unique = [...new Set(elementTypes)]
    const inner = unique.length === 1 ? unique[0] : `(${unique.join(' | ')})`
    return `${inner}[]`
  }

  if (isRecord(value)) {
    const entries = Object.entries(value)
    const lines = entries.map(([k, v]) => {
      const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : `"${k}"`
      const isOptional = v === null
      const typeStr = inferType(v, indent, depth + 1, rootName, interfaces)
      return `${indent.repeat(depth + 1)}${safeKey}${isOptional ? '?' : ''}: ${typeStr};`
    })
    return `{
${lines.join('\n')}
${indent.repeat(depth)}}`
  }

  return 'unknown'
}

export function generateTypes(
  json: string,
  rootName: string = 'Root',
  style: 'interface' | 'type' = 'interface'
): { ok: true; output: string } | { ok: false; error: string } {
  if (!json.trim()) return { ok: false, error: '入力が空です' }
  let parsed: JsonValue
  try {
    parsed = JSON.parse(json)
  } catch (e) {
    return { ok: false, error: `JSONの解析に失敗: ${e instanceof SyntaxError ? e.message : String(e)}` }
  }
  const indent = '  '
  const interfaces = new Map<string, string>()
  if (isRecord(parsed)) {
    const typeStr = inferType(parsed, indent, 0, rootName, interfaces)
    const decl = style === 'interface'
      ? `export interface ${rootName} ${typeStr}`
      : `export type ${rootName} = ${typeStr}`
    return { ok: true, output: decl }
  }
  return { ok: true, output: `export type ${rootName} = ${inferType(parsed, indent, 0, rootName, interfaces)}` }
}

よくある使用例・注意点

03
APIレスポンスの型付け
fetch や axios で取得したAPIレスポンスに型を付けたい場合に活用できます。レスポンスJSONをそのままペーストすれば、すぐに使えるinterface定義が生成されます。生成後は実際のAPIドキュメントと照合して省略可能フィールドに ? を追加するとより堅牢になります。
null値の扱い
JSONでnullのフィールドは TypeScriptの型として null と推論されます。実際には string | null のようなユニオン型が適切なケースも多いため、生成後に手動で調整することを推奨します。また、フィールドがnullの場合は ? (optional) としてマークします。
ネストされたオブジェクト
深くネストされたオブジェクトも再帰的に処理し、インライン型として展開されます。ネストが深い場合や同じ構造が繰り返し使われる場合は、生成された型を分割して個別のinterfaceに切り出すとコードの再利用性が高まります。
配列の型推論
配列の型は最初の要素から推論されます。複数の異なる型の要素が含まれる場合はユニオン型として生成されます。空配列の場合は unknown[] となるため、実際の型に置き換えてください。ルートが配列の場合は RootList 型も合わせて生成されます。

関連ツール

04
JSONフォーマッターCSV → JSON変換

ソースコード

05

このツールのソースコード(テストコードを含む)はGitHubで公開しています。 MITライセンスで自由に利用・改変できます。

GitHub でコードを見る →