Skip to content

fix: add support for node 22/24, drop node 16/21#2580

Open
jasoniangreen wants to merge 3 commits intomasterfrom
fix/node-22
Open

fix: add support for node 22/24, drop node 16/21#2580
jasoniangreen wants to merge 3 commits intomasterfrom
fix/node-22

Conversation

@jasoniangreen
Copy link
Collaborator

@jasoniangreen jasoniangreen commented Feb 8, 2026

Adds support for node 22/24 and drops node 16/21. I did consider if the change to support node 22 should be in ajv config around the esModuleInterop but that would change the actual output of the lib whereas this fix only changes test files.

Summary

Node 22 introduced native TypeScript type stripping. When ts-node is registered via -r ts-node/register, Node 22's native handler intercepts .ts files first and runs in "strip-only" mode, which cannot handle import = require() syntax — a TypeScript-specific construct. This causes ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX on all test runs.

This PR:

  • Converts all import X = require("Y")import * as X from "Y" in 17 spec files (23 occurrences)
  • Updates the CI matrix from [16.x, 18.x, 20.x, 21.x] to [18.x, 20.x, 22.x, 24.x]
  • Updates README to reflect supported Node version range (18.x - current)
  • Removes dead if-node-version 12 from test-all script and its dependency

Why drop Node 16 and 21?

  • Node 16: EOL since September 2023
  • Node 21: EOL since June 2024 (odd-numbered releases are short-lived)

Why import * as instead of import X from?

esModuleInterop is not enabled in the base tsconfig (@ajv-validator/config), so import X from "Y" would fail for CommonJS modules. import * as X from "Y" is semantically equivalent to import X = require("Y") when compiling to CommonJS and works across all Node versions without experimental flags.

Alternatives considered

  • NODE_OPTIONS=--no-experimental-strip-types: Would suppress Node's native TS handling, but depends on the flag continuing to exist
  • NODE_OPTIONS=--experimental-transform-types: Would enable full TS syntax support in Node, but relies on an experimental flag with unclear ts-node interaction

Refactoring the imports is the safest, most future-proof approach — zero production code changes, mechanical transformation only in test files.

@jasoniangreen jasoniangreen changed the title fix: add support for node 22 and drop 16 fix: add support for node 22/24, drop node 16/21 Feb 8, 2026
@jasoniangreen
Copy link
Collaborator Author

@epoberezkin I wanted to have another crack at "resolve $dynamicRef to $dynamicAnchor in $defs" but it looks like this is needed first (node 16 build fails on master).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant