Skip to content

types: #99 lib.d.ts loader + checker features — 250→256 Pass#1263

Open
nickna wants to merge 11 commits into
worktree-epic-99from
worktree-99-libtypes
Open

types: #99 lib.d.ts loader + checker features — 250→256 Pass#1263
nickna wants to merge 11 commits into
worktree-epic-99from
worktree-99-libtypes

Conversation

@nickna

@nickna nickna commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Stacked on #1262 (base is worktree-epic-99; will retarget to main once #1262 merges). Continues the TypeScript conformance work (epic #80 / #99), taking the 296-test subset baseline 250 → 256 Pass / 29 → 23 Fail. Zero regressions at every step; full xUnit 15452/0 and conformance green on every commit.

#99 — from deferred epic to a working lib loader

  • Increment 1 — lib-type seam. A single TryResolveLibType consulted by both ResolveTypeNameCore (for the type) and ReportUnknownTypeName (so the name isn't flagged TS2304). Resolves Symbol/SymbolConstructor in type position. → flips symbolProperty55, symbolType15.
  • Increment 2a — the loader. LibTypeLoader parses ambient lib declarations embedded as libdefs/*.d.ts resources (the vendored TypeScript lib is a dev-only submodule, absent at runtime) and resolves them to real TypeInfo via a throwaway checker's ExtractLibTypes. SymbolConstructor now comes from the loaded lib. Built once, cached.
  • Increment 2b — first loader flip. implements/extends resolution consults the loaded (member-less) wrapper interfaces for String/Number/Boolean, so class C implements String / interface I extends String are valid targets. var s: String still resolves to the primitive — zero assignability change. → flips stringLiteralTypeIsSubtypeOfString.

Checker features (found while working the Fail bucket)

  • TS2416implements now checks against inferred method return types (the validation ran before body inference, when un-annotated returns were <inferred>≈any). Narrow after-inference re-check of un-annotated methods, reported at the method line. → symbolProperty24.
  • TS2367symbol == boolean/number/string/bigint flagged as a no-overlap comparison, scoped to symbol-vs-concrete-primitive. → symbolType9.
  • TS2353 — excess-property checking now runs on fresh object-literal call arguments (both non-generic and generic paths, which previously skipped argument validation), attributed to the offending property's own line. → symbolProperty21.

Remaining Fail bucket is the hard core: globalThis/Intl ambient types, lib-version awareness (the 6 lib-drift tests), and the accessor getter-return-inference feature.

nickna added 11 commits July 8, 2026 23:49
…tructor)

First increment of #99 (lib.d.ts modeling), seam-first: a single TryResolveLibType
switch, consulted by both ResolveTypeNameCore (for the type) and ReportUnknownTypeName
(so the name isn't flagged TS2304), resolves TYPE-position lib names SharpTS doesn't
yet parse from the vendored .d.ts files. Checked AFTER user declarations so a user
interface of the same name wins. A later increment backs this switch with a real
lib.d.ts loader.

Covers the Symbol family: SymbolConstructor -> the existing WellKnownSymbolTypes shape;
Symbol -> a new member-less wrapper interface (a symbol value is assignable to it, but
it is not assignable back to the symbol primitive). Flips symbolProperty55, symbolType15.
…eInfo)

The real-loader foundation for #99 increment 2. LibTypeLoader parses ambient lib
declarations embedded as libdefs/*.d.ts resources (the vendored TypeScript lib is a
dev-only submodule, so it must be embedded to work at runtime) and resolves them to
modeled TypeInfo via a throwaway checker's new ExtractLibTypes (PreRegister into a
fresh env, diagnostics suppressed, extracted by name). Built once, cached process-wide.

TryResolveLibType now sources SymbolConstructor from the LOADED lib instead of a
hand-modeled shape (Symbol stays hand-modeled — the wrapper needs a member-less shape
a symbol can satisfy, which the loaded interface can't give until primitive apparent
members are modeled). No baseline change (symbolProperty55/symbolType15 still pass);
this is the pipeline that later increments fill from the real es5.d.ts + resolve the
primitive-vs-interface tension to flip the remaining lib tests.

Full xUnit 15452/0, conformance 252 Pass (0 regressions).
…ts/extends

First test flipped by the lib loader. A wrapper name (String/Number/Boolean)
resolves to the primitive in type position, so 'class C implements String' and
'interface I extends String' saw a non-interface and reported spurious TS2304/TS2312.
Now the implements and interface-extends resolution consult LibTypeLoader when the
name isn't a user interface, using the (currently member-less) lib wrapper interface
as a valid implements/extends target. 'var s: String' still resolves to the primitive,
so no assignability change there.

Flips stringLiteralTypeIsSubtypeOfString. Full xUnit 15452/0, conformance 253 Pass.
…pes (TS2416)

'class C implements I' validation runs before the method-body pass, so an
un-annotated method (e.g. '[Symbol.toPrimitive]() { return "" }') had a
<inferred> (~any) return type that hid a mismatch with the interface. Capture the
resolved interfaces during that pass and re-check un-annotated method return types
against them at the end of class-checking (after inference is published), reporting
TS2416 at the method's own line. Only un-annotated methods are re-checked, so
annotated ones aren't double-reported.

Flips symbolProperty24. Full xUnit 15452/0, conformance 254 Pass.
…lap (TS2367)

A symbol can never equal a boolean/number/string/bigint, so ==/!=/===/!== between
them is unintentional (TS2367). Scoped to the case where exactly one operand is a
symbol and the other is a concrete primitive — symbol vs symbol / vs any / vs a
union that could hold a symbol is left untouched, so no broad no-overlap sweep.

Flips symbolType9. Full xUnit 15452/0, conformance 255 Pass.
…nts (TS2353)

Excess-property checking ran for assignments but not call arguments — a fresh
object literal passed to a typed parameter with extra properties was accepted.
Wire CheckExcessProperties into both the non-generic argument loop and the generic
call path (which skipped argument validation entirely), scoped to direct object
literals (tsc's fresh-literal rule). Also: CheckExcessProperties now flattens a
generic interface argument (I<T>) to its concrete members, and attributes TS2353 to
the offending property's own line (not the enclosing statement's) so a multi-line
call argument reports correctly.

Flips symbolProperty21. Full xUnit 15452/0, conformance 256 Pass.
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