JSON to TypeScript 변환기는 JSON 객체나 배열을 읽어 발견한 모든 객체의 선언을 만들어 줍니다. 예전에 별도 도구였던 TypeSift의 기능도 이 페이지에 합쳐져 있어서 루트 이름(기본 ApiResponse), interface와 type 별칭, export 키워드, readonly 속성, 알 수 없는 값을 unknown으로 둘지 any로 둘지를 모두 고를 수 있습니다. 실제 계약을 쓰기 전에 API 응답, 설정 파일, 픽스처의 첫 타입이 필요할 때 쓰는 도구입니다.
같은 위치에 있는 값은 모두 병합됩니다. 객체 배열은 모든 원소의 키를 합친 인터페이스 하나가 되고, 일부 원소에만 있는 키는 key?: T로 표시됩니다. null은 | null이 되고 섞인 배열은 (string | number)[] 같은 진짜 유니온이 됩니다. 루트도 객체일 필요가 없어서 최상위 배열은 export type Rows = Row[]로 출력됩니다.
모든 처리는 브라우저 안에서 이루어지며 입력은 업로드되지 않습니다. 입력 한도는 20 MiB입니다.
사용 방법
JSON 붙여넣기 또는 예제 불러오기
JSON 객체나 배열을 붙여넣거나, 예제 메뉴에서 API 응답, 중첩 배열, 엣지 케이스를 골라 출력이 어떻게 달라지는지 확인합니다. 이름 붙은 객체 타입을 만들 수 없는 단일 값 루트는 거부됩니다.
루트 이름 정하기
루트 타입 이름에 이름을 입력합니다. 영문자와 숫자가 아닌 문자는 단어 경계로 처리되어 PascalCase가 되므로
my api는MyApi가 되고, 숫자로 시작하면Type접두사가 붙습니다. 다운로드 파일 이름도 같은 이름을 따라MyApi.ts처럼 정해집니다.선언 방식 고르기
선언 방식에서 interface와 type 별칭 중 하나를 고르고, export 키워드와 readonly 속성을 켜거나 끄고, 타입을 알 수 없는 값을 unknown으로 쓸지 any로 쓸지 정합니다.
선언 확인
루트가 먼저 나오고 중첩 타입이 만난 순서대로 뒤따릅니다.
?표시와| null유니온이 API에 대해 알고 있는 내용과 맞는지 확인합니다.복사 또는 다운로드
코드를
.ts나.d.ts파일에 넣습니다. 문자열 리터럴 유니온처럼 샘플로는 알 수 없는 제약은 직접 추가합니다.
작동 원리
JSON과 TypeScript 타입 대응
타입은 첫 번째 값이 아니라 같은 위치에서 본 모든 값으로 추론됩니다. 일부 객체에 없는 키는 선택 속성이 되고, null은 타입을 unknown으로 망가뜨리는 대신 | null을 덧붙입니다.
배열은 모든 원소의 타입을 모읍니다. 타입이 하나면 T[], 여럿이면 (A | B)[]입니다. 객체 배열은 키 이름의 단수형을 딴 인터페이스 하나를 공유하므로 ApiResponse 아래 items는 ApiResponseItem이 됩니다.
| JSON 값 | TypeScript 타입 | 비고 |
|---|---|---|
| string | string | |
| number | number | 정수와 실수를 구분하지 않습니다 |
| true / false | boolean | |
| 다른 타입과 함께 나온 null | T | null | [null, "a"]는 (string | null)[] |
| null만 나온 경우 | null | |
| 객체 | interface 또는 type 별칭 | 경로로 이름을 붙이고, 끄지 않으면 export합니다 |
| 일부 객체에 없는 키 | key?: T | 같은 위치에 객체가 둘 이상 있어야 합니다 |
| 여러 타입의 배열 | (A | B)[] | |
| 빈 배열 | unknown[] | any 옵션이면 any[] |
이름 짓기, 충돌, 따옴표 규칙
중첩 인터페이스의 이름은 부모 이름 뒤에 키를 PascalCase로 붙인 것입니다. 서로 다른 두 위치가 같은 이름이 되면 나중 것에 숫자 접미사(2, 3, ...)가 붙어서 앞의 인터페이스를 덮어쓰지 않으므로 속성이 사라지지 않습니다.
속성 키가 ^[A-Za-z_$][A-Za-z0-9_$]*$에 맞으면 그대로, 그렇지 않은 user-name이나 a b 같은 키는 큰따옴표 문자열로 쓰이며 접근할 때 대괄호 표기법을 써야 합니다.
export interface ApiResponse {
"user-name": string;
tags: string[];
}옵션 한눈에 보기
선언 방식은 interface와 type 별칭 중에서 고릅니다. export 키워드를 끄면 모든 선언에서 접두사가 빠집니다. readonly 속성을 켜면 각 속성 앞에 readonly가 붙습니다. 알 수 없는 값은 []의 원소처럼 아무 정보도 없을 때 쓰는 타입을 정합니다.
이 옵션들은 추론된 같은 구조를 어떻게 출력하느냐만 바꿉니다. ?와 | null을 포함한 구조 자체는 달라지지 않습니다.
실제 예시
{"user":{"id":1,"name":"Ari"},"tags":["api","beta"]}export interface ApiResponse {
user: ApiResponseUser;
tags: string[];
}
export interface ApiResponseUser {
id: number;
name: string;
}중첩 객체마다 경로 이름을 딴 export interface가 만들어지고 루트는 ApiResponse라는 이름을 유지합니다.
{"items":[{"sku":"a","qty":2},{"sku":"b","qty":1,"note":"x"}]}export interface ApiResponse {
items: ApiResponseItem[];
}
export interface ApiResponseItem {
sku: string;
qty: number;
note?: string;
}두 원소가 ApiResponseItem을 공유합니다. note 키는 한 원소에만 있어서 선택 속성이 됩니다.
{"user-name":"a","tags":["a",1,null],"empty":[],"note":null}export interface ApiResponse {
"user-name": string;
tags: (string | number | null)[];
empty: unknown[];
note: null;
}식별자가 아닌 키는 따옴표로 감싸이고, null은 유니온에 합류하며, 빈 배열은 unknown[], null만 있는 값은 null이 됩니다.
[{"id":1,"tag":"a"},{"id":2}]export type Rows = Row[];
export type Row = {
readonly id: number;
readonly tag?: string;
};루트 타입 이름 Rows, 선언 방식 type 별칭, readonly 속성 켬으로 실행한 결과입니다. 루트는 type 별칭이 되고 원소는 Row라는 이름을 받습니다.
{"a":{"b":{"x":1}},"aB":{"y":"s"}}export interface ApiResponse {
a: ApiResponseA;
aB: ApiResponseAB2;
}
export interface ApiResponseA {
b: ApiResponseAB;
}
export interface ApiResponseAB {
x: number;
}
export interface ApiResponseAB2 {
y: string;
}a.b와 aB는 모두 ApiResponseAB가 되는데, 두 번째에 접미사 2가 붙어서 어느 인터페이스도 속성을 잃지 않습니다.
자주 하는 실수
선택 속성은 객체가 둘 이상일 때만 나타납니다
같은 위치의 일부 객체에 키가 없을 때만 선택 속성이 됩니다. 객체가 하나뿐이면 비교 대상이 없어 모든 키가 필수입니다. 레코드를 여러 개 붙여넣거나
?를 직접 추가하세요.숫자는 int와 float로 나뉘지 않습니다
둘 다
number이며,10.0처럼 값이 정수인 소수 표기도 마찬가지입니다. 타입 추론 중 JSON 숫자는 JavaScript number 정밀도를 사용하므로 2^53을 넘는 ID는 자릿수를 잃을 수 있습니다. 이런 ID는 자체 계약에서string을 쓰세요.샘플만으로는 타입이 완전한지 알 수 없습니다
샘플에 null이 한 번도 없으면
| null이 붙지 않고, 모든 원소에 키가 있었다면 필수가 됩니다. 값이 고르지 않은 경우까지 담은 샘플을 쓰세요.ID를 키로 쓰는 객체는 넓은 인터페이스가 됩니다
{"u1": {...}, "u2": {...}}같은 객체는Record<string, T>가 아니라 키마다 속성 하나로 출력됩니다. 직접 고쳐 쓰세요.이름이 겹치면 숫자 접미사가 붙습니다
충돌 뒤에는
ApiResponseAB2같은 이름이 나옵니다. 서로 다른 인터페이스이므로 커밋하기 전에 의미 있는 이름으로 바꾸세요.
자주 묻는 질문
루트가 배열이어도 되나요?
됩니다. export type ApiResponse = ApiResponseItem[];와 항목 인터페이스가 출력됩니다. 루트 이름을 Rows로 하면 Rows = Row[]가 됩니다.
interface인가요, type 별칭인가요?
선언 방식에서 둘 중 고를 수 있습니다. 객체는 고른 방식으로 출력되고, 배열 루트는 항상 type 별칭입니다. 단일 값 루트는 거부됩니다.
선택 속성을 표시해 주나요?
네, 같은 위치의 객체들(예: 한 배열의 원소들) 중 일부에 키가 없으면 key?: T로 출력합니다.
null은 어떻게 처리되나요?
null이 유니온에 추가되어 [null, "a"]는 (string | null)[]가 됩니다. null만 나온 위치는 null 타입입니다.
TypeSift와 같은 도구인가요?
네, TypeSift는 이 페이지에 합쳐졌습니다. 루트 이름, interface·type 별칭, export, readonly, unknown·any가 모두 여기의 옵션입니다.
키가 따옴표로 감싸여 나오는 이유는 무엇인가요?
user-name처럼 식별자로 쓸 수 없는 키이기 때문입니다. obj["user-name"]로 접근하세요.
JSON이 업로드되나요? 크기 제한은요?
업로드되지 않으며 변환은 브라우저 안에서 실행됩니다. 입력 한도는 20 MiB입니다.
마지막 업데이트:
