TypeScript Beautifier & Formatter

Paste a .ts or .tsx file and get it back printed by Prettier, running inside your browser tab. Generic arrows, decorators, enums, mapped types and JSX all survive, because the parser reads TypeScript instead of guessing from JavaScript rules. Pick your indent, quotes and trailing comma style, then copy the matching .prettierrc into the repo so the whole team prints the same way.

Source
0 lines, 0 characters
Formatted
Nothing formatted yet
Matching .prettierrc

Why a JavaScript beautifier breaks TypeScript

Most online TypeScript formatters run js-beautify underneath. That library tokenizes JavaScript, and TypeScript reuses characters JavaScript already assigned a meaning. The angle brackets in Map<string, number> look like less-than and greater-than to a JavaScript tokenizer, so they get padded like comparison operators. Worse, an arrow function with a return type ends in > followed by =>, and the tokenizer reads >= as a single operator. Here is the same line through both:

js-beautify 1.14
const load = async (id: number): Promise < User | null >= > {const r = await fetch(`/api/${id}`);return r.ok ? r.json() : null};

Does not compile. >= > is no longer an arrow.

This page (Prettier 3.3.3)
const load = async (id: number): Promise<User | null> => {const r = await fetch(`/api/${id}`);return r.ok ? r.json() : null;};

Same code, parsed as TypeScript, printed back valid.

The earlier version of this page shipped the js-beautify path. Testing generics, optional properties and mapped types produced output with opts ? : {} and [K in keyof T] - ? :, both of which fail tsc. So the page now runs Prettier's own TypeScript parser and printer in the browser. The trade is about 1.2 MB of script on first visit, cached after, against output you do not have to repair by hand.

Construct by construct, what comes back

Every row below was pasted through this page at the default settings. The left column is the compressed input, the right is what the printer returns.

ConstructInputFormatted
Nested genericstype Deep=Promise<Record<string,Array<Array<number>>>>;type Deep = Promise<Record<string, Array<Array<number>>>>;
Decorators@Component({selector:'app-root'})export class AppComponent{@Input() name!:string;}@Component({ selector: "app-root" })
export class AppComponent {
  @Input() name!: string;
}
Enumsenum Status{Active='active',Paused='paused'}One member per line, trailing comma on the last member when trailing commas are set to All or ES5.
Optional propertyopts?:{pad?:number;upper?:boolean}opts?: { pad?: number; upper?: boolean }
Mapped type with modifiertype Keys<T>={[K in keyof T]-?:T[K]};type Keys<T> = { [K in keyof T]-?: T[K] };
satisfiesconst cfg={port:8080}satisfies Config;const cfg = { port: 8080 } satisfies Config;
Type-only importsimport {type Role,fetchRoles} from './roles';import { type Role, fetchRoles } from "./roles";
Long unionTen string literals joined by | on one lineBreaks to one member per line with a leading | once the line passes print width.
TSXconst App=()=><div>{items.map(i=><Item key={i.id} {...i}/>)}</div>;Wraps the JSX in parentheses, one element per line, and adds parens around the arrow parameter.
Non-null and nullishconst len=maybe!.length;const x=obj?.a?.b??0;const len = maybe!.length;
const x = obj?.a?.b ?? 0;

Two behaviors surprise people the first time. Enum members and object literals that fit within print width stay on one line only if they were written on one line and contain no newline after the opening brace. Put a line break after { and the printer keeps the object expanded regardless of width. And angle bracket assertions like <number>value format fine here because the page uses the plain TypeScript parser. In a real .tsx file that syntax is a JSX tag and tsc rejects it, so use value as number in React code.

The settings panel is a .prettierrc editor

Each control above maps one to one onto a Prettier option, and the config box under the output rewrites itself as you change them. The defaults on this page are Prettier's own defaults: two space indent, 80 column print width, double quotes, semicolons on, trailing commas everywhere including function parameters. Teams coming from older codebases most often flip three of them:

Copy the config, save it as .prettierrc at the repo root, and npx prettier --write "src/**/*.ts" produces byte-identical output to this page, as long as the repo pins Prettier 3.3. A newer major or minor release can print a handful of constructs differently.

A syntax error stops the format instead of guessing

Because the input goes through a real parser, an invalid file does not get a best-effort reflow. It returns the parser's message and position, and the source pane scrolls to that line. Paste const x: = 5; and the panel reports Type expected (1:10). This is stricter than js-beautify, which reindents anything you hand it, and it is also the reason the formatted pane never contains code that the compiler would reject on syntax alone.

The parser checks syntax, not types. Assigning a string to a variable declared number formats without complaint. Missing imports, unknown identifiers and wrong argument counts all pass. Run tsc --noEmit for those.

Where this page stops

Moving the same rules into the repo

An online formatter fixes one file. The repo needs the same output on every commit, from every editor. Three steps get there:

  1. Save the config box above as .prettierrc and add Prettier as a dev dependency: npm i -D prettier@3.3.3.
  2. Turn on format on save. VS Code needs the Prettier extension and "editor.defaultFormatter": "esbenp.prettier-vscode" in .vscode/settings.json. WebStorm ships Prettier support under Languages, then JavaScript, then Prettier.
  3. Add prettier --check . to CI so an unformatted file fails the build rather than reaching review. A pre-commit hook through lint-staged catches it earlier still.

Once that is in place this page is for the cases outside the repo: a snippet from a chat, a file from a client without a config, or checking what a setting change would do before you commit it.

TypeScript formatting questions

Does this run the real Prettier or an imitation?

The real one. The page loads the standalone build of Prettier 3.3.3 with its TypeScript and estree plugins from a CDN and calls prettier.format in your browser. Output matches the command line tool at the same version and options.

Can I format .tsx files with React components?

Yes. The TypeScript parser reads JSX, so components, fragments, spread props and conditional rendering all format. The one difference from plain .ts is that angle bracket type assertions are not valid in TSX, so write value as Type in React files.

Why did the formatter change my single quotes to double quotes?

Double quotes are the Prettier default. Switch the Quotes control to Single. Strings that contain a single quote character still print with double quotes so nothing needs escaping.

Why does my object stay on multiple lines when it would fit on one?

Prettier keeps an object expanded when the original has a newline between the opening brace and the first key. This is deliberate so you can choose the shape. Remove that first line break and the printer collapses the object if it fits within print width.

Does it sort or remove unused imports?

No. Prettier prints imports in the order written and never removes code. Import sorting needs a separate plugin such as prettier-plugin-organize-imports, which this page does not load. Run that through the repo toolchain instead.

Is my code uploaded to a server?

No. Parsing and printing happen inside the browser tab. Nothing is posted to toolexe.com or any third party, which is why there is no share link. Close the tab and the code is gone.

What happens with a syntax error in the middle of the file?

The format stops and the error panel shows the parser message with line and column. The source pane scrolls to that line. Nothing partial is written to the output pane, so you never copy a half-formatted file.