Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changeset/legacy-ts-noinfer.md
Original file line number Diff line number Diff line change
@@ -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
```
2 changes: 1 addition & 1 deletion .cursor/rules/ci-config.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -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<version>/` 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.

Expand Down
7 changes: 6 additions & 1 deletion packages/normalizr/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion packages/rest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
27 changes: 9 additions & 18 deletions scripts/build-legacy-types.sh
Original file line number Diff line number Diff line change
@@ -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] <version1> [version2] ..."
echo "Usage: $0 <version1> [version2] ..."
exit 1
fi

Expand All @@ -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"
}

Expand Down
1 change: 1 addition & 0 deletions website/blog/2026-10-03-v0.19-batch-set.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 */}

Expand Down