Frontend Development 23 min read

What’s New in TypeScript 5.6 Beta? Explore the Latest Compiler Features

Microsoft released TypeScript 5.6 Beta on July 26 2024, introducing stricter null‑and‑truthiness checks, iterator helper methods, built‑in iterator types, arbitrary module identifiers, new compiler flags like --noUncheckedSideEffectImports and --noCheck, region‑priority diagnostics, improved project ownership detection, and several notable behavior changes across the language and tooling.

Code Mala Tang
Code Mala Tang
Code Mala Tang
What’s New in TypeScript 5.6 Beta? Explore the Latest Compiler Features
Original article: https://devblogs.microsoft.com/typescript/announcing-typescript-5-6-beta/

Microsoft released the TypeScript 5.6 Beta on July 26 2024.

<code>npm install -D typescript@beta</code>

Here is a quick overview of some of the new features in TypeScript 5.6:

Prohibit null‑value and truthiness checks

Iterator helper methods

Strict built‑in iterator checking (with --strictBuiltinIteratorReturn )

Support for arbitrary module identifiers

--noUncheckedSideEffectImports option

--noCheck option

Allow --build with intermediate errors

Region‑priority diagnostics in the editor

Search parent configuration files to determine project ownership

Significant behavior changes

Prohibit Null‑Value and Truthiness Checks

You might have written a regular expression but forgotten to call .test(...) :

<code>if (/0x[0-9a-f]/) {
    // Oops! This block always runs.
    // ...
}</code>

Or you may have mistakenly written an arrow function =&gt; instead of the greater‑than‑or‑equal operator &gt;= :

<code>if (x =&gt; 0) {
    // Oops! This block always runs.
    // ...
}</code>

Or you might have used the nullish coalescing operator ?? as a default value but confused it with the comparison operator &lt; :

<code>function isValid(value: string | number, options: any, strictness: "strict" | "loose") {
    if (strictness === "loose") {
        value = +value;
    }
    return value < options.max ?? 100; // Interpreted as (value < options.max) ?? 100
}</code>

These examples are syntactically valid JavaScript, but they do not match the author's intent. Previously TypeScript silently accepted them, but the new checks now emit errors when the compiler can determine that a truthiness or null‑value check will always evaluate a certain way.

<code>if (/0x[0-9a-f]/) {
    // ~~~~~~~~~~~~~~
    // Error: This expression is always true.
}

if (x =&gt; 0) {
    // ~~~~~~
    // Error: This expression is always true.
}

// ... other error messages</code>

Enabling ESLint's no-constant-binary-expression rule yields similar results, but the built‑in TypeScript checks provide additional coverage.

Note that some always‑true or always‑null expressions such as true , false , 0 , and 1 remain allowed because they are useful in loops and debugging code.

Iterator Helper Methods

JavaScript defines the concepts of iterables (objects with a [Symbol.iterator]() method) and iterators (objects with a next() method). TypeScript now models these with the Iterable and Iterator types, allowing you to use methods like map , filter , reduce , and take directly on iterators.

<code>function* positiveIntegers() {
    let i = 1;
    while (true) {
        yield i;
        i++;
    }
}

const evenNumbers = positiveIntegers().map(x => x * 2);
// Output: 2, 4, 6, 8, 10
for (const value of evenNumbers.take(5)) {
    console.log(value);
}</code>

Similar helper methods are available on Map , Set , and other built‑in collections.

Strict Built‑in Iterator Checking ( --strictBuiltinIteratorReturn )

The compiler now models the result of Iterator.next() with the IteratorResult type, distinguishing between IteratorYieldResult and IteratorReturnResult . With the new BuiltinIterator and BuiltinIteratorReturn types, TypeScript can enforce safer iterator implementations.

<code>function* abc123() {
    yield "a";
    yield "b";
    yield "c";
    return 123;
}
const iter = abc123();
iter.next(); // { value: "a", done: false }
// ...
iter.next(); // { value: 123, done: true }
</code>

When --strictBuiltinIteratorReturn is enabled, returning undefined from an iterator is flagged, and missing override modifiers on computed properties are reported.

Support for Arbitrary Module Identifiers

JavaScript allows exporting bindings with string literal names that are not valid identifiers, e.g.:

<code>const banana = "🍌";
export { banana as "🍌" };

import { "🍌" as banana } from "./foo";
function eat(food: string) {
    console.log("Eating", food);
}
eat(banana);
</code>

TypeScript 5.6 now permits such arbitrary module identifiers, which is useful for interop with other languages and for tools like esbuild.

--noUncheckedSideEffectImports Option

Side‑effect imports (e.g., import "some-module"; ) previously caused the compiler to load and type‑check the module if it existed, silently ignoring missing files. The new flag makes missing side‑effect imports an error, helping catch typos in imports of CSS, assets, or other resources.

<code>import "oops-this-module-does-not-exist";
// Error: Cannot find module 'oops-this-module-does-not-exist' or its corresponding type declarations.
</code>

Projects can declare ambient modules for assets (e.g., declare module "*.css" {} ) to silence the error where appropriate.

--noCheck Option

This flag skips type checking of all input files, allowing faster transpilation. It is useful when separating JavaScript emission from type checking, or when generating declaration files with --isolatedDeclarations .

Improved --build Behavior

The build mode now continues compiling dependent projects even if intermediate projects have errors, always emitting .tsbuildinfo files regardless of the --incremental setting.

Region‑Priority Diagnostics in the Editor

The language service can now return diagnostics for the visible region of a file first, dramatically reducing latency for large files (e.g., 143 ms for region diagnostics vs. 3330 ms for full diagnostics).

Search Parent Configuration Files to Determine Project Ownership

When locating a tsconfig.json for a file, the compiler now continues searching up the directory tree after finding a configuration file, allowing more flexible project structures with multiple configs.

Notable Behavior Changes

lib.d.ts updates may affect DOM typings.

.tsbuildinfo is always written during --build .

Node‑modules now respect file extensions and package.json"type" fields when resolving modules.

Computed properties with override are now correctly checked.

Correctly Check override on Computed Properties

Previously, computed properties marked with override were not validated against base class members. TypeScript 5.6 now reports errors when an override modifier is used on a property that does not exist in the base class, and when noImplicitOverride is enabled but the modifier is missing.

<code>const foo = Symbol("foo");
const bar = Symbol("bar");

class Base {
    [bar]() {}
}

class Derived extends Base {
    override [foo]() {}
    // ~~~~~~
    // Error: This member cannot have an 'override' modifier because it does not exist in base class 'Base'.

    [bar]() {}
    // ~~~~~~
    // Error with noImplicitOverride: This member must have an 'override' modifier because it overrides a member in base class 'Base'.
}
</code>

For more details, see the official TypeScript 5.6 release notes.

TypeScriptJavaScriptCompilerIteratorsDiagnosticsBetaModules
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.