본문으로 건너뛰기

TypeScript에서 JSON 스키마로 변환 — Numio

ts-json-schema-generator로 TypeScript 타입에서 draft-07 JSON Schema를 생성합니다. 모든 타입은 "definitions" 아래에 들어가며, 선택적 속성은 "required"에서 빠지고 객체에는 "additionalProperties": false가 붙습니다.

요청과 응답 타입이 TypeScript interface로 정의되어 있고, Ajv 검증이나 API 게이트웨이용 JSON Schema가 필요할 때.

TypeScript

JSON Schema

이럴 때 사용하세요

  • 요청과 응답 타입이 TypeScript interface로 정의되어 있고, Ajv 검증이나 API 게이트웨이용 JSON Schema가 필요할 때.
  • 구조가 이미 TypeScript 타입으로 정의된 JSON 설정 파일의 스키마를 공개하고 싶을 때.

사용 방법

  1. TypeScript interface나 타입 별칭을 붙여 넣습니다. @minimum, @format, @pattern 같은 JSDoc 태그는 스키마에 반영됩니다.
  2. 소스는 /api/typescript-to-json-schema로 전송되어 서버의 임시 파일에 기록되고, 모든 타입을 노출하는 설정으로 처리됩니다.
  3. JSON Schema를 복사합니다. 입력에 타입이 하나뿐이면 루트에도 그 타입을 가리키는 $ref가 붙습니다.

TypeScript

/** A product in the catalog */
export interface Product {
  /** @minimum 0 */
  price: number;
  name: string;
  tags?: string[];
}

JSON Schema (draft-07)

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/Product",
  "definitions": {
    "Product": {
      "type": "object",
      "properties": {
        "price": {
          "type": "number",
          "minimum": 0
        },
        "name": {
          "type": "string"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "price",
        "name"
…

세부 정보 및 제한 사항

입력은 변환을 위해 서버 라우트(/api/typescript-to-json-schema)로 전송되며, 브라우저에서만 처리되지 않습니다. Next.js API 라우트는 기본적으로 최대 1 MB의 요청 본문을 받습니다.

JSDoc은 확장 모드로 파싱됩니다. 설명 주석은 "description"이 되고, @minimum 0이나 @minLength 1 같은 태그는 키워드가 됩니다.

interface의 메서드는 건너뜁니다. Date는 format이 date-time인 string이 되고, 리터럴 유니온은 enum이 됩니다.

bigint는 지원하지 않으며 "Unknown node" 오류를 반환합니다. Map과 Set은 해당 interface, 즉 숫자 size만 있는 객체로 기술되므로 JSON 데이터에는 Record<string, T>나 배열을 쓰세요.

FAQ

export되지 않은 타입도 포함되나요?

네. 입력에 있는 모든 타입이 export 여부와 관계없이 "definitions"에 추가되며, 타입 간 참조에는 $ref가 쓰입니다.

선택적 속성과 nullable 속성은 어떻게 표현되나요?

선택적 속성은 "required"에서 빠집니다. null과의 유니온은 {"type": "null"}을 포함한 anyOf가 됩니다.

루트에 $ref가 있는 이유는 무엇인가요?

타입이 하나뿐이면 생성기가 $ref로 루트를 그 타입에 연결합니다. 타입이 여러 개면 "definitions"만 출력됩니다.

사양 및 참고 자료