Skip to content

Make languageNamed accept display names and extensions again#2883

Open
schani wants to merge 1 commit into
masterfrom
fix/language-named-display-names
Open

Make languageNamed accept display names and extensions again#2883
schani wants to merge 1 commit into
masterfrom
fix/language-named-display-names

Conversation

@schani

@schani schani commented Jul 7, 2026

Copy link
Copy Markdown
Member

Problem

languageNamed() and isLanguageName() in quicktype-core stopped accepting display names ("TypeScript", "C++", "JSON Schema") and file extensions ("kt"), and started throwing Unknown language name: ... instead of returning undefined for unknown names.

Most visible fallout: app.quicktype.io stores the chosen language's display name in localStorage and calls languageNamed() with it on load, so returning users got a blank page until they cleared localStorage.

Root cause

The v23.1.0 rewrite (da1238c) of packages/quicktype-core/src/language/All.ts changed languageNamed() to match only the lowercase entries of each language's names array and to throw on a miss. Before that, it matched names, displayName, and extension, and returned undefined when nothing matched.

Fix

Restore the old matching behavior in All.ts:

  • match names, then displayName, then extension, all case-insensitively;
  • names take precedence over extensions, so "js" still resolves to JavaScript rather than Flow (whose extension is "js");
  • return undefined for unknown names instead of throwing (all in-repo callers already guard with isLanguageName() or defined(), and getTargetLanguage() in Run.ts still reports DriverUnknownOutputLanguage for unknown names);
  • keep the precise LanguageNameMap[Name] return type via an overload for calls with a known LanguageName literal, while plain strings get TargetLanguage | undefined;
  • isLanguageName() now delegates to languageNamed(), so it accepts the same spellings.

Tests

The regression test was written first and demonstrated failing before the fix, on top of current master:

  • test/check-language-named.ts (wired into test/test.ts alongside the existing checkJavaEnumAcronymCasing guard) asserts that languageNamed()/isLanguageName() resolve lowercase names, display names, and extensions case-insensitively, and return undefined/false — not throw — for unknown names. The fixture harness only ever passes exact lowercase names, so no fixture input can catch this; asserting on the API directly is the right slot.
  • Against unfixed master the check fails: it doesn't even compile under the harness tsconfig (the old signature rejects plain strings), and with ts-node --transpile-only it reports 16 runtime failures, e.g. languageNamed("TypeScript"): expected TypeScript, got throw: Error: Unknown language name: TypeScript.
  • After the fix it passes (type-checked, no --transpile-only).

Verification

  • Runtime repro from the triage: require("quicktype-core").languageNamed("TypeScript") threw before, now returns the TypeScript language; languageNamed("nope") returns undefined.
  • CLI: node dist/index.js --lang TypeScript sample.json now works; --lang nonexistent still errors with Unknown output language nonexistent.
  • FIXTURE=typescript-zod script/test passes (210 tests), which also runs the new check.
  • packages/quicktype-vscode type-checks cleanly against the new signatures (tsc --noEmit).
  • Not verified locally: the app.quicktype.io web app itself (its source is not in this repo), and non-installed language toolchains (php, dart, dotnet, java, kotlin) — but this change touches no code generation, only language-name lookup, and CI runs the full matrix.

Fixes #2769

🤖 Generated with Claude Code

The v23.1.0 rewrite of languageNamed()/isLanguageName() (da1238c)
matched only the lowercase entries in each language's names array and
threw "Unknown language name" on a miss. Before that, languageNamed()
matched names, displayName, and extension, and returned undefined for
unknown names.

That broke consumers passing display names — most visibly
app.quicktype.io, which stores the chosen language's display name
(e.g. "TypeScript") in localStorage and crashed to a blank page for
returning users.

Restore the old behavior: match names, display names, and extensions
case-insensitively (names take precedence over extensions so "js"
still resolves to JavaScript, not Flow), and return undefined instead
of throwing. An overload keeps the precise LanguageNameMap return type
for calls with a known LanguageName literal while allowing arbitrary
strings to return TargetLanguage | undefined.

Add a regression check to the test harness, since fixtures only ever
pass exact lowercase language names and cannot catch this.

Fixes #2769

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@schani schani force-pushed the fix/language-named-display-names branch from 86d5347 to 0055534 Compare July 7, 2026 01:50
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.

[BUG]: QuickType web interface fails to load

1 participant