DevToolBoxGRATIS
Blog

JSON ke TypeScript Online: Panduan Lengkap untuk Developer

13 menit bacaoleh DevToolBox
TL;DR

Generating TypeScript types from JSON saves hours of manual typing, catches bugs at compile time, and keeps your codebase in sync with APIs. Use our free online tool or libraries like quicktype and json2ts to auto-generate interfaces. Combine generated types with Zod for runtime validation. Always prefer interfaces for object shapes and enable strict mode in tsconfig.json for maximum type safety.

Key Takeaways
  • TypeScript interfaces generated from JSON catch shape mismatches at compile time, preventing runtime errors.
  • Use interface for object shapes (extendable, mergeable) and type alias for unions, intersections, and mapped types.
  • Mark fields as optional (?) when they may be absent, and use union types (string | null) for nullable values.
  • Tools like quicktype, json2ts, and our online converter handle nested objects, arrays, and union types automatically.
  • Zod bridges the gap between compile-time types and runtime validation with z.infer<typeof schema>.
  • Enable resolveJsonModule and strict mode in tsconfig.json to import .json files with full type safety.
  • Wrap API responses in a generic ApiResponse<T> type for consistent error handling across your app.

Try our free JSON to TypeScript converter

Why Generate TypeScript Types from JSON?

Every modern web application communicates with APIs that return JSON data. Without TypeScript types, you are flying blind: property names could be misspelled, nested objects could be null, and arrays could contain unexpected shapes. TypeScript catches these problems at compile time, but only if you have accurate type definitions.

Manually writing interfaces for complex API responses is tedious and error-prone. A single JSON payload from a REST API can have dozens of nested fields, optional properties, and array structures. Automated generation ensures your types match the actual data shape.

Here are the key benefits of generating TypeScript types from JSON:

  • Compile-time safety: Access non-existent properties? TypeScript catches it before your code runs.
  • IDE autocomplete: Generated interfaces give you full IntelliSense for every nested field.
  • Refactoring confidence: Rename a field in your type and TypeScript flags every usage that needs updating.
  • Documentation: Types serve as living documentation of your API contracts.
  • Team alignment: Shared types ensure frontend and backend developers agree on data shapes.
// Without types - runtime errors waiting to happen
const user = await fetch("/api/user").then(r => r.json());
console.log(user.nme);     // Typo! No error until runtime
console.log(user.address.city); // Crashes if address is null

// With generated types - caught at compile time
interface User {
  name: string;
  email: string;
  address: Address | null;
}
const user: User = await fetch("/api/user").then(r => r.json());
console.log(user.nme);     // TS Error: Property 'nme' does not exist
console.log(user.address.city); // TS Error: 'address' is possibly null

Interface vs Type Alias: Which Should You Use for JSON Data?

TypeScript offers two ways to define object shapes: interface and type. For JSON-derived types, interfaces are generally preferred, but each has strengths:

When to Use interface

Interfaces are the default choice for object shapes. They support declaration merging (augmenting an existing interface) and extends for inheritance. Most JSON-to-TypeScript tools generate interfaces by default.

// Interface: extendable and mergeable
interface User {
  id: number;
  name: string;
  email: string;
}

// Extend an interface
interface AdminUser extends User {
  role: "admin";
  permissions: string[];
}

// Declaration merging: add fields to existing interface
interface User {
  avatar?: string; // Merged with the original User interface
}

// Now User has: id, name, email, avatar

When to Use type Alias

Type aliases are better for union types, intersection types, mapped types, and conditional types. If your JSON contains fields that can be multiple types (e.g., <code>string | number</code>), a type alias is more natural for expressing that.

// Type alias: ideal for unions and intersections
type Status = "active" | "inactive" | "pending";
type ID = string | number;

// Intersection type
type UserWithPosts = User & { posts: Post[] };

// Mapped type (only possible with type)
type ReadonlyUser = Readonly<User>;
type PartialUser = Partial<User>;
type UserKeys = keyof User; // "id" | "name" | "email"

// Conditional type
type ApiResult<T> = T extends Error ? ErrorResponse : SuccessResponse<T>;

Rule of thumb: Use interface for API response objects and type for unions, utility types, and complex transformations.

Handling Optional and Nullable Fields

Real-world JSON data often has fields that are sometimes present and sometimes missing, or fields that can be null. TypeScript distinguishes between these cases:

Optional Fields (?)

Use the ? modifier when a field may be absent from the JSON entirely. This is different from a field being present with a null value.

// JSON may or may not have "middleName" and "phone"
// { "name": "Alice", "email": "alice@example.com" }
// { "name": "Bob", "email": "bob@example.com", "middleName": "J.", "phone": "+1234" }

interface User {
  name: string;
  email: string;
  middleName?: string; // May be absent from JSON
  phone?: string;      // May be absent from JSON
}

// Usage: must check before accessing
function getDisplayName(user: User): string {
  if (user.middleName) {
    return `${user.name} ${user.middleName}`;
  }
  return user.name;
}

Nullable Fields (| null)

Use a union with null when the field is always present but its value can be null. This is common in database-backed APIs where a column exists but has no value.

// JSON always has "bio" but it can be null
// { "name": "Alice", "bio": "Software engineer" }
// { "name": "Bob", "bio": null }

interface UserProfile {
  name: string;
  bio: string | null;       // Always present, may be null
  avatarUrl: string | null;  // Always present, may be null
}

// Usage: narrow the type before using
function renderBio(profile: UserProfile): string {
  return profile.bio ?? "No bio provided";
}

Optional AND Nullable

Some APIs return fields that are both optional and nullable. Combine ? with | null:

interface UserSettings {
  theme: "light" | "dark";
  nickname?: string | null;     // May be absent OR present as null
  customColor?: string | null;  // May be absent OR present as null
}

// All of these are valid:
const a: UserSettings = { theme: "dark" };                        // nickname absent
const b: UserSettings = { theme: "dark", nickname: null };        // nickname is null
const c: UserSettings = { theme: "dark", nickname: "CoolUser" }; // nickname has value

Nested Objects and Arrays

JSON from APIs typically contains deeply nested structures. TypeScript handles these with nested interface definitions or inline types:

Nested Object Interfaces

Extract each nested object into its own interface for reusability and clarity:

// JSON with nested structure:
// {
//   "id": 1,
//   "name": "Alice",
//   "address": { "street": "123 Main", "city": "NYC", "geo": { "lat": 40.7, "lng": -74.0 } },
//   "company": { "name": "Acme", "department": "Engineering" }
// }

interface GeoLocation {
  lat: number;
  lng: number;
}

interface Address {
  street: string;
  city: string;
  state?: string;
  zipCode?: string;
  geo: GeoLocation;
}

interface Company {
  name: string;
  department: string;
}

interface User {
  id: number;
  name: string;
  address: Address;
  company: Company;
}

Typed Arrays

Arrays in JSON should be typed with the element type. Use Type[] or Array<Type> syntax:

interface BlogPost {
  id: number;
  title: string;
  tags: string[];           // Array of primitives
  comments: Comment[];      // Array of objects
  images: Image[];          // Array of objects
}

interface Comment {
  id: number;
  author: string;
  body: string;
  replies: Comment[];       // Recursive type: comments can have replies
}

interface Image {
  url: string;
  alt: string;
  width: number;
  height: number;
}

// Type[] vs Array<Type> - both are equivalent
type StringArray = string[];
type StringArray2 = Array<string>;

// ReadonlyArray prevents push/pop/splice
type ImmutableTags = ReadonlyArray<string>;

Tuple Types for Fixed-Length Arrays

If your JSON contains arrays with a fixed number of elements of specific types (e.g., coordinates), use tuple types:

// JSON: { "coordinates": [40.7128, -74.0060] }
// JSON: { "range": [1, 100] }

type Coordinates = [number, number];       // [latitude, longitude]
type Range = [number, number];             // [min, max]
type RGB = [number, number, number];       // [red, green, blue]
type NameAge = [string, number];           // ["Alice", 30]

interface Location {
  name: string;
  coordinates: Coordinates;
}

// Labeled tuple elements (TypeScript 4.0+)
type Point = [x: number, y: number, z?: number];

Union Types from Varying JSON Values

Some JSON fields can contain different types of values. For example, an ID field might be a string or number, or a status field might be one of several literal values. TypeScript union types handle these naturally:

String Literal Unions

When a field has a fixed set of possible values, use a string literal union for maximum type safety:

// String literal union for status field
type OrderStatus = "pending" | "processing" | "shipped" | "delivered" | "cancelled";

interface Order {
  id: string;
  status: OrderStatus;      // Only these 5 values allowed
  priority: "low" | "medium" | "high";
}

// Number literal union
type HttpStatus = 200 | 201 | 400 | 401 | 403 | 404 | 500;

// Mixed type union
type ID = string | number;  // API returns ID as string or number

interface Product {
  id: ID;
  price: number;
  discount: number | null;  // null means no discount
}

Discriminated Unions

When JSON objects have a "type" field that determines their shape, use discriminated unions. This is common in event systems and polymorphic APIs:

// Discriminated union: "type" field determines the shape
interface TextMessage {
  type: "text";
  content: string;
}

interface ImageMessage {
  type: "image";
  url: string;
  width: number;
  height: number;
}

interface VideoMessage {
  type: "video";
  url: string;
  duration: number;
  thumbnail: string;
}

type Message = TextMessage | ImageMessage | VideoMessage;

// TypeScript narrows the type based on the discriminant
function renderMessage(msg: Message) {
  switch (msg.type) {
    case "text":
      return msg.content;        // TypeScript knows this is TextMessage
    case "image":
      return msg.url;            // TypeScript knows this is ImageMessage
    case "video":
      return msg.thumbnail;      // TypeScript knows this is VideoMessage
  }
}

Try our free JSON to TypeScript converter

JSON-to-TypeScript Generation Tools

Several tools can automatically generate TypeScript interfaces from JSON. Here are the most popular options:

quicktype

Quicktype is the most powerful JSON-to-TypeScript tool. It infers union types, handles optional fields, and supports many output languages. Available as a CLI, npm package, and web app:

# Install quicktype CLI
npm install -g quicktype

# Generate TypeScript from a JSON file
quicktype -s json -o types.ts --lang ts data.json

# Generate from a JSON URL (API endpoint)
quicktype -s json -o types.ts --lang ts "https://api.example.com/users"

# Generate with runtime type checks (io-ts)
quicktype -s json -o types.ts --lang ts --just-types data.json

# Generate interfaces (not classes)
quicktype -s json -o types.ts --lang ts --just-types --interfaces-only data.json

# Add to package.json scripts
# "generate:types": "quicktype -s json -o src/types/api.ts --lang ts --just-types api-response.json"

json2ts / json-to-ts

A simpler alternative that generates TypeScript interfaces from JSON. Available as an npm package and VS Code extension:

# Install json-to-ts
npm install -g json-to-ts

# Use programmatically in Node.js
const JsonToTS = require("json-to-ts");

const json = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
  address: {
    street: "123 Main St",
    city: "New York"
  },
  tags: ["developer", "designer"]
};

const interfaces = JsonToTS(json);
console.log(interfaces.join("\n\n"));
// interface RootObject {
//   id: number;
//   name: string;
//   email: string;
//   address: Address;
//   tags: string[];
// }
//
// interface Address {
//   street: string;
//   city: string;
// }

Online Converters

For quick one-off conversions, our free online tool lets you paste JSON and get TypeScript interfaces instantly. No installation required:

Try our free JSON to TypeScript converter

VS Code Extensions

Several VS Code extensions can convert JSON to TypeScript directly in your editor. Search for "JSON to TS" in the extensions marketplace. The most popular ones include Paste JSON as Code and JSON to TS.

Zod: Runtime Validation with TypeScript Types

TypeScript types only exist at compile time. They are erased when your code is compiled to JavaScript. This means runtime data (API responses, user input, environment variables) can still be the wrong shape. Zod solves this by providing runtime validation that also generates TypeScript types:

Basic Zod Schema

Define a schema and infer the TypeScript type from it. The schema validates at runtime, and the inferred type provides compile-time safety:

import { z } from "zod";

// Define a schema
const UserSchema = z.object({
  id: z.number(),
  name: z.string().min(1),
  email: z.string().email(),
  age: z.number().int().positive().optional(),
  role: z.enum(["admin", "user", "moderator"]),
  address: z.object({
    street: z.string(),
    city: z.string(),
    zipCode: z.string().regex(/^\d{5}(-\d{4})?$/),
  }).nullable(),
});

// Infer the TypeScript type from the schema
type User = z.infer<typeof UserSchema>;
// Equivalent to:
// interface User {
//   id: number;
//   name: string;
//   email: string;
//   age?: number | undefined;
//   role: "admin" | "user" | "moderator";
//   address: { street: string; city: string; zipCode: string } | null;
// }

// Validate data at runtime
const result = UserSchema.safeParse(jsonData);
if (result.success) {
  const user = result.data; // Fully typed as User
} else {
  console.error(result.error.issues);
}

Validating API Responses with Zod

Use Zod to validate fetch responses before using the data. This catches API contract violations at runtime:

import { z } from "zod";

const ProductSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  price: z.number().positive(),
  inStock: z.boolean(),
  categories: z.array(z.string()),
});

type Product = z.infer<typeof ProductSchema>;

async function fetchProduct(id: string): Promise<Product> {
  const response = await fetch(`/api/products/${id}`);
  const json = await response.json();

  // Validate at runtime - throws if shape is wrong
  return ProductSchema.parse(json);
}

// Safe version that does not throw
async function fetchProductSafe(id: string) {
  const response = await fetch(`/api/products/${id}`);
  const json = await response.json();
  const result = ProductSchema.safeParse(json);

  if (!result.success) {
    console.error("API response validation failed:", result.error.flatten());
    return null;
  }
  return result.data;
}

Zod Transforms

Zod can transform data during validation, converting strings to dates, trimming whitespace, or setting defaults:

const EventSchema = z.object({
  id: z.number(),
  title: z.string().trim(),           // Auto-trim whitespace
  // Transform ISO string to Date object
  startDate: z.string().transform((s) => new Date(s)),
  endDate: z.string().transform((s) => new Date(s)),
  // Default value if missing
  maxAttendees: z.number().default(100),
  // Coerce string to number (common in form data / query params)
  ticketPrice: z.coerce.number(),
});

// Input type (what the API returns)
type EventInput = z.input<typeof EventSchema>;
// { id: number; title: string; startDate: string; endDate: string; ... }

// Output type (what you get after parsing)
type Event = z.output<typeof EventSchema>;
// { id: number; title: string; startDate: Date; endDate: Date; ... }

Generic API Response Types

Most APIs wrap their data in a standard envelope with fields like success, data, error, and pagination. Define a generic type to handle this consistently:

Basic Generic Response

A generic ApiResponse<T> type lets you reuse the same wrapper for any data type:

// Generic API response wrapper
interface ApiResponse<T> {
  success: boolean;
  data: T;
  error?: {
    code: string;
    message: string;
    details?: Record<string, string[]>;
  };
  meta?: {
    requestId: string;
    timestamp: string;
  };
}

// Usage with specific types
type UserResponse = ApiResponse<User>;
type ProductListResponse = ApiResponse<Product[]>;
type DeleteResponse = ApiResponse<null>;

Paginated Response

Extend the generic pattern for paginated endpoints:

interface PaginationMeta {
  page: number;
  perPage: number;
  total: number;
  totalPages: number;
  hasNextPage: boolean;
  hasPrevPage: boolean;
}

interface PaginatedResponse<T> {
  success: boolean;
  data: T[];
  pagination: PaginationMeta;
}

// Usage
type PaginatedUsers = PaginatedResponse<User>;
type PaginatedProducts = PaginatedResponse<Product>;

// Example response shape:
// {
//   "success": true,
//   "data": [{ "id": 1, "name": "Alice" }, ...],
//   "pagination": { "page": 1, "perPage": 20, "total": 150, ... }
// }

Using Generic Response Types

Combine generic response types with fetch functions for end-to-end type safety:

// Typed API client using generic response types
class ApiClient {
  private baseUrl: string;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }

  async get<T>(path: string): Promise<ApiResponse<T>> {
    const res = await fetch(`${this.baseUrl}${path}`);
    return res.json() as Promise<ApiResponse<T>>;
  }

  async getPaginated<T>(path: string, page = 1): Promise<PaginatedResponse<T>> {
    const res = await fetch(`${this.baseUrl}${path}?page=${page}`);
    return res.json() as Promise<PaginatedResponse<T>>;
  }
}

// Usage - fully typed
const api = new ApiClient("https://api.example.com");

const userRes = await api.get<User>("/users/1");
// userRes.data is typed as User

const productsRes = await api.getPaginated<Product>("/products");
// productsRes.data is typed as Product[]
// productsRes.pagination is typed as PaginationMeta

Working with JSON APIs in TypeScript (fetch + Type Safety)

The built-in fetch API returns Response with an untyped .json() method. Here is how to add type safety:

Typed Fetch Wrapper

Create a generic fetch wrapper that validates the response and returns typed data:

// Type-safe fetch wrapper
async function fetchJson<T>(url: string, init?: RequestInit): Promise<T> {
  const response = await fetch(url, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...init?.headers,
    },
  });

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  }

  return response.json() as Promise<T>;
}

// Usage
const user = await fetchJson<User>("/api/users/1");
// user is typed as User

const products = await fetchJson<Product[]>("/api/products");
// products is typed as Product[]

// POST with typed body
const newUser = await fetchJson<User>("/api/users", {
  method: "POST",
  body: JSON.stringify({ name: "Alice", email: "alice@test.com" }),
});

Axios with TypeScript

Axios supports generics out of the box, making typed API calls straightforward:

import axios from "axios";

// Axios supports generics for response typing
const { data: user } = await axios.get<User>("/api/users/1");
// user is typed as User

const { data: products } = await axios.get<Product[]>("/api/products");
// products is typed as Product[]

// POST with typed request and response
interface CreateUserRequest {
  name: string;
  email: string;
}

const { data: created } = await axios.post<User, { data: User }, CreateUserRequest>(
  "/api/users",
  { name: "Alice", email: "alice@test.com" }
);

Type-Safe Error Handling

Define error types and use discriminated unions for robust error handling:

// Discriminated union for API results
type Result<T, E = Error> =
  | { ok: true; data: T }
  | { ok: false; error: E };

interface ApiError {
  code: string;
  message: string;
  statusCode: number;
}

async function fetchSafe<T>(url: string): Promise<Result<T, ApiError>> {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      return {
        ok: false,
        error: {
          code: "HTTP_ERROR",
          message: response.statusText,
          statusCode: response.status,
        },
      };
    }
    const data = (await response.json()) as T;
    return { ok: true, data };
  } catch (err) {
    return {
      ok: false,
      error: {
        code: "NETWORK_ERROR",
        message: err instanceof Error ? err.message : "Unknown error",
        statusCode: 0,
      },
    };
  }
}

// Usage: TypeScript narrows based on ok field
const result = await fetchSafe<User>("/api/users/1");
if (result.ok) {
  console.log(result.data.name); // Typed as User
} else {
  console.error(result.error.code); // Typed as ApiError
}

Try our free JSON to TypeScript converter

tsconfig Strict Mode and JSON Imports

Your tsconfig.json settings significantly affect how TypeScript handles JSON data. Here are the critical options:

Enable Strict Mode

Strict mode enables a set of type-checking options that catch more bugs. For JSON-heavy projects, strictNullChecks is especially important because it forces you to handle null and undefined values explicitly:

// tsconfig.json - recommended for JSON-heavy projects
{
  "compilerOptions": {
    "strict": true,
    // strict enables all of these:
    // "strictNullChecks": true,       // Forces null/undefined handling
    // "strictFunctionTypes": true,    // Stricter function type checking
    // "strictBindCallApply": true,    // Stricter bind/call/apply
    // "strictPropertyInitialization": true,
    // "noImplicitAny": true,          // No implicit any types
    // "noImplicitThis": true,
    // "alwaysStrict": true,

    // Additional recommended options
    "noUncheckedIndexedAccess": true,  // obj[key] returns T | undefined
    "noPropertyAccessFromIndexSignature": true,
    "exactOptionalPropertyTypes": true
  }
}

// With strictNullChecks, this is an error:
const user: User = await fetchJson("/api/users/1");
console.log(user.address.city);
//          ~~~~~~~~~~~~~ Error: Object is possibly 'null'

// Must handle null:
console.log(user.address?.city ?? "Unknown");

Importing JSON Files

With resolveJsonModule enabled, TypeScript can import .json files and infer their types automatically:

// tsconfig.json
{
  "compilerOptions": {
    "resolveJsonModule": true,  // Enable JSON imports
    "esModuleInterop": true     // Enable default imports
  }
}

// Now you can import JSON files with full type inference
import config from "./config.json";
// TypeScript infers: { port: number; host: string; debug: boolean }

import countries from "./countries.json";
// TypeScript infers the full shape of the JSON

// The imported values are fully typed
console.log(config.port);     // number
console.log(config.host);     // string
console.log(config.unknown);  // Error: Property 'unknown' does not exist

esModuleInterop

Enable esModuleInterop for cleaner imports of CommonJS modules (including many JSON-related libraries):

// Without esModuleInterop:
import * as fs from "fs";         // Namespace import required
const data = JSON.parse(fs.readFileSync("data.json", "utf-8"));

// With esModuleInterop:
import fs from "fs";              // Clean default import
const data = JSON.parse(fs.readFileSync("data.json", "utf-8"));

// Works for JSON-related libraries too:
import Ajv from "ajv";            // JSON Schema validator
import yaml from "js-yaml";       // YAML parser
import csvParser from "csv-parser"; // CSV parser

Best Practices for Maintaining Generated Types

Auto-generated types need ongoing maintenance to stay in sync with your APIs. Follow these best practices:

  • Automate generation: Add a script to your package.json that regenerates types from API schemas (OpenAPI/Swagger) or sample JSON.
  • Version your types: Commit generated types to version control so changes are visible in code reviews.
  • Separate generated from hand-written: Keep generated types in a types/generated/ directory and hand-written types in types/.
  • Use readonly: Mark generated types as Readonly<T> or use readonly properties to prevent accidental mutation.
  • Add JSDoc comments: Document fields with descriptions from the API documentation for better IDE tooltips.
  • Validate at boundaries: Use Zod or io-ts at API boundaries to catch runtime mismatches between expected and actual types.
  • Run CI type checks: Add tsc --noEmit to your CI pipeline to catch type errors before deployment.
  • Keep types DRY: Use TypeScript utility types (Pick, Omit, Partial, Required) to derive sub-types from base types instead of duplicating definitions.
// Example: project structure for generated types
src/
  types/
    generated/
      api-users.ts       // Auto-generated from OpenAPI spec
      api-products.ts    // Auto-generated from JSON samples
    index.ts             // Re-exports all types
    utils.ts             // Hand-written utility types

// package.json scripts
{
  "scripts": {
    "generate:types": "quicktype -s schema api/openapi.yaml -o src/types/generated/api.ts --lang ts --just-types",
    "typecheck": "tsc --noEmit",
    "prebuild": "npm run generate:types && npm run typecheck"
  }
}

// Use Readonly to prevent mutation of API data
type ReadonlyUser = Readonly<User>;
type DeepReadonlyUser = {
  readonly [K in keyof User]: User[K] extends object
    ? Readonly<User[K]>
    : User[K];
};

// Use utility types to derive sub-types
type CreateUserPayload = Omit<User, "id" | "createdAt">;
type UpdateUserPayload = Partial<Omit<User, "id">>;
type UserSummary = Pick<User, "id" | "name" | "email">;

Frequently Asked Questions

How do I convert JSON to TypeScript interfaces online?

Paste your JSON into our free online JSON to TypeScript converter tool. It automatically generates TypeScript interfaces with proper nesting, optional fields, and array types. You can also use quicktype.io or json2ts.com for similar functionality.

Should I use interface or type for JSON data in TypeScript?

Use interface for most JSON object shapes. Interfaces support declaration merging and extends, making them ideal for API response types. Use type aliases for union types (string | number), intersection types, and mapped/conditional types.

How do I handle optional and nullable fields from JSON in TypeScript?

Use the ? modifier for fields that may be absent (e.g., middleName?: string). Use union with null for fields that are always present but can be null (e.g., bio: string | null). Combine both for fields that are optional AND nullable: bio?: string | null.

What is the best tool to auto-generate TypeScript types from JSON?

quicktype is the most feature-rich tool, supporting union type inference, optional fields, and multiple output languages. For simpler needs, json-to-ts (npm package) or VS Code extensions like Paste JSON as Code work well. Our online tool provides instant browser-based conversion.

How does Zod help with JSON and TypeScript?

Zod provides runtime validation schemas that also generate TypeScript types via z.infer<typeof schema>. This means you define your data shape once and get both compile-time type checking and runtime validation. Use Zod to validate API responses, form data, and environment variables.

How do I import a JSON file in TypeScript with type safety?

Enable resolveJsonModule and esModuleInterop in your tsconfig.json. Then import JSON files directly: import data from "./data.json". TypeScript will infer the types from the JSON structure automatically. For stricter types, you can assert the import: import data from "./data.json" assert { type: "json" }.

What tsconfig settings are important for JSON-heavy TypeScript projects?

Enable strict (especially strictNullChecks), resolveJsonModule (for JSON imports), esModuleInterop (for cleaner imports), and noUncheckedIndexedAccess (for safer object property access). These settings maximize type safety when working with JSON data.

How do I create a generic API response type in TypeScript?

Define a generic interface like: interface ApiResponse<T> { success: boolean; data: T; error?: string; }. Then use it with specific types: ApiResponse<User>, ApiResponse<Product[]>. This provides consistent error handling and response structure across your entire application.

Conclusion

Generating TypeScript types from JSON is one of the highest-ROI practices in modern web development. It catches bugs at compile time, provides IDE autocomplete, and keeps your frontend in sync with backend APIs. Start with our free online tool for quick conversions, adopt quicktype for CI pipelines, and add Zod for runtime validation at API boundaries. Combined with strict tsconfig settings and generic response types, you will build applications that are both type-safe and maintainable.

Convert JSON to TypeScript Online

𝕏 Twitterin LinkedIn
Apakah ini membantu?

Tetap Update

Dapatkan tips dev mingguan dan tool baru.

Tanpa spam. Berhenti kapan saja.

Coba Alat Terkait

TSJSON to TypeScriptZDJSON to Zod Schema{ }JSON FormatterGoJSON to Go Struct

Artikel Terkait

JSON ke TypeScript: Panduan Lengkap dengan Contoh

Pelajari cara mengonversi data JSON ke interface TypeScript secara otomatis. Mencakup objek bersarang, array, field opsional, dan praktik terbaik.

TypeScript Generics Dijelaskan: Panduan Praktis dengan Contoh

Kuasai TypeScript generics dari dasar hingga pola lanjutan.

JSON ke Zod Schema: Validasi Runtime Type-Safe di TypeScript

Pelajari cara mengonversi JSON ke skema Zod untuk validasi runtime type-safe di TypeScript.

TypeScript vs JavaScript: Kapan dan Bagaimana Mengonversi

Panduan praktis kapan harus mengonversi TypeScript ke JavaScript dan sebaliknya. Strategi migrasi, tooling, dampak ukuran bundle, dan pertimbangan tim.

Panduan Validasi Zod: Skema, Transforms, Refinements, dan Integrasi tRPC

Kuasai validasi skema Zod di TypeScript: skema, transforms, refinements, dan tRPC.