Home CSV to TypeScript

CSV to TypeScript interface generator

Paste a CSV file and get the interface describing one parsed row. Column types come from the values, not from the header.

The type depends on how you parse, not on the file

A CSV file has no types. Every cell is text, so the interface that describes a parsed row depends entirely on what your parser did — and this is the mismatch that produces a type which is correct on this page and wrong in your code.

With type detection on, the interface describes rows from a parser that converts values: signups: number, active: boolean. That matches csv-parse with cast: true, Papa Parse with dynamicTyping: true, or pandas.

With detection off, every field is string — which is what a plain split(','), a default Papa Parse, or csv-parse without casting actually gives you. If your runtime types disagree with your compile-time types, this switch is usually the reason.

The leading-zero rule applies here too

Even with detection on, 01234 stays a string, because a value is converted only when writing the number back out reproduces the original text exactly. So a zip code column is typed string while a quantity column is typed number — which is right, and is what a naive cast gets wrong in both directions.

One interface, not a nested tree

A CSV row is flat, so the output is a single interface with one property per column. A column named user.name becomes a quoted key 'user.name' rather than a nested object: dots in a CSV header are part of the name, and reading them as structure would reshape any file whose columns happen to contain a full stop.

If you want the nested version, convert to JSON first with the CSV to JSON converter and paste that into the JSON generator.

Empty cells

With detection on an empty cell is null, so a column that is empty anywhere is typed string | null. That is usually what you want and occasionally not — if your parser produces '' for an empty cell rather than null, turn detection off and the whole row is strings.

Paste enough rows

Types come from the values present, so a five-row paste describes those five rows. The column that is empty only on row 900, or numeric until someone typed "N/A", will not show up. Paste the header plus a genuinely representative sample — including the rows you know are awkward.

Common questions

Why is my number column typed as string?

Either type detection is off, or the values are not plain numbers — a leading zero, a trailing zero after a decimal point, thousands separators or a currency symbol all keep a column as text, deliberately.

Which parser does the output match?

With type detection on it matches a parser that casts values: csv-parse with cast: true, Papa Parse with dynamicTyping: true, or pandas. With detection off it matches a plain split or a default Papa Parse, where every field is a string.

How do I get nested interfaces from a CSV?

You cannot directly, because a CSV row is flat. Convert to JSON first, then paste that into the JSON to TypeScript generator.

What happens to a column with empty cells?

With type detection on an empty cell becomes null, so the column is typed as a union with null. With detection off it stays an empty string and the column is just string.

How many rows should I paste?

Enough to be representative. Types are inferred from the values present, so a column that is only awkward on row 900 will not be reflected in a five-row sample.

Last updated