Skip to content

fix(types): Apply newer legacy type overlays to older TS outputs - #4138

Merged
ntucker merged 2 commits into
claude/project-thread-bw2hx0from
claude/project-thread-mdbtb1
Oct 4, 2026
Merged

ntucker merged 2 commits into
claude/project-thread-bw2hx0from
claude/project-thread-mdbtb1

Conversation

@ntucker

@ntucker ntucker commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

Requested by Nathaniel · project thread

Follow-up from #4122 (stacked on it; retargets to master once it merges).

Motivation

Before: on TypeScript 4.0–4.7 with skipLibCheck: false, @data-client/endpoint and @data-client/normalizr reported Cannot find name 'NoInfer', because ts4.2/ and ts4.0/ shipped the TS 5.4 builtin instead of src-4.8-types' fallback. normalizr also reported Only named exports may use 'export type' on TS 4.0–4.9.

After: no errors from these on any TS 4.x.

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

Solution

  • scripts/build-legacy-types.sh always applies every newer version's src-*-types overlay (the old intent, which downlevel-dts silently overwrote). The --inherit-newer-overlays flag is gone; rest output stays byte-identical.
  • normalizr re-exports memo types by name instead of export type * (TS 5.0 syntax downlevel-dts passes through).
  • Changed outputs, all reviewed: endpoint ts4.2/NoInfer, ts4.0/{NoInfer,endpointTypes} (src-4.2's relaxed call/apply/bind thisArg), ts3.4/{NoInfer,schemaArgs,schemas/Entity,EntityFields,EntityTypes} (src-4.0's no-abstract new/no-as-remap versions, which 3.4 can actually parse); normalizr ts4.0/NoInfer, ts3.4/{NoInfer,EntityFields,schemaArgs}.
  • Verified with a minimal consumer (skipLibCheck: false) on TS 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.7, 4.8, 4.9, 5.0, 5.3: every NoInfer/export type error is gone and no new error appears. 4.1, 4.5, 4.7–5.3 are now clean.

Open questions

Pre-existing errors this doesn't touch, split into their own follow-up: endpoint on TS 4.0 (RemoveArray/PartialArray recursive conditionals need 4.1), TS 4.2 (InstanceType on abstract TBase), TS 4.2–4.4 (schema.d.ts EntityFields constraint), and stale src-4.0-types Entity denormalize signatures.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE


Generated by Claude Code


Note

Medium Risk
Changes how published ts*/ declaration bundles are built and normalizr’s public type surface; low runtime impact but affects all TS 4.x consumers typechecking node_modules.

Overview
Fixes published legacy .d.ts outputs so TypeScript 4.x consumers with skipLibCheck: false no longer hit Cannot find name 'NoInfer' (@data-client/endpoint / @data-client/normalizr) or Only named exports may use 'export type' (@data-client/normalizr).

scripts/build-legacy-types.sh now always layers each newer src-*-types overlay onto older ts*/ folders (the previous --inherit-newer-overlays behavior, which downlevel-dts had been overwriting). @data-client/rest drops that CLI flag from build:legacy-types; CI/docs note that overlay inheritance is the default and intentional type output changes need a changeset.

@data-client/normalizr replaces export type * from memo types with explicit named export type { … } so downleveled declarations stay valid on TS 4.0–4.9.

Patch changesets and a v0.19 blog bullet document the fix for users.

Reviewed by Cursor Bugbot for commit d7eca37. Bugbot is set up for automated code reviews on this repo. Configure here.

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> = 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE
@changeset-bot

changeset-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d7eca37

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@data-client/endpoint Patch
@data-client/normalizr Patch
@data-client/rest Patch
@data-client/graphql Patch
@data-client/react Patch
@data-client/vue Patch
example-benchmark Patch
example-benchmark-react Patch
normalizr-github-example Patch
normalizr-redux-example Patch
normalizr-relationships Patch
test-bundlesize Patch
coinbase-lite Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs-site Ready Ready Preview Oct 4, 2026 2:44am UTC

Request Review

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE
@ntucker ntucker self-assigned this Oct 4, 2026
@ntucker
ntucker marked this pull request as ready for review October 4, 2026 02:44
@codecov

codecov Bot commented Oct 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.87%. Comparing base (f60af6f) to head (d7eca37).

Additional details and impacted files
@@                      Coverage Diff                      @@
##           claude/project-thread-bw2hx0    #4138   +/-   ##
=============================================================
  Coverage                         97.87%   97.87%           
=============================================================
  Files                               156      156           
  Lines                              3057     3057           
  Branches                            612      612           
=============================================================
  Hits                               2992     2992           
  Misses                               18       18           
  Partials                             47       47           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ntucker
ntucker merged commit db068cd into claude/project-thread-bw2hx0 Oct 4, 2026
22 checks passed
@ntucker
ntucker deleted the claude/project-thread-mdbtb1 branch October 4, 2026 03:17
ntucker added a commit that referenced this pull request Oct 4, 2026
* 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> = 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE

* docs(blog): Note legacy TypeScript types fix

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE

---------

Co-authored-by: Claude <noreply@anthropic.com>
ntucker added a commit that referenced this pull request Oct 4, 2026
…i): fail-open esmodule relevance, faster rest legacy types (#4122)

* internal(ci): Fail open on esmodule relevance and speed up rest legacy types

The esmodule relevance flag now uses a denylist of provably irrelevant
paths, so new inputs run the esmodule jobs by default. rest's legacy
types build uses scripts/build-legacy-types.sh (direct downlevel-dts,
d.ts-only copies) with --newer-overlays-last to keep its overlay order;
ts4.0/ts4.1 output is byte-identical (8.6s -> 4.5s locally).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEcQdob4nGVuMq91oUHC2V

* internal(ci): Simplify legacy types overlay order and share docs-only paths

Downlevel always runs first; --inherit-newer-overlays (rest) then applies
earlier versions' custom types. Without the flag those copies were always
overwritten by downlevel-dts, so endpoint/normalizr output is unchanged
(ts*/ byte-identical). The esmodule and tests relevance checks now share
one DOCS_ONLY path list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEcQdob4nGVuMq91oUHC2V

* fix(types): Apply newer legacy type overlays to older TS outputs (#4138)

* 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> = 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE

* docs(blog): Note legacy TypeScript types fix

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE

---------

Co-authored-by: Claude <noreply@anthropic.com>

* fix(types): Fix endpoint/rest legacy type errors with skipLibCheck off (#4140)

* 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> = 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE

* docs(blog): Note legacy TypeScript types fix

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpCgcZt8G8R5KARZ7z5CKE

* fix(types): Fix endpoint/rest legacy type errors with skipLibCheck off

- TS 4.0: unroll RemoveArray and approximate PartialArray (recursive
  conditional types need 4.1) in new src-4.0-types overlays
- TS <4.2: rewrite `abstract new` to `new` in the downleveled output and
  drop the stale src-4.0-types Entity/EntityTypes copies
- TS 4.2: ConstructorInstance<> replaces InstanceType<> on abstract TBase
- TS 4.2-4.4: UnionInstance Args is unconstrained
- TS 4.0-4.5: rest getPage narrows paginationField with Extract<>
- CI: esmodule-types also typechecks a skipLibCheck: false consumer

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMEHZGboXdMFRkF4D2ktki

* docs(blog): Link #4140 in v0.19 notes

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMEHZGboXdMFRkF4D2ktki

* refactor(types): Isolate recursive tuple types so the 4.0 overlay is one small file

- RemoveArray and PartialArray move to tupleTypes.ts; the src-4.0-types
  overlay replaces only that module instead of copying endpointTypes/utility
- Legacy build only rewrites files that contain `abstract new (`
- libcheck typetest skips TypeScript's own lib checks
- Split the legacy types bullet in ci-config.mdc

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMEHZGboXdMFRkF4D2ktki

* internal: Resolve leftover merge conflict in ci-config rule

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMEHZGboXdMFRkF4D2ktki

* internal: Resolve leftover merge conflict in build-legacy-types.sh

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMEHZGboXdMFRkF4D2ktki

---------

Co-authored-by: Claude <noreply@anthropic.com>

* internal(ci): Harden legacy types script and libcheck lib/ on latest TS

version_lt compares major.minor in bash instead of relying on sort -V
(a missing -V silently skipped the abstract new rewrite), and the
abstract new grep no longer fails the build under pipefail when nothing
matches. esmodule-types-latest also runs the skipLibCheck: false
typetest so lib/ is checked on the newest compiler.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEcQdob4nGVuMq91oUHC2V

---------

Co-authored-by: Claude <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — d7eca377 Deployed Oct 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants