From ef02e0dddc6c730e20f0a714b54a6f42fa8df8e9 Mon Sep 17 00:00:00 2001 From: Alexis Atkinson Date: Sat, 7 Jun 2025 18:18:51 -0600 Subject: [PATCH 1/2] put long types on on their own lines in diagnostic messages --- internal/checker/relater.go | 9 ++++++++- internal/diagnostics/diagnostics_generated.go | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/internal/checker/relater.go b/internal/checker/relater.go index 8da7906566..d4ed86bdc2 100644 --- a/internal/checker/relater.go +++ b/internal/checker/relater.go @@ -4705,7 +4705,14 @@ func (r *Relater) reportRelationError(message *diagnostics.Message, source *Type return } } - message = diagnostics.Type_0_is_not_assignable_to_type_1 + + includesWideTypes := len(sourceType) > 30 && len(targetType) > 30 + isPretty := r.c.compilerOptions.Pretty == core.TSTrue + if isPretty && includesWideTypes { + message = diagnostics.Type_Colon_0_is_not_assignable_to_type_Colon_1 + } else { + message = diagnostics.Type_0_is_not_assignable_to_type_1 + } } } switch r.getChainMessage(0) { diff --git a/internal/diagnostics/diagnostics_generated.go b/internal/diagnostics/diagnostics_generated.go index 5fb56a7143..5a4eb11326 100644 --- a/internal/diagnostics/diagnostics_generated.go +++ b/internal/diagnostics/diagnostics_generated.go @@ -1990,6 +1990,10 @@ var Using_JSX_fragments_requires_fragment_factory_0_to_be_in_scope_but_it_could_ var Import_assertions_have_been_replaced_by_import_attributes_Use_with_instead_of_assert = &Message{code: 2880, category: CategoryError, key: "Import_assertions_have_been_replaced_by_import_attributes_Use_with_instead_of_assert_2880", text: "Import assertions have been replaced by import attributes. Use 'with' instead of 'assert'."} +var This_expression_is_never_nullish = &Message{code: 2881, category: CategoryError, key: "This_expression_is_never_nullish_2881", text: "This expression is never nullish."} + +var Type_Colon_0_is_not_assignable_to_type_Colon_1 = &Message{code: 2882, category: CategoryError, key: "Type_Colon_0_is_not_assignable_to_type_Colon_1_2882", text: "Type:\n {0}\n\nis not assignable to type:\n {1}\n"} + var Import_declaration_0_is_using_private_name_1 = &Message{code: 4000, category: CategoryError, key: "Import_declaration_0_is_using_private_name_1_4000", text: "Import declaration '{0}' is using private name '{1}'."} var Type_parameter_0_of_exported_class_has_or_is_using_private_name_1 = &Message{code: 4002, category: CategoryError, key: "Type_parameter_0_of_exported_class_has_or_is_using_private_name_1_4002", text: "Type parameter '{0}' of exported class has or is using private name '{1}'."} From 2ec7f34976848e5db4a7bdf154ef65041577cb7e Mon Sep 17 00:00:00 2001 From: Alexis Atkinson Date: Sat, 7 Jun 2025 18:19:13 -0600 Subject: [PATCH 2/2] add tests for printing wide types in diagnostic messages --- .../compiler/prettyFormatLongTypes.errors.txt | 62 +++++++++++++++++++ .../compiler/prettyFormatLongTypes.js | 32 ++++++++++ .../compiler/prettyFormatLongTypes.symbols | 39 ++++++++++++ .../compiler/prettyFormatLongTypes.types | 55 ++++++++++++++++ .../cases/compiler/prettyFormatLongTypes.ts | 17 +++++ 5 files changed, 205 insertions(+) create mode 100644 testdata/baselines/reference/compiler/prettyFormatLongTypes.errors.txt create mode 100644 testdata/baselines/reference/compiler/prettyFormatLongTypes.js create mode 100644 testdata/baselines/reference/compiler/prettyFormatLongTypes.symbols create mode 100644 testdata/baselines/reference/compiler/prettyFormatLongTypes.types create mode 100644 testdata/tests/cases/compiler/prettyFormatLongTypes.ts diff --git a/testdata/baselines/reference/compiler/prettyFormatLongTypes.errors.txt b/testdata/baselines/reference/compiler/prettyFormatLongTypes.errors.txt new file mode 100644 index 0000000000..8f558eb973 --- /dev/null +++ b/testdata/baselines/reference/compiler/prettyFormatLongTypes.errors.txt @@ -0,0 +1,62 @@ +prettyFormatLongTypes.ts:6:1 - error TS2882: Type: + { b: { c: { e: { f: string; }; }; }; } + +is not assignable to type: + { b: { c: { e: { f: number; }; }; }; } + + The types of 'b.c.e.f' are incompatible between these types. + Type 'string' is not assignable to type 'number'. + +6 a = b; +  ~ + +prettyFormatLongTypes.ts:9:1 - error TS2322: Type 'string' is not assignable to type '{ b: { c: { e: { f: number; }; }; }; }'. + +9 a = c; +  ~ + +prettyFormatLongTypes.ts:12:1 - error TS2322: Type '{ b: { c: { e: { f: number; }; }; }; }' is not assignable to type 'string'. + +12 c = a; +  ~ + +prettyFormatLongTypes.ts:15:1 - error TS2322: Type 'boolean' is not assignable to type 'string'. + +15 c = false; +  ~ + + +==== prettyFormatLongTypes.ts (4 errors) ==== + let a = { b: { c: { e: { f: 123 } } } }; + let b = { b: { c: { e: { f: "123" } } } }; + let c = "test"; + + // both the source and target types are wide enough enough trigger pretty printing + a = b; + ~ +!!! error TS2882: Type: +!!! error TS2882: { b: { c: { e: { f: string; }; }; }; } +!!! error TS2882: +!!! error TS2882: is not assignable to type: +!!! error TS2882: { b: { c: { e: { f: number; }; }; }; } +!!! error TS2882: +!!! error TS2882: The types of 'b.c.e.f' are incompatible between these types. +!!! error TS2882: Type 'string' is not assignable to type 'number'. + + // only the source type is wide enough to trigger pretty printing + a = c; + ~ +!!! error TS2322: Type 'string' is not assignable to type '{ b: { c: { e: { f: number; }; }; }; }'. + + // only the target type is wide enough to trigger pretty printing + c = a; + ~ +!!! error TS2322: Type '{ b: { c: { e: { f: number; }; }; }; }' is not assignable to type 'string'. + + // neither the source nor the target type is wide enough to trigger pretty printing + c = false; + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'string'. + +Found 4 errors in the same file, starting at: prettyFormatLongTypes.ts:6 + diff --git a/testdata/baselines/reference/compiler/prettyFormatLongTypes.js b/testdata/baselines/reference/compiler/prettyFormatLongTypes.js new file mode 100644 index 0000000000..95ea7a0f0a --- /dev/null +++ b/testdata/baselines/reference/compiler/prettyFormatLongTypes.js @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/prettyFormatLongTypes.ts] //// + +//// [prettyFormatLongTypes.ts] +let a = { b: { c: { e: { f: 123 } } } }; +let b = { b: { c: { e: { f: "123" } } } }; +let c = "test"; + +// both the source and target types are wide enough enough trigger pretty printing +a = b; + +// only the source type is wide enough to trigger pretty printing +a = c; + +// only the target type is wide enough to trigger pretty printing +c = a; + +// neither the source nor the target type is wide enough to trigger pretty printing +c = false; + + +//// [prettyFormatLongTypes.js] +let a = { b: { c: { e: { f: 123 } } } }; +let b = { b: { c: { e: { f: "123" } } } }; +let c = "test"; +// both the source and target types are wide enough enough trigger pretty printing +a = b; +// only the source type is wide enough to trigger pretty printing +a = c; +// only the target type is wide enough to trigger pretty printing +c = a; +// neither the source nor the target type is wide enough to trigger pretty printing +c = false; diff --git a/testdata/baselines/reference/compiler/prettyFormatLongTypes.symbols b/testdata/baselines/reference/compiler/prettyFormatLongTypes.symbols new file mode 100644 index 0000000000..3467679c44 --- /dev/null +++ b/testdata/baselines/reference/compiler/prettyFormatLongTypes.symbols @@ -0,0 +1,39 @@ +//// [tests/cases/compiler/prettyFormatLongTypes.ts] //// + +=== prettyFormatLongTypes.ts === +let a = { b: { c: { e: { f: 123 } } } }; +>a : Symbol(a, Decl(prettyFormatLongTypes.ts, 0, 3)) +>b : Symbol(b, Decl(prettyFormatLongTypes.ts, 0, 9)) +>c : Symbol(c, Decl(prettyFormatLongTypes.ts, 0, 14)) +>e : Symbol(e, Decl(prettyFormatLongTypes.ts, 0, 19)) +>f : Symbol(f, Decl(prettyFormatLongTypes.ts, 0, 24)) + +let b = { b: { c: { e: { f: "123" } } } }; +>b : Symbol(b, Decl(prettyFormatLongTypes.ts, 1, 3)) +>b : Symbol(b, Decl(prettyFormatLongTypes.ts, 1, 9)) +>c : Symbol(c, Decl(prettyFormatLongTypes.ts, 1, 14)) +>e : Symbol(e, Decl(prettyFormatLongTypes.ts, 1, 19)) +>f : Symbol(f, Decl(prettyFormatLongTypes.ts, 1, 24)) + +let c = "test"; +>c : Symbol(c, Decl(prettyFormatLongTypes.ts, 2, 3)) + +// both the source and target types are wide enough enough trigger pretty printing +a = b; +>a : Symbol(a, Decl(prettyFormatLongTypes.ts, 0, 3)) +>b : Symbol(b, Decl(prettyFormatLongTypes.ts, 1, 3)) + +// only the source type is wide enough to trigger pretty printing +a = c; +>a : Symbol(a, Decl(prettyFormatLongTypes.ts, 0, 3)) +>c : Symbol(c, Decl(prettyFormatLongTypes.ts, 2, 3)) + +// only the target type is wide enough to trigger pretty printing +c = a; +>c : Symbol(c, Decl(prettyFormatLongTypes.ts, 2, 3)) +>a : Symbol(a, Decl(prettyFormatLongTypes.ts, 0, 3)) + +// neither the source nor the target type is wide enough to trigger pretty printing +c = false; +>c : Symbol(c, Decl(prettyFormatLongTypes.ts, 2, 3)) + diff --git a/testdata/baselines/reference/compiler/prettyFormatLongTypes.types b/testdata/baselines/reference/compiler/prettyFormatLongTypes.types new file mode 100644 index 0000000000..2557832937 --- /dev/null +++ b/testdata/baselines/reference/compiler/prettyFormatLongTypes.types @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/prettyFormatLongTypes.ts] //// + +=== prettyFormatLongTypes.ts === +let a = { b: { c: { e: { f: 123 } } } }; +>a : { b: { c: { e: { f: number; }; }; }; } +>{ b: { c: { e: { f: 123 } } } } : { b: { c: { e: { f: number; }; }; }; } +>b : { c: { e: { f: number; }; }; } +>{ c: { e: { f: 123 } } } : { c: { e: { f: number; }; }; } +>c : { e: { f: number; }; } +>{ e: { f: 123 } } : { e: { f: number; }; } +>e : { f: number; } +>{ f: 123 } : { f: number; } +>f : number +>123 : 123 + +let b = { b: { c: { e: { f: "123" } } } }; +>b : { b: { c: { e: { f: string; }; }; }; } +>{ b: { c: { e: { f: "123" } } } } : { b: { c: { e: { f: string; }; }; }; } +>b : { c: { e: { f: string; }; }; } +>{ c: { e: { f: "123" } } } : { c: { e: { f: string; }; }; } +>c : { e: { f: string; }; } +>{ e: { f: "123" } } : { e: { f: string; }; } +>e : { f: string; } +>{ f: "123" } : { f: string; } +>f : string +>"123" : "123" + +let c = "test"; +>c : string +>"test" : "test" + +// both the source and target types are wide enough enough trigger pretty printing +a = b; +>a = b : { b: { c: { e: { f: string; }; }; }; } +>a : { b: { c: { e: { f: number; }; }; }; } +>b : { b: { c: { e: { f: string; }; }; }; } + +// only the source type is wide enough to trigger pretty printing +a = c; +>a = c : string +>a : { b: { c: { e: { f: number; }; }; }; } +>c : string + +// only the target type is wide enough to trigger pretty printing +c = a; +>c = a : { b: { c: { e: { f: number; }; }; }; } +>c : string +>a : { b: { c: { e: { f: number; }; }; }; } + +// neither the source nor the target type is wide enough to trigger pretty printing +c = false; +>c = false : false +>c : string +>false : false + diff --git a/testdata/tests/cases/compiler/prettyFormatLongTypes.ts b/testdata/tests/cases/compiler/prettyFormatLongTypes.ts new file mode 100644 index 0000000000..39f24b31cd --- /dev/null +++ b/testdata/tests/cases/compiler/prettyFormatLongTypes.ts @@ -0,0 +1,17 @@ +// @pretty: true + +let a = { b: { c: { e: { f: 123 } } } }; +let b = { b: { c: { e: { f: "123" } } } }; +let c = "test"; + +// both the source and target types are wide enough enough trigger pretty printing +a = b; + +// only the source type is wide enough to trigger pretty printing +a = c; + +// only the target type is wide enough to trigger pretty printing +c = a; + +// neither the source nor the target type is wide enough to trigger pretty printing +c = false;