diff --git a/src/rules/expectRule.ts b/src/rules/expectRule.ts index 99cc14de..d1478de0 100644 --- a/src/rules/expectRule.ts +++ b/src/rules/expectRule.ts @@ -298,7 +298,12 @@ function getExpectTypeFailures( const actual = checker.typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.NoTruncation); if (actual !== expected) { - unmetExpectations.push({ node, expected, actual }); + console.log("!!!", actual); + const actualSorted = fixupType(actual); + if (actualSorted !== expected) { + console.log("???", actualSorted); + unmetExpectations.push({ node, expected, actual }); + } } typeAssertions.delete(line); @@ -308,6 +313,27 @@ function getExpectTypeFailures( } } +function fixupType(s: string): string { + // Don't mess up `{ a: number | string }` into `string } | { a: number` + if (/[\<\(\[\{]/.test(s)) { + return s; + } + return fixupUnions(s); +} + +function fixupUnions(s: string): string { + const splitter = " | "; + return s.split(splitter).map(fixupIntersections).sort().join(splitter); +} + +function fixupIntersections(s: string): string { + if (s.startsWith("(") && s.endsWith(")")) { + return `(${fixupIntersections(s.slice(1, s.length - 1))})`; + } + const splitter = " & "; + return s.split(splitter).sort().join(splitter); +} + function lineOfPosition(pos: number, sourceFile: SourceFile): number { return sourceFile.getLineAndCharacterOfPosition(pos).line; } diff --git a/test/dt-header/wrong/types/bad-url-username/index.d.ts.lint b/test/dt-header/wrong/types/bad-url-username/index.d.ts.lint index 91b3d985..0ac32c82 100644 --- a/test/dt-header/wrong/types/bad-url-username/index.d.ts.lint +++ b/test/dt-header/wrong/types/bad-url-username/index.d.ts.lint @@ -1,5 +1,5 @@ // Type definitions for dt-header 1.0 // Project: https://github.com/bobby-headers/dt-header // Definitions by: Jane Doe - ~ [Error parsing header. Expected: '>'] + ~ [Error parsing header. Expected: /\/] // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped diff --git a/test/dt-header/wrong/types/bad-url/index.d.ts.lint b/test/dt-header/wrong/types/bad-url/index.d.ts.lint index c71501e1..35f39b1a 100644 --- a/test/dt-header/wrong/types/bad-url/index.d.ts.lint +++ b/test/dt-header/wrong/types/bad-url/index.d.ts.lint @@ -1,5 +1,5 @@ // Type definitions for dt-header 1.0 // Project: https://github.com/bobby-headers/dt-header // Definitions by: Jane Doe - ~ [Error parsing header. Expected: '/] // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped diff --git a/test/expect/expectType.ts.lint b/test/expect/expectType.ts.lint index 2b830753..24c72118 100644 --- a/test/expect/expectType.ts.lint +++ b/test/expect/expectType.ts.lint @@ -18,3 +18,17 @@ declare function f( // Test that we never truncate types. f; // $ExpectType (one: number, two: [number, number], three: [number, number, number], four: [number, number, number, number]) => number + +// Test that a union could be either exactly what tsc output, or a sorted version of that. +declare const x: "foo" | "bar"; +x; // $ExpectType "foo" | "bar" +x; // $ExpectType "bar" | "foo" + +type A = { a: number }; +type B = { b: number }; +type C = { c: number }; + +// Test that we don't try to sort nested unions. +declare class Generic {} +declare const generic: Generic; +generic; // $ExpectType Generic