Skip to content

Use the width of a type to add newlines in type assignment error messages #45896

Open
microsoft/typescript-go
#1099
@orta

Description

@orta

Today we ship a one-type-fits-all style for printing type is not assignable to type messages. We'd like to improve this in a pretty simple manner: by occasionally adding newlines. For example with this arbitrary comparison:

let a = { b: { c: { e: { f: 123 } } } };
let b = { b: { c: { e: { f: "123" } } } };
a = b;

Looks like this today:

src/vendor/ata/index.ts(12,1): error TS2322: 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'.

I propose that because both of the printed types are longer than 20-30 chars, then we switch to:

src/vendor/ata/index.ts(12,1): error TS2322: 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'.

Key details

  • Strip the quotes around the type
  • Add colons and newlines if the type is over a certain size. Let's call it 30 characters for now, and make it easy to change and we can experiment at the final stages of review.

Some Examples

No changes

let a = 123
let b = "abc"
a = b
  • Before: src/index.ts(21,1): error TS2322: Type 'string' is not assignable to type 'number'.
  • After: src/index.ts(21,1): error TS2322: Type 'string' is not assignable to type 'number'.

No change! (Though a part of me does really want to drop the quotes for primitives)

window = {}
Type '{}' is not assignable to type 'Window & typeof globalThis'.
  Type '{}' is missing the following properties from type 'Window': clientInformation, closed, customElements, devicePixelRatio, and 189 more. (2322)

No change! {} and Window & typeof globalThis are too small.

Changing one

window = addEventListener
src/index.ts(1,1): error TS2322: Type '{ <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void; (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | ... 1 more ... | undefined): void; }' is not assignable to type 'Window & typeof globalThis'.
   Type '{ <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void; (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | ... 1 more ... | undefined): void; }' is missing the following properties from type 'Window': HTMLDocument, closed, customElements, devicePixelRatio, and 187 more.
src/vendor/ata/index.ts(12,1): error TS2322: Type: 
{ <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void; (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | ... 1 more ... | undefined): void; }

is not assignable to type:
Window & typeof globalThis

  Type '{ <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void; (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | ... 1 more ... | undefined): void; }' is missing the following properties from type 'Window': HTMLDocument, closed, customElements, devicePixelRatio, and 187 more.

Changing both

Animation = AnalyserNode
index.ts(12,1) Type '{ new (context: BaseAudioContext, options?: AnalyserOptions | undefined): AnalyserNode; prototype: AnalyserNode; }' is not assignable to type '{ new (effect?: AnimationEffect | null | undefined, timeline?: AnimationTimeline | null | undefined): Animation; prototype: Animation; }'.
  Types of property 'prototype' are incompatible.
    Type 'AnalyserNode' is missing the following properties from type 'Animation': currentTime, effect, finished, id, and 18 more.
index.ts(12,1) Type:
{ new (context: BaseAudioContext, options?: AnalyserOptions | undefined): AnalyserNode; prototype: AnalyserNode; }

is not assignable to type:
{ new (effect?: AnimationEffect | null | undefined, timeline?: AnimationTimeline | null | undefined): Animation; prototype: Animation; }

  Types of property 'prototype' are incompatible.
    Type 'AnalyserNode' is missing the following properties from type 'Animation': currentTime, effect, finished, id, and 18 more.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Effort: CasualGood issue if you're already used to contributing to the codebase. Harder than "good first issue".Experience EnhancementNoncontroversial enhancementsGood First IssueWell scoped, documented and has the green lightHelp WantedYou can do thisSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions