Three mistakes when converting JSON to types
A copied API body feels like it should turn into types with nothing left over. The converter will draft something. The draft follows a few rules that are easy to miss if you only look at the first row and the green status.
Mistake 1: expecting every row to shape the interface
Take two objects that do not match:
[{"id":1,"name":"Ada"},{"id":2,"email":"linus@example.com"}]
The TypeScript result is only the first object:
export interface Root {
id: number;
name: string;
}
The PHP DTO matches that shape: public int $id and public string $name, each assigned with ?? null. email is not on the class. The Laravel array still contains both rows, so the second row's email survives there. CSV is the format that notices the extra key. Its header is id,name,email, the first data row ends with an empty cell, and the second row leaves name empty:
id,name,email
1,Ada,
2,,linus@example.com
If you need email on the interface, put it on the object you convert, or add the property after the draft.
Mistake 2: asking CSV for a column per nested field
A nested object stays one cell. For the two-person sample whose meta holds active, the CSV the converter writes is:
id,name,role,meta
1,Ada,engineer,"{""active"":true}"
2,Linus,founder,"{""active"":false}"
There is no active column. An array at the top level is the same kind of cell: {"id":1,"tags":[]} puts [] under tags. Laravel, by contrast, nests meta as a PHP array, and TypeScript gives it a second interface, Meta, with active: boolean. The PHP DTO does neither of those. It types meta as array and copies the value through.
Mistake 3: shipping the class or the interface without reading it
The PHP class is always named DataTransferObject. The constructor writes $this->id = $data['id'] ?? null against public int $id. A missing key becomes null in that line. Nested objects do not become child classes.
A key such as first-name is quoted in the Laravel array, which is fine for PHP array syntax. The TypeScript line is first-name: string; and the PHP property is public string $first-name;. Both use the key as a bare name.
Child interfaces drop one trailing s. A property items whose first element is an object is typed Item[]. A property status with an object element is typed Statu[], and the interface is export interface Statu.
Invalid JSON does not produce a half result. The output is cleared. { shows Expected property name or '}' in JSON at position 1 (line 1 column 2). A trailing comma in {"a":1,} shows Expected double-quoted property name in JSON at position 7 (line 1 column 8). Empty input shows Unexpected end of JSON input. Fix the text in the formatter at https://kepttools.com/json-formatter, then convert again at https://kepttools.com/json-converter.
The empty-array cases, the null fields, and the rest of the FAQ are in the guide: https://kepttools.com/guides/json-to-typescript-php-dto-laravel
Comments
Join the discussionNo comments yet. Be the first to comment.

