TypeScript 5.3 was announced on 20 November 2023. It supports import attributes, with { type: "json" }, which replaced the older assert syntax, and narrows in more places JavaScript code reaches for: switch (true), comparisons with true and false, and instanceof against a class with a Symbol.hasInstance method.
One optimization in the release reads as if tsc stopped parsing JSDoc, which would matter a great deal for checked JavaScript. It did not stop for .js files; see below.
At a glance
| Release | TypeScript 5.3 |
|---|---|
| Released | 20 November 2023, the day of its announcement on the TypeScript blog |
| Source | TypeScript 5.3 release notes |
| Examples | Every example runs through TypeScript 5.9.3 when this site is built. |
| Previous release | TypeScript 5.2 |
| Next release | TypeScript 5.4 |
What changed for JavaScript
Import attributes
import data from "./data.json" with { type: "json" } tells the runtime what kind of module to expect. TypeScript does not check the attribute's value in 5.3 (5.4 began checking it against a global ImportAttributes type). Under nodenext, 5.7 made the attribute required for JSON.
import config from "./config.json" with { type: "json" };
console.log(`Listening on ${config.hots}:${config.port}`);error TS2339: Property 'hots' does not exist on type '{ port: number; host: string; }'.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} switch (true) narrows
Each case condition in a switch (true) now narrows inside that case, the way an if chain does.
/** @param {unknown} value */
export function describe(value) {
switch (true) {
case typeof value === "string":
return value.toUpperCase();
case Array.isArray(value):
return `${value.length} items`;
default:
return "something else";
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} instanceof and Symbol.hasInstance
A class can decide what instanceof means with a static [Symbol.hasInstance] method. When that method is a type predicate, value instanceof Point narrows value to the predicate's type, which can be a plain object type rather than the class.
/** @typedef {{ x: number, y: number }} PointLike */
export class Point {
/**
* @param {unknown} value
* @returns {value is PointLike}
*/
static [Symbol.hasInstance](value) {
return typeof value === "object" && value !== null && "x" in value && "y" in value;
}
}
/** @param {unknown} value */
export function distance(value) {
if (value instanceof Point) {
return Math.hypot(value.x, value.y);
}
return 0;
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} super cannot reach class fields
super.greet() only finds methods on the base class's prototype. If greet is a class field (an arrow function assigned in the class body), it is not there and the call throws. TypeScript 5.3 reports it (TS2855).
class Base {
greet = () => "hello";
}
export class Loud extends Base {
shout() {
return super.greet().toUpperCase();error TS2855: Class field 'greet' defined by the parent class is not accessible in the child class via super.
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": [
"*.js"
]
} tsc skips JSDoc only in .ts files
The release notes say tsc now avoids parsing JSDoc to save time. In TypeScript's source the default mode for tsc parses every JSDoc comment in JavaScript files, where JSDoc carries the types, and in .ts files only the comments that contain @see or @link. This site's tests check that behavior with TypeScript 5.9.
What did not change
resolution-mode became stable for import types, so import("pkg", { with: { "resolution-mode": "require" } }) can pick a package's CommonJS or ES module types. It is a TypeScript type syntax and the notes show it only for .ts files; this site has not tested it inside JSDoc.
Upgrade notes
The breaking changes are the DOM types and the new super check (TS2855).
Gotchas
switch (true)narrowing is per case; once a case falls through into the next, the variable has the union of both narrowings.
Sources
- TypeScript 5.3 release notes · TypeScript handbook
- Announcing TypeScript 5.3 · TypeScript blog
Last reviewed 20 October 2026.