What we use TypeScript for
Everywhere front-end code amounts to more than a few lines of interaction. In Astro projects we write components and data access with types. In Shopware 6 themes we type our own plugins and the handover between Twig and JavaScript. For custom interfaces — configurators, editorial tools, dashboards behind a login — TypeScript is a precondition for us, not a flourish. Small scripts inside a WordPress page often stay plain JavaScript.
TypeScript has its greatest effect at interfaces. When a REST or GraphQL API returns data, types describe the response, and the compiler speaks up when the back end renames a field or makes it optional. Those types can be generated from OpenAPI descriptions instead of typed out by hand. Errors of this kind otherwise surface in the browser — in the worst case at the customer's end, on a Friday afternoon.
How we work with it
We start strict, because retrofitting is more expensive. strict is switched on, any needs a reason, and we check the types shipped with third-party packages rather than believing them. The compiler runs in continuous integration, not only on the developer's machine — otherwise the first red error eventually gets ignored. For existing projects the route is reversed: migrate step by step, file by file, starting where changes happen most often.
We build with Vite and check with ESLint and the TypeScript compiler separately — bundlers transpile, they do not check. We keep types close to the data: one source for the shapes that back end and front end share, rather than two definitions that drift apart. And we do not write types that only impress the compiler. A generic monster nobody reads is not documentation, it is a second language inside the project.
Limits: what TypeScript does not do
TypeScript checks what the compiler can see, and it only sees your code. Everything that arrives at runtime from outside is a claim to begin with: API responses, form data, values from local storage, content from the CMS. Treat them as typed without checking and you have safety on paper. At those edges we validate at runtime, for instance with Zod. A type error nobody verifies is a runtime error on a delay.
Not every project needs TypeScript. For a few lines on a landing page, the effort for build, configuration and type definitions is out of all proportion; there we write modern JavaScript and leave it at that. TypeScript also does not replace tests. It checks shapes, not behaviour — whether a price calculation returns the right number is beyond the compiler. And where types only pass with casts, the data model is usually the thing that is wrong.