Schema에서 TypeScript 타입 생성하기
핵심 요약: json-schema-to-typescript와 quicktype은 한 명령으로 .d.ts를 내지만 초안일 뿐입니다. 선택성, 유니언, additionalProperties, 날짜는 사람이 손봐야 합니다.

핵심부터 말하면, json-schema-to-typescript나 quicktype로 생성한 뒤 선택성, 유니언, additionalProperties, 날짜를 손으로 고치세요. Schema는 원천, 타입은 출력으로 유지하고 CI의 types:check 단계로 강제하세요.
한 명령이 파일을 줍니다. 올바른 타입을 주지는 않습니다.
한 줄 명령
npx json-schema-to-typescript schema.json > src/types/order.d.ts
$ref, allOf, oneOf, anyOf를 처리하고 description을 JSDoc으로 변환합니다. 배너와 선택한 style로 배치 생성하려면 작은 build-types.mjs에서 Node API를 호출하세요.
대안은 quicktype이며 샘플 JSON에서 스키마를 추론할 수도 있습니다:
npx quicktype -s schema schema.json -o order.ts --lang typescript
이후 고칠 네 가지
선택성. required에 없는 모든 것이 ?가 됩니다. 그러나 "항상 존재, null일 수 있음"과 "없을 수 있음"은 다른 계약입니다:
interface Order {
remark?: string | null; // may be missing
status: string;
}
백엔드가 항상 remark: null을 보낸다면 ?를 떼고 모든 소비자가 undefined를 가드하게 만들지 마세요.
비판별 유니언. oneOf는 대개 A | B가 되고 TypeScript는 리터럴 필드 없이 좁힐 수 없습니다. Schema의 각 분기에 고정 type 속성을 더하세요.
additionalProperties. 생략되거나 true이면 때때로 [k: string]: unknown, 때때로 any가 됩니다. 전자는 안전하고 후자는 객체 전체의 타입 검사를 조용히 끕니다.
날짜 형식. format: "date-time"은 전송로에서 문자열입니다. Date로 매핑하면 역직렬화도 해야 하고, 아니면 런타임 값은 문자열로 남고 타입이 거짓말합니다.
방향 고정
Schema가 원천, 타입이 출력입니다. 손으로 쓴 타입에서 Schema를 생성하는 것은 재생성이 의무이고 CI에서 강제될 때만 허용됩니다. 아니면 양쪽이 어긋나고 어느 쪽이 권위인지 아무도 모릅니다.
파이프라인에 넣기
"types:gen": "json2ts -i schemas/ -o src/types/generated",
"types:check": "pnpm types:gen && git diff --exit-code src/types/generated"
types:check가 중요한 부분입니다. Schema를 바꾸고 재생성하지 않으면 CI가 실패합니다.
FAQ
생성 파일에 왜 any가 들어가나?
대개 additionalProperties가 true이거나 생략되어 일부 생성기가 [k: string]: any로 매핑하기 때문입니다. unknown이나 명시적 필드로 바꾸세요. any는 객체 전체의 타입 검사를 끕니다.
생성 후 선택 필드를 어떻게 고치나?
required 밖의 모든 것이 ?가 되지만 "항상 존재, null일 수 있음"은 "없을 수 있음"과 다릅니다. 백엔드가 항상 필드를 보내면 ?를 떼세요.
Schema와 타입이 어긋나면 CI가 실패해야 하나?
예. 재생성 후 git diff --exit-code를 실행하는 types:check 스크립트는 Schema가 재생성 없이 바뀌는 즉시 빌드를 실패시킵니다.