WW Tools
All references

JSON to TypeScript, Go, and Zod Type Mapping

JSON has six value kinds and no type system of its own, so every generator has to decide what each one becomes in the target language. These tables are the mapping the JSON to TypeScript, Go & Zod converter uses. They also cover the cases one sample cannot settle: an empty array, a key that was only ever null, an integer past the JavaScript safe-integer limit.

JSON value to target type

JSON valueTypeScriptGoZod
"hello"stringstringz.string()
42 (integral)numberint64z.number()
1.5 (fractional)numberfloat64z.number()
true / falsebooleanboolz.boolean()
nullnullanyz.null()
{ ... }A named interface or type aliasA named structA named z.object schema
[1, 2, 3]number[][]int64z.array(z.number())
[1, "a"](string | number)[][]anyz.array(z.union([z.string(), z.number()]))
[] (empty in every sample)unknown[][]anyz.array(z.unknown())
{} (no keys)An interface with no membersA struct with no fieldsz.object({})
9007199254740993 (past MAX_SAFE_INTEGER)number, already roundedint64, already roundedz.number(), already rounded

JSON.parse rounds an integer larger than Number.MAX_SAFE_INTEGER before any converter sees it, so the exact value is gone by then. Keep such ids as strings in the payload if you need them intact.

Optional versus nullable

What the samples showedTypeScriptGoZod
Key in every sample, never nullfield: TField T `json:"field"`z.T()
Key missing from some samplesfield?: TField T `json:"field,omitempty"`z.T().optional()
Key always present, sometimes nullfield: T | nullField *T `json:"field"`z.T().nullable()
Key missing somewhere AND null somewherefield?: T | nullField *T `json:"field,omitempty"`z.T().nullish()

An absent key and a null value are different runtime facts: "key" in obj is false for the first and true for the second. The converter keeps them apart by default, and can collapse both into one style if your codebase prefers that.

Type alias versus interface

Capabilityinterfacetype
Describe an object shapeYesYes
Declaration merging (two declarations combine)YesNo
Union types (A | B)NoYes
Mapped and conditional typesNoYes
Combine with another shapeextendsIntersection (&)
Editor tooltip renderingShows the nameOften expands the members

Frequently asked questions

What is the difference between an optional key and a nullable key?

An optional key may be absent from the object entirely, so a lookup returns undefined and Object.keys does not list it. A nullable key is present, with the value null. TypeScript writes the first as field?: T and the second as field: T | null. Go writes the first as omitempty in the json tag and the second as a pointer field. Zod writes .optional() and .nullable(), plus .nullish() for a key that is both.

Why did my array of objects become one type instead of two?

Because the objects are merged rather than compared. Every element contributes its keys to one shape. Keys that only some elements had are marked optional, and a key whose value differed in kind becomes a union. That is why a list of 200 records produces one named type instead of 200 near-identical ones.

Why does Go get int64 when TypeScript gets number?

JavaScript has one numeric type, so every JSON number is a number in TypeScript. Go separates integers from floating point: an integral value maps to int64, and a value with a fractional part maps to float64. If a field is integral in one sample and fractional in another, the merged type widens to float64.

Use the tool