microsoft / microsoft/TypeScript

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

Open
#45,896 14 comments 25 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.4k
Avg merge
1d 19h
Merged PRs (30d)
117

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue gives type-assignment diagnostic examples and proposes a configurable 30-character threshold, but names no files or tests. Start by locating the compiler entry point that formats TS2322 messages. Done means long type text is split with the requested colons and newlines, while the short examples remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.