Paste TypeScript on the left and click "Convert" — we will turn it into XMLPaste TypeScript code

What this tool does

If you have ever had to write an XML payload that mirrors a TypeScript interface — for a SOAP client, an RSS generator, a config file, or a contract test — you know how much scaffolding is involved. The browser gives you XMLSerializer for an existing DOM, not for a typed object. Paste the TypeScript here and you get back well-formed XML in one pass. A single interface, a type alias, a typed const, or something deeply nested — same result.

The converter reads the types, not just the values. interface Order { ... } + const order: Order = { ... } produces an <Order> root with every field from the interface. Optional fields (field?: T) that are missing from the literal become empty elements so the output matches the declared shape. readonly is ignored for output purposes. Enums emit their value (string enums emit the string, numeric enums emit the number). Union types emit whatever the actual literal contains. Generics are resolved by the concrete instantiation.

Nested interfaces and arrays expand as nested elements. An items: OrderItem[] field becomes <items><OrderItem/><OrderItem/></items>, using the element type name for each child. Record and Map types become containers of <Entry><Key/><Value/></Entry>. Date, bigint, and null are handled by type — ISO-8601 for dates, decimal string for bigint, empty elements for null. If you paste multiple type definitions plus one typed constant, the constant is what gets serialized and the interfaces are used as the schema.

How to use it

Three steps. Works the same whether you paste a short interface or a whole types.ts.

1

Paste your TypeScript (or try the sample)

Drop your TS into the left editor as-is. An interface, a type alias, a typed const, or a whole module — all fine. Click Load Sample to see a realistic Order / OrderItem / Address example with nested objects.

Keep the type annotations in — that is what the parser uses to decide output element names and types. Leave import and export statements too; they are ignored automatically.

2

Hit Convert

Click the green Convert button. The tool reads the types, resolves the values, and emits the XML in one pass. A short loading indicator shows while it runs.

3

Copy the XML

The right panel fills with indented, well-formed XML that any standards-compliant XML parser will accept. Copy it straight into your SOAP request, RSS template, config file, or test fixture.

When this actually comes in handy

SOAP / XML API clients

You have a TypeScript interface for a SOAP request body and need the XML skeleton to send over <code>fetch</code>. Paste the interface plus a typed example, copy the XML, paste it into your request.

XSD-driven contracts

Generate XML examples from your TS types for documentation that sits alongside an <a href="https://www.w3.org/TR/xmlschema-1/" target="_blank" rel="noopener">XSD</a>. Keeps your examples in sync with the types, which are in sync with the schema.

Starting config files

A Settings interface with 40 fields becomes a ready-to-edit XML template for any XML-based config store. No handwritten element building, no typos, no forgotten fields.

Mock data for integration tests

Convert the typed fixtures from your Vitest or Jest setup into XML seed data for legacy systems and mock servers that still consume XML.

Common questions

Does it use the types or just the object values?

Both. The types decide element names, ordering, and which fields must be present (optional fields become empty elements if missing). The actual value literal supplies the data. If you paste only a const with no interface, the tool uses the literal directly — still works, just without the type-driven safety.

How does it handle optional fields and union types?

Optional fields (field?: T) that are missing from the value are written as empty elements (<field/>) to keep the output shape consistent. Union types (string | number) emit whatever the literal actually contains. Discriminated unions work too — the discriminant becomes an attribute or child element depending on its name.

What about Date, bigint, and enum?

Date values come out as ISO-8601 strings. bigint is emitted as its decimal string (no n suffix). String enums emit the string value, numeric enums emit the number. null becomes an empty element, undefined drops the element entirely unless the field is declared required.

Does it handle generics, Record, and Map?

Yes. Generic interfaces are resolved by their concrete instantiation — Response<Order> with a real Order value emits the concrete shape. Record<K, V> becomes a container of named elements, one per key. Map becomes a container of <Entry><Key/><Value/></Entry> pairs. Tuple types emit one element per slot.

Can I paste a whole types.ts file?

Yes. Paste as much TypeScript as you like. Import statements are ignored, type-only declarations define the shape, and the first exported or top-level typed const is what gets serialized. If there are multiple candidates, the one with the most resolvable fields is picked.

Is my code stored?

Your code is sent to the backend for conversion and is not persisted — we do not log the payload. As always with online tools, if the code is genuinely sensitive, look it over before pasting.

Other tools you may need

TypeScript to XML is one piece of the puzzle. These pair well with it: