Skip to content

fix(dynamic): map unmappable function params/returns and type parameters to JSVAL - #221

Open
techfreaque wants to merge 1 commit into
vercel-labs:mainfrom
techfreaque:fix-dynamic-type-mapping-v2
Open

fix(dynamic): map unmappable function params/returns and type parameters to JSVAL#221
techfreaque wants to merge 1 commit into
vercel-labs:mainfrom
techfreaque:fix-dynamic-type-mapping-v2

Conversation

@techfreaque

Copy link
Copy Markdown

Problem

In --dynamic mode, three categories of types could not be mapped to IR types, causing SC errors on valid programs that use heavily-generic npm packages (Drizzle, Zod, React):

  1. Function params/returns with no static IR mapping (e.g. (schema: z.ZodTypeAny) => void): emitted SC2008 on the containing record type.
  2. TypeParameter with no bound or an unmappable bound (e.g. TConfig extends z.AnyZodObject): fell through to null, poisoning any intersection that contained it.
  3. Multi-signature function types (overloaded functions / intersection overloads from TEvents callbacks): had no static lowering path, causing SC1090.

Fix

types.ts:

  • Function param: if pt is null in --dynamic mode, use JSVAL. The param accepts any island value.
  • Function return: if ret is null in --dynamic mode, return funcOf(params, JSVAL). The function is callable; the return value rides the island.
  • TypeParameter fallback: call checker.getBaseConstraintOfType(widened) and recursively map the constraint. If the constraint maps (e.g. TSchema extends z.ZodTypeAny → JSVAL), the parameter maps to the same type.
  • Multi-signature → JSVAL with stdlib carve-out: callSigs.length > 1 in --dynamic returns JSVAL, except when every declaration comes from a stdlib file (@types/node etc.) — those have static overload-selection lowerings that must not regress (e.g. spawnSync, readFileSync).

ts7/checker.ts: adds getBaseConstraintOfType method to CheckerFacade.

lowering/lowerer.ts: exports esOwnKeyOrder for downstream use.

Verification

A program that imports Drizzle ORM with 30+ table joins, Zod schemas with TSchema extends z.ZodTypeAny, and overloaded event callback types compiles without SC errors. spawnSync, readFileSync, and other stdlib overloads retain their static lowerings. packages/compiler builds clean.

Non-goals

MIDI type support (node-midi / @julusian/midi) is intentionally excluded from this PR — it belongs in a separate focused change.

…ers to JSVAL

In --dynamic mode, three categories of type-mapping failures now resolve
to JSVAL rather than emitting SC errors:

1. Function params/returns that don't map to a static IR type (e.g.
   complex Zod schema types, React prop types): the param/return becomes
   JSVAL. The function remains callable from static code.

2. TypeParameters with no bound or an unmappable bound: falls back to
   the constraint type via checker.getBaseConstraintOfType. If the
   constraint maps (e.g. TSchema extends z.ZodTypeAny → JSVAL), the
   parameter maps to the same type. Previously this caused SC2008 on
   intersection types with heavily-generic npm packages.

3. Multi-signature function types (overloaded / intersection overloads)
   that lack a static lowering: return JSVAL unless every declaration
   comes from a stdlib file (spawnSync, readFileSync etc. have static
   lowerings via their overload selection path and must not regress).

Also adds getBaseConstraintOfType to CheckerFacade and exports
esOwnKeyOrder for downstream use.
@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

@techfreaque is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant