Rohan Yeole - Homepage Rohan Yeole

JavaScript vs TypeScript When Hiring: I Now Require TypeScript — Here's Exactly Why

May 22, 20261 min read

I require TypeScript for any production JavaScript project. This is not a stylistic preference — it is based on a specific class of bugs that TypeScript prevents, and on what TypeScript proficiency signals about how a developer thinks. Here is the full reasoning.

What TypeScript Actually Does

TypeScript is a strict superset of JavaScript that adds static typing. The TypeScript compiler (tsc) reads your .ts files, performs type checking, and emits plain .js files. At runtime, types are completely erased — there are no TypeScript types in the executed code. The type system exists entirely at development time.

This is the most important thing to understand: TypeScript does not make your runtime faster, does not change the JavaScript semantics, and does not prevent all bugs. It prevents one specific category: type mismatches that are only visible at runtime because the type is wrong but the code executes without error until it accesses a property that doesn't exist.

function processOrder(order: { id: number; total: number; currency: string }) {
    return `Order ${order.id}: ${order.currency}${order.total}`;
}

// TypeScript catches this at compile time:
processOrder({ id: 1, total: 99.99 }); // Error: missing 'currency'

// JavaScript catches this at runtime (or not at all, producing 'Order 1: undefined99.99'):
processOrder({ id: 1, total: 99.99 });

In a codebase with hundreds of functions and dozens of API calls, the TypeScript compiler is a pre-execution audit that catches every mismatched call signature, every missing required field, and every property access on a potentially null value — before the code runs.

The Class of Bugs TypeScript Prevents

Missing required properties. The example above. In a JavaScript codebase, the function executes and produces wrong output; the bug surfaces as a display issue or a downstream calculation error, not as an exception. TypeScript catches it immediately.

Null and undefined dereference. With strictNullChecks: true, TypeScript tracks which values can be null or undefined. user.name on a value typed as User | null is a compile error — you must handle the null case explicitly before accessing properties. The alternative: a runtime TypeError: Cannot read properties of null that surfaces when a specific user has a null profile or a specific edge case reaches the code path.

Function signature drift. In large codebases, functions are refactored over time. A function that accepted (userId: number) gets a new signature (userId: number, options?: Options). In JavaScript, calling it with old arguments silently ignores the missing options. In TypeScript, every call site gets a compile error immediately when the signature changes — which means the refactor is either complete (all callers updated) or it fails to compile, not silently wrong.

API response type mismatches. When a backend API changes a field name or type, a JavaScript frontend finds out when a user triggers the code path that accesses the changed field. A TypeScript frontend with typed API responses finds out when someone runs the compiler — which, in a CI pipeline, is every commit.

What TypeScript Proficiency Signals

The specific indicator is not whether a developer adds TypeScript to projects — it is whether they use it correctly. Adding TypeScript to a project and then suppressing every error with // @ts-ignore or using any everywhere is not TypeScript proficiency; it is TypeScript on paper.

Real TypeScript proficiency means designing types from the contract outward: - Defining the shape of API responses as interfaces before writing the component - Using discriminated unions for state machines: type RequestState = { status: 'idle' } | { status: 'loading' } | { status: 'success'; data: User } | { status: 'error'; error: string } - Making invalid states unrepresentable at the type level, so the code cannot be in a state that doesn't make sense - Writing generic utilities: <T>(items: T[], keyFn: (item: T) => string) => Record<string, T>

A developer who writes types this way is thinking about the interface between code units before writing the implementation. That design discipline produces code that is easier to understand, easier to test, and harder to misuse. TypeScript proficiency is a proxy for design thinking.

How to Evaluate TypeScript Proficiency in an Interview

Ask them to type a function from scratch. Give a verbal description: "A function that takes a list of users and a key, and returns the user with that key, or undefined if not found." A proficient answer: function findUser(users: User[], id: number): User | undefined. A weak answer: function findUser(users: any[], id: any): any.

Ask about any vs unknown. Both accept any value, but unknown forces you to do type narrowing before using the value — you can't call methods on unknown without first checking the type. any disables type checking entirely. Using unknown for truly unknown inputs (API responses, user input) is correct; using any for the same is a type system bypass.

Ask what strict: true in tsconfig.json enables. Expected: strictNullChecks (null and undefined are not assignable to every type), noImplicitAny (implicit any inference is an error), and several others. A developer who has configured TypeScript for a project has thought about these settings. A developer who has only used TypeScript on pre-configured projects may not know they exist.

Look at their GitHub for any density. Search their public repos for as any and // @ts-ignore. A senior TypeScript developer has near-zero of these in production code (excluding very specific justified cases). A developer who uses as any to silence every type error has not embraced the type system.

The Practical Hiring Implication

Requiring TypeScript narrows your candidate pool by roughly 20–30% — not all JavaScript developers are TypeScript-proficient. The remaining pool is, on average, more senior and produces better code.

For production applications: narrow the pool and require TypeScript. The bugs you avoid are more expensive than the extended search time.

For very short contracts with a clear bounded scope: the tradeoff is closer to break-even. A 40-hour fixed-scope project may not require TypeScript if the scope is genuinely bounded and the developer is highly experienced.

Frequently Asked Questions

Is TypeScript harder to write than JavaScript? For developers not familiar with type systems: yes, for the first 2–4 weeks. For developers with TypeScript experience: no — and codebases with good types are faster to work in because the IDE provides complete autocomplete and catches errors immediately. The upfront cost is real and the long-term payoff is real.

Does TypeScript slow down development? For developers new to TypeScript: slightly, at the start. For experienced TypeScript developers: no. TypeScript's compiler errors surface bugs that would otherwise be found in code review, testing, or production — moving the discovery earlier doesn't add work, it redistributes it to a cheaper discovery point.

What TypeScript configuration should I require? At minimum: "strict": true in tsconfig.json. This enables the full suite of strict checks, including strictNullChecks and noImplicitAny. Without strict: true, TypeScript with default settings provides significantly weaker guarantees.

Chat with me on WhatsApp