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.
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 => instead of the greater‑than‑or‑equal operator >= :
<code>if (x => 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 < :
<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 => 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.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.