let x = { a: { b: { c: { d: { e: { f() { return { g: "hello" }; } } } } } } };
let y = { a: { b: { c: { d: { e: { f() { return { g: 12345 }; } } } } } } };
x = y;
Existing Behavior
Type '{ a: { b: { c: { d: { e: { f(): { g: number; }; }; }; }; }; }; }' is not assignable to type '{ a: { b: { c: { d: { e: { f(): { g: string; }; }; }; }; }; }; }'.
Types of property 'a' are incompatible.
Type '{ b: { c: { d: { e: { f(): { g: number; }; }; }; }; }; }' is not assignable to type '{ b: { c: { d: { e: { f(): { g: string; }; }; }; }; }; }'.
Types of property 'b' are incompatible.
Type '{ c: { d: { e: { f(): { g: number; }; }; }; }; }' is not assignable to type '{ c: { d: { e: { f(): { g: string; }; }; }; }; }'.
Types of property 'c' are incompatible.
Type '{ d: { e: { f(): { g: number; }; }; }; }' is not assignable to type '{ d: { e: { f(): { g: string; }; }; }; }'.
Types of property 'd' are incompatible.
Type '{ e: { f(): { g: number; }; }; }' is not assignable to type '{ e: { f(): { g: string; }; }; }'.
Types of property 'e' are incompatible.
Type '{ f(): { g: number; }; }' is not assignable to type '{ f(): { g: string; }; }'.
Types of property 'f' are incompatible.
Type '() => { g: number; }' is not assignable to type '() => { g: string; }'.
Type '{ g: number; }' is not assignable to type '{ g: string; }'.
Types of property 'g' are incompatible.
Type 'number' is not assignable to type 'string'.
Proposed
Type '{ a: { b: { c: { d: { e: { f(): { g: number; }; }; }; }; }; }; }' is not assignable to type '{ a: { b: { c: { d: { e: { f(): { g: string; }; }; }; }; }; }; }'.
'a.b.c.d.e.f(...).g' is incompatible between these types because 'number' is not assignable to type 'string'
Individual multiline diagnostic messages I think require a couple changes to our diagnostic message chain builder, but I’d be down for considering it, personally. It’s worth remembering that it could still occur in a pyramid, so you could have something like
which is… maybe better? I dunno, linebreaks, man. I know I probably don’t wanna see
so there’d probably need to be some kind of length heuristic, at least.
Brainstorming about the (currently) impossible here, I would say that the thing that
gitdoes on highlighting diffs (viadiff-highlight) would be super interesting here:Would the TypeScript team be open to a pipe dream issue about this for some future?
May I suggest a small whitespace tweak to make the new and awesome error a bit more readable? Instead of
move the
is not assignable toto the end of the first line, so the types vertically align for easier scanning and vertical comparison:or, to minimize horizontal scrolling/overflow place it in a line in between the types:
Happy to make such a PR 😃
I explored this a bit with @alloy when thinking about whether we could also use bold/italics to also provide emphasis, instead we used
{ ..., b: { ... c: } }to provide focus while keeping the pyramid of nested errors.I prefer the version in OP. I wonder if turning it into three lines would make it more readable:
Then you get to see the full message without scrolling, and can more easily compare the types.
Ideally, if we’re in an environment where we can use bold:
Which would really help lead someone’s eyes to the right spots to make their own decisions.
@RyanCavanaugh Thank you for your reply. Reversing the order is one dimension and I agree this is not a perfect solution everywhere.
What I had in mind was making the error message say which object is missing the index signature. Right now we only know one of them is missing it.
My hope is this could point the users into the right direction: finding a way to update the object in a way that preserves its index signature (which the spread operator
...doesn’t do).I’d like to try this.
@karol-majewski “just print the error messages in reverse order” is a common suggestion; see https://github.com/microsoft/TypeScript/issues/29759#issuecomment-460838893 . TL;DR it makes some things better and other things worse
@weswigham no worries. I’m sure it will be. Thanks for letting me know.
I think this issue is a good place to leave notes and questions 👍
@DanielRosenwasser In that case, you might want to assign this to someone else. I can’t really commit to a deadline right now.