diff --git a/CHANGELOG.md b/CHANGELOG.md index 49bb86f75..7335e0048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased +### Features + +- Literal numeric unions will now be sorted during conversion, #2502. + ### Bug Fixes - Module readmes will now be included in JSON output, #2500. diff --git a/src/lib/converter/types.ts b/src/lib/converter/types.ts index 991d26143..7ffe2e183 100644 --- a/src/lib/converter/types.ts +++ b/src/lib/converter/types.ts @@ -1045,9 +1045,10 @@ const unionConverter: TypeConverter = { ); }, convertType(context, type) { - return new UnionType( - type.types.map((type) => convertType(context, type)), - ); + const types = type.types.map((type) => convertType(context, type)); + sortLiteralUnion(types); + + return new UnionType(types); }, }; @@ -1115,3 +1116,18 @@ function kindToModifier( return undefined; } } + +function sortLiteralUnion(types: SomeType[]) { + if ( + types.some((t) => t.type !== "literal" || typeof t.value !== "number") + ) { + return; + } + + types.sort((a, b) => { + const aLit = a as LiteralType; + const bLit = b as LiteralType; + + return (aLit.value as number) - (bLit.value as number); + }); +} diff --git a/src/test/converter2/issues/gh2502.ts b/src/test/converter2/issues/gh2502.ts new file mode 100644 index 000000000..84f4298c0 --- /dev/null +++ b/src/test/converter2/issues/gh2502.ts @@ -0,0 +1,7 @@ +// A future TS version might change this so that numbers are hardcoded +// to show up in a specific order. As of TS 5.3.3, this makes the union display +// as 3 | 1 | 2. +type WeirdOrder = [1, 2, 3][number]; +// ^? + +export const Test = null! as WeirdOrder; diff --git a/src/test/issues.c2.test.ts b/src/test/issues.c2.test.ts index 7b8a9da77..24c1b9b84 100644 --- a/src/test/issues.c2.test.ts +++ b/src/test/issues.c2.test.ts @@ -1389,6 +1389,12 @@ describe("Issue Tests", () => { convert(); }); + it("Sorts literal numeric unions when converting a type, #2502", () => { + const project = convert(); + const refl = query(project, "Test"); + equal(refl.type?.toString(), "1 | 2 | 3"); + }); + it("Handles an infinitely recursive type, #2507", () => { const project = convert(); const type = querySig(project, "fromPartial").typeParameters![0].type;