From 49c3cdb98f23981c025b719ce735918759bb98a7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 4 Oct 2026 02:43:30 +0000 Subject: [PATCH 1/2] fix(types): Apply newer legacy type overlays to older TS outputs endpoint and normalizr legacy outputs (ts4.2, ts4.0, ts3.4) now inherit every newer version's src-*-types overlay, as rest already did. This replaces the TS 5.4 NoInfer builtin with the NI = T fallback for TS < 4.8 consumers. normalizr re-exports memo types by name instead of `export type *` (TS 5.0 syntax that downlevel-dts leaves as is). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE --- .changeset/legacy-ts-noinfer.md | 22 ++++++++++++++++++++++ .cursor/rules/ci-config.mdc | 2 +- packages/normalizr/src/index.ts | 7 ++++++- packages/rest/package.json | 2 +- scripts/build-legacy-types.sh | 27 +++++++++------------------ 5 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 .changeset/legacy-ts-noinfer.md diff --git a/.changeset/legacy-ts-noinfer.md b/.changeset/legacy-ts-noinfer.md new file mode 100644 index 000000000000..d27ac8b61936 --- /dev/null +++ b/.changeset/legacy-ts-noinfer.md @@ -0,0 +1,22 @@ +--- +'@data-client/endpoint': patch +'@data-client/normalizr': patch +'@data-client/rest': patch +'@data-client/graphql': patch +'@data-client/react': patch +'@data-client/vue': patch +--- + +Fix types for TypeScript 4.x when `skipLibCheck` is off + +TypeScript 4.0 through 4.7 no longer report `Cannot find name 'NoInfer'` from `@data-client/endpoint` or `@data-client/normalizr`, and TypeScript 4.0 through 4.9 no longer report `Only named exports may use 'export type'` from `@data-client/normalizr`. + +```ts +import { Entity } from '@data-client/endpoint'; +import { normalize } from '@data-client/normalizr'; + +// Before (TypeScript 4.7, skipLibCheck: false): +// error TS2304: Cannot find name 'NoInfer'. +// error TS1383: Only named exports may use 'export type'. +// After: no errors +``` diff --git a/.cursor/rules/ci-config.mdc b/.cursor/rules/ci-config.mdc index 44174b5e7a7b..937fdf532d2b 100644 --- a/.cursor/rules/ci-config.mdc +++ b/.cursor/rules/ci-config.mdc @@ -12,7 +12,7 @@ alwaysApply: false - Jobs halt via the `halt-unless-relevant-change` command based on flags computed once in `setup` (`.ci-esmodule-relevant`, `.ci-tests-relevant`) and transported via `save_cache`/`restore_cache` (keyed on `CIRCLE_SHA1`) so jobs can halt before paying `attach_workspace`. Missing/unreadable flags fail open (jobs run). On the default branch both flags are always true (a push may carry several commits). The diff uses `--no-renames` so moving a file out of a relevant dir still counts. - `esmodule` (validate-esmodule-browser-build, esmodule-types*): a denylist, so new paths fail open. False only when every changed path is provably outside the esmodule jobs' inputs: the shared `DOCS_ONLY` paths (also the `tests` denylist) plus `.vscode/`, `plans/`, root `__tests__/` (excluded by every `tsconfig.compile.json`), `eslint.config.mjs`, `jest.config.js`, `examples/*.md`, and examples the jobs never build (`benchmark`, `benchmark-react`, `coin-app`, `nextjs`, `normalizr-github`, `normalizr-redux`, `test-bundlesize`, `vue-todo-app`). Only add a path if no esmodule job (or the `setup` builds feeding them) reads it. - `tests` (lint, typecheck, unit_tests, node_matrix): false only when every changed path is docs/website/tooling (`website/`, `docs/`, `.changeset/`, `.cursor/`, `.agents/`, `.claude/`, `.github/`, root `*.md`), except `website/src/components/Playground/` (has unit tests). When both flags are false, `setup` halts before install. -- Legacy TS types (`ci:build:legacy-types`, consumed by `esmodule-types`) build inside `setup` (`ci:build:setup:esmodule`) only when the esmodule flag is set; there is no separate job, to keep a job hop off the critical path. In CI it builds only endpoint/normalizr/rest outputs for TS >= 4.0 (`LEGACY_MIN_TS=4.0`), since the oldest TS in the `esmodule-types` matrix is 4.0; release builds (`build:types`) still emit every version. `scripts/build-legacy-types.sh` builds each TS version concurrently; rest passes `--inherit-newer-overlays` so its `src-4.1-types` also apply to `ts4.0` (endpoint/normalizr don't pass it; each version gets only its own overlays). Any change to legacy types building must leave `ts*/` output byte-identical to master (diff it). +- Legacy TS types (`ci:build:legacy-types`, consumed by `esmodule-types`) build inside `setup` (`ci:build:setup:esmodule`) only when the esmodule flag is set; there is no separate job, to keep a job hop off the critical path. In CI it builds only endpoint/normalizr/rest outputs for TS >= 4.0 (`LEGACY_MIN_TS=4.0`), since the oldest TS in the `esmodule-types` matrix is 4.0; release builds (`build:types`) still emit every version. `scripts/build-legacy-types.sh` builds each TS version concurrently; each `ts/` gets the downleveled `lib`, then every newer version's `src-*-types` overlay, then its own. Any change to legacy types building must leave `ts*/` output byte-identical to master (diff it) unless it intentionally changes published types (then add a changeset). - Never `git fetch --depth` the base branch in the relevance check: a shallow fetch severs the merge base and the three-dot diff fails. - Changing root `package.json` `workspaces` requires updating the `setup` job's workspace trimming step. diff --git a/packages/normalizr/src/index.ts b/packages/normalizr/src/index.ts index 3eb4d4da9619..3c6ac4bce05f 100644 --- a/packages/normalizr/src/index.ts +++ b/packages/normalizr/src/index.ts @@ -19,7 +19,12 @@ export type { export type { NI } from './NoInfer.js'; export * from './endpoint/types.js'; export * from './interface.js'; -export type * from './memo/types.js'; +export type { + EntityCache, + EndpointsCache, + DenormGetEntity, + IMemoPolicy, +} from './memo/types.js'; export * from './Expiry.js'; export { INVALID } from './denormalize/symbol.js'; export { validateQueryKey } from './buildQueryKey.js'; diff --git a/packages/rest/package.json b/packages/rest/package.json index 63b837a0a850..5faf4e204233 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -123,7 +123,7 @@ "build:js:browser": "BROWSERSLIST_ENV=legacy yarn g:rollup", "build:bundle": "yarn g:runs build:js:\\* && echo '{\"type\":\"commonjs\"}' > dist/package.json", "build:clean": "yarn g:clean ts4.0 ts4.1 index.d.ts next.d.ts", - "build:legacy-types": "yarn g:legacy-types --inherit-newer-overlays 4.1 4.0", + "build:legacy-types": "yarn g:legacy-types 4.1 4.0", "build": "run build:lib && run build:legacy:lib && run build:bundle", "dev": "NODE_ENV=production BROWSERSLIST_ENV='2020' POLYFILL_TARGETS='chrome>88,safari>14' yarn g:babel --out-dir lib -w", "prepare": "run build:lib", diff --git a/scripts/build-legacy-types.sh b/scripts/build-legacy-types.sh index 89e972517a49..b54f85420c51 100755 --- a/scripts/build-legacy-types.sh +++ b/scripts/build-legacy-types.sh @@ -1,17 +1,9 @@ #!/bin/bash set -e -# --inherit-newer-overlays: custom types for a version also apply to every -# version listed after it. Without it each version gets only its own. -inherit=false -if [ "$1" = "--inherit-newer-overlays" ]; then - inherit=true - shift -fi - # Check if at least one directory is provided if [ $# -eq 0 ]; then - echo "Usage: $0 [--inherit-newer-overlays] [version2] ..." + echo "Usage: $0 [version2] ..." exit 1 fi @@ -28,19 +20,18 @@ copy_types() { done } -# Each output dir gets the downleveled lib, then (with --inherit-newer-overlays) -# earlier versions' custom types, then its own. Each output dir only depends on -# lib and src-*-types, so versions build concurrently. +# Versions are listed newest first, and custom types for a version also apply +# to every version listed after it. So each output dir gets the downleveled lib, +# then earlier versions' custom types, then its own. Each output dir only +# depends on lib and src-*-types, so versions build concurrently. build_version() { local version="$1" shift "$downlevel_dts" lib "ts$version" --to="$version" - if [ "$inherit" = true ]; then - for earlier in "$@" - do - copy_types "./src-$earlier-types" "./ts$version" - done - fi + for earlier in "$@" + do + copy_types "./src-$earlier-types" "./ts$version" + done copy_types "./src-$version-types" "./ts$version" } From d7eca37741fa7054651c7723a9a750f06e1d4338 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 4 Oct 2026 02:43:56 +0000 Subject: [PATCH 2/2] docs(blog): Note legacy TypeScript types fix Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE --- website/blog/2026-10-03-v0.19-batch-set.md | 1 + 1 file changed, 1 insertion(+) diff --git a/website/blog/2026-10-03-v0.19-batch-set.md b/website/blog/2026-10-03-v0.19-batch-set.md index 2c0f61f114e9..d369ce495270 100644 --- a/website/blog/2026-10-03-v0.19-batch-set.md +++ b/website/blog/2026-10-03-v0.19-batch-set.md @@ -16,6 +16,7 @@ import StackBlitz from '@site/src/components/StackBlitz'; - Fix TypeScript 7 module resolution for package `exports`; imports now resolve to declaration files ([#4019](https://github.com/reactive/data-client/pull/4019)) - [renderDataHook()](/docs/api/renderDataHook) runs provider mount effects when the first render suspends ([#4099](https://github.com/reactive/data-client/pull/4099)) +- Fix `Cannot find name 'NoInfer'` and `export type` errors on TypeScript 4.x with `skipLibCheck` off ([#4138](https://github.com/reactive/data-client/pull/4138)) {/* truncate */}