From e93092dc34c804925206bc721c6a69fb07829c3f Mon Sep 17 00:00:00 2001 From: David Matejka Date: Sat, 24 Oct 2026 16:20:12 +0200 Subject: [PATCH] perf(bindx-client): declare TEntity invariant on selection builder methods ScalarMethod, HasOneMethod and HasManyMethod reference SelectionBuilder again, so TypeScript measures TEntity's variance through a cycle with the `-?` mapped type in SelectionBuilderMethods. Under TypeScript 7.1 that measurement comes out unmeasurable, which forces a structural comparison of every builder: the cost grows with the square of the entity's field count and hits TS2589 on large schemas (microsoft/TypeScript#64950). TypeScript 7.0 was only fast because it measured TEntity as independent through the cycle, which is unsound. `in out` states the variance instead of measuring it. TSelected and THasManyParams need no annotation. Co-Authored-By: Claude Opus 5.5 --- packages/bindx-client/src/selection/types.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/bindx-client/src/selection/types.ts b/packages/bindx-client/src/selection/types.ts index 86ec63a6..95f06cd4 100644 --- a/packages/bindx-client/src/selection/types.ts +++ b/packages/bindx-client/src/selection/types.ts @@ -94,7 +94,10 @@ export interface FluentFragment< /** * Scalar method on selection builder - selects a scalar field */ -export interface ScalarMethod { +// TEntity is declared `in out` on all three *Method interfaces. Measured instead, it cycles through the `-?` mapped +// type in SelectionBuilderMethods and comes out unmeasurable, so TypeScript 7.1 compares builders structurally: +// quadratic in the entity's field count, TS2589 on large schemas. +export interface ScalarMethod { /** Select field with original name */ (): SelectionBuilder, THasManyParams> /** Select field with alias */ @@ -109,7 +112,7 @@ export interface ScalarMethod = TOptions extends { as: infer A extends string } * Has-many method on selection builder - selects a relation to multiple entities */ export interface HasManyMethod< - TEntity, + in out TEntity, // see ScalarMethod K extends keyof TEntity, TItem, TSelected extends object,