Skip to content

fix(typescript-input): dedupe object type aliases referenced by properties#3043

Open
schani wants to merge 3 commits into
masterfrom
agent/fix-issue-879
Open

fix(typescript-input): dedupe object type aliases referenced by properties#3043
schani wants to merge 3 commits into
masterfrom
agent/fix-issue-879

Conversation

@schani

@schani schani commented Jul 20, 2026

Copy link
Copy Markdown
Member

The bug

TypeScript source used as quicktype's input, where an object type alias
(type X = { ... }) is referenced by a property, produced a duplicate
type. For example:

type AuthTokens = {
    accessToken: string;
    refreshToken: string;
    idToken: string;
};

class UserInfo {
    username: string;
    password?: string;
    tokens?: AuthTokens;
}

node dist/index.js --src-lang typescript --lang typescript input.ts produced
both an AuthTokens interface and a spurious duplicate Tokens interface,
with UserInfo.tokens typed Tokens instead of AuthTokens. This did not
happen when AuthTokens was a class or interface, matching the original
report.

Root cause

quicktype-typescript-input builds a JSON Schema from TypeScript source via
the pinned typescript-json-schema package. That package's getTypeDefinition
only emits a $ref to a named definition when the referenced symbol is
ref-able; for type X = {...} aliases, the resolved property type is an
"anonymous object type" internally (as opposed to a class/interface,
which is not anonymous), so it gets fully inlined instead of $ref'd unless
the generator's aliasRef option is enabled — and enabling that option
introduces its own indirection artifacts (extra __type/_1-suffixed
definitions, chained refs) rather than a clean fix.

The fix

packages/quicktype-typescript-input/src/index.ts already monkey-patches the
typescript-json-schema generator's getTypeDefinition in one place
(patchGeneratorForBuiltinTypes, for Map/unsupported builtins). This PR
adds a second, analogous patch, patchGeneratorForTypeAliases: when a
property's type resolves to an anonymous object type that is directly backed
by a (non-generic) top-level type-alias symbol, it rewrites the definition
into a $ref pointing at that alias's own top-level schema definition
instead of letting typescript-json-schema inline a structural duplicate.

Test coverage

Added to test/unit/typescript-input.test.ts (the existing unit-test file
for schemaForTypeScriptSources):

  • A regression test reproducing the exact issue Duplicate types from TypeScript input #879 scenario, asserting the
    schema has exactly AuthTokens and UserInfo definitions (no duplicate),
    and that UserInfo.tokens is a $ref to AuthTokens.
  • A companion test confirming the pre-existing, already-correct behavior for
    class-based property types is unchanged.

Note: quicktype's fixture-test framework (test/inputs/json,
test/inputs/schema, test/languages.ts, test/fixtures.ts) only drives
quicktype's output side — TypeScript is registered there solely as an
output language, never as an input source — so there is no fixture mechanism
for "TypeScript source as input." schemaForTypeScriptSources already has
direct unit-test coverage for this reason, which is where this regression
test was added.

Verification

  • npm run build passes.
  • npm run test:unit — all 26 files / 172 tests pass (was 12 tests in the
    TypeScript-input file, now includes the 2 new ones).
  • Manually re-ran the exact issue repro
    (node dist/index.js --src-lang typescript --lang typescript input.ts)
    before and after: before, output has both AuthTokens and duplicate
    Tokens; after, only AuthTokens is emitted and UserInfo.tokens: AuthTokens.
  • Also spot-checked interface, array-of-alias, and generic-alias shapes to
    confirm no regressions in already-working cases.

CI will additionally run the full fixture suite across all output languages.

Fixes #879

🤖 Generated with Claude Code

schani and others added 3 commits July 20, 2026 18:24
…rties (#879)

Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
…e-76a-76

# Conflicts:
#	test/unit/typescript-input.test.ts
@github-actions

Copy link
Copy Markdown

No generated-output differences

✅ Generated outputs are unchanged between the PR base and head revisions.

@github-actions

Copy link
Copy Markdown

No generated-output differences

✅ Generated outputs are unchanged between the PR base and head revisions.

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.

Duplicate types from TypeScript input

1 participant