Bugs in TypeScript

The TypeScript compiler is a software program like any other, and therefore it can have (and has had) breaking changes.

Over the past six years, TypeScript has evolved significantly, introducing new features and addressing various bugs and limitations. While many issues have been resolved, some notable bugs and challenges have emerged during this period. Here's an overview of some significant bugs and issues in TypeScript from 2019 to 2025:

Method Override Type Safety

TypeScript's structural type system allows for method overrides that can lead to type unsafety. For example, a subclass can override a method with a narrower parameter type, which can cause runtime errors when the method is called with unexpected arguments. This behavior stems from TypeScript's design choice to prioritize flexibility over strict type safety in certain scenarios. Although enabling --strictFunctionTypes can mitigate some issues, it doesn't enforce strictness in class hierarchies due to compatibility concerns with existing JavaScript patterns. (TypeScript: The Bad Parts, Inheritance vs. subtyping in TypeScript - a bug? - Stack Overflow)

Promise.all Type Inference Issues

In TypeScript 3.7, updates to type declarations for Promise.all and Promise.race introduced inference issues, leading to incorrect type resolutions in certain cases. The team initially planned to introduce the awaited type to address these problems in TypeScript 3.9. However, due to unforeseen complexities and potential breaking changes, the feature was postponed for further design considerations. (TypeScript 3.9 Improves Performance, Promises and Errors - InfoQ)

Intersection Types with Discriminant Properties

Prior to TypeScript 3.9, intersecting types with conflicting discriminant properties (e.g., kind: "circle" and kind: "square") would result in a type where the conflicting property was of type never, but the overall type was still considered valid. This could lead to confusing type errors or unexpected behavior. TypeScript 3.9 introduced stricter checks, collapsing such impossible intersections to never, thereby preventing the creation of invalid types. (Breaking Changes · microsoft/TypeScript Wiki · GitHub)

Optional Chaining and Non-Null Assertion Confusion

The combination of optional chaining (?.) and non-null assertions (!) led to unintuitive behavior in earlier versions of TypeScript. For instance, the expression foo?.bar!.baz was previously interpreted in a way that could cause runtime errors if foo was undefined. TypeScript 3.9 addressed this by changing the parsing logic to align with developer expectations, treating the expression as foo?.bar.baz. (Breaking Changes · microsoft/TypeScript Wiki · GitHub)

Stricter Checks on Type Parameters

In TypeScript 4.8, under strictNullChecks, the compiler introduced stricter checks for unconstrained type parameters. Previously, type parameters were considered assignable to {} or object, even if they could be null or undefined. The update enforced that such assignments are errors unless the type parameter is explicitly constrained, enhancing type safety but potentially causing issues in existing codebases. (Breaking Changes · microsoft/TypeScript Wiki · GitHub)

Challenges with Third-Party Type Definitions

TypeScript developers often rely on community-maintained type definitions from repositories like DefinitelyTyped. However, discrepancies between these type definitions and the actual behavior of third-party libraries can lead to type errors or unexpected behavior. Additionally, version mismatches between the type definitions and the corresponding libraries can introduce further complications. (Four years of Typescript: a retrospective - Jon Bevan's Writing)

Was this page helpful?