-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve error position/range for arrow functions with expression body #57866
Comments
Seems reasonable. If a return type annotation exists, we can put it there // Arrow function with expression body
// Today
const g1: () => number = () => pipe(1, add(1), identity);
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// Proposed
const g2: () => number = () => pipe(1, add(1), identity);
// ~~
// Or (?)
const g3 = (): number => pipe(1, add(1), identity);
// ~~~~~~ Aside: Try to guess where the error span is in this code! 🫠 const p: () => string = (): number => 32; |
I kind of like moving it to the return type itself, but either way I feel like we should adjust the error message in these cases if possible. Something like
|
I recall that I once suggested putting the error span on the |
The mentioned discussion happened here. I don't mind this change if the team likes it. My main problem with it is that it's a pretty short error span but OTOH you can end up with even single-character error spans anyway so that concern can be ignored. It should be OK - especially with the adjusted error message like the one proposed by @DanielRosenwasser . I'm pretty sure I'll this change, as I've also mentioned in that same comment 😉 :
|
I would like to raise a PR for this change because I think it will significantly improve DX. Can anyone guide me to where in the code I need to make the change? Hopefully I can figure it out from there. |
One way to fix this would be to pass |
Thanks @Andarist but I think there may be a misunderstanding. If I'm not mistaken, I just found this PR (for #52934) of yours which fixed the issue for arrow functions with block bodies. All I want to do here is make the same change for arrow functions with expression (non-block) bodies. I've got a WIP PR here, but I might need some more guidance. |
Fixes microsoft#57866 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1ff3a2acad..2ea2c5ee56 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2527,6 +2527,14 @@ export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpa } } + if (node.parent !== undefined && node.parent.kind === SyntaxKind.ArrowFunction) { + const arrowFn = node.parent as ArrowFunction; + if (arrowFn.body === node && arrowFn.type !== undefined) { + const pos = skipTrivia(sourceFile.text, arrowFn.type.pos); + return getSpanOfTokenAtPosition(sourceFile, pos); + } + } + if (errorNode === undefined) { // If we don't have a better node, then just set the error on the first token of // construct. diff --git a/tests/baselines/reference/conditionalTypes1.errors.txt b/tests/baselines/reference/conditionalTypes1.errors.txt index aa2ae24033..476345ed9f 100644 --- a/tests/baselines/reference/conditionalTypes1.errors.txt +++ b/tests/baselines/reference/conditionalTypes1.errors.txt @@ -73,7 +73,7 @@ conditionalTypes1.ts(160,5): error TS2322: Type 'T' is not assignable to type 'Z Type 'string | number' is not assignable to type 'ZeroOf<T>'. Type 'string' is not assignable to type 'ZeroOf<T>'. conditionalTypes1.ts(263,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'z' must be of type 'T1', but here has type 'Foo<T & U>'. -conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'. +conditionalTypes1.ts(288,33): error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'. Type 'number | boolean' is not assignable to type 'T94<U>'. Type 'number' is not assignable to type 'T94<U>'. Type 'boolean' is not assignable to type 'true'. @@ -465,7 +465,7 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t type T95<T> = T extends string ? boolean : number; const f44 = <U>(value: T94<U>): T95<U> => value; const f45 = <U>(value: T95<U>): T94<U> => value; // Error - ~~~~~ + ~~~ !!! error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'. !!! error TS2322: Type 'number | boolean' is not assignable to type 'T94<U>'. !!! error TS2322: Type 'number' is not assignable to type 'T94<U>'. diff --git a/tests/baselines/reference/mappedTypeConstraints2.errors.txt b/tests/baselines/reference/mappedTypeConstraints2.errors.txt index 0d3b3244c9..098bbd3f4b 100644 --- a/tests/baselines/reference/mappedTypeConstraints2.errors.txt +++ b/tests/baselines/reference/mappedTypeConstraints2.errors.txt @@ -6,7 +6,7 @@ mappedTypeConstraints2.ts(16,11): error TS2322: Type 'Mapped3<K>[Uppercase<K>]' mappedTypeConstraints2.ts(42,7): error TS2322: Type 'Mapped6<K>[keyof Mapped6<K>]' is not assignable to type '`_${string}`'. Type 'Mapped6<K>[string] | Mapped6<K>[number] | Mapped6<K>[symbol]' is not assignable to type '`_${string}`'. Type 'Mapped6<K>[string]' is not assignable to type '`_${string}`'. -mappedTypeConstraints2.ts(51,57): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'. +mappedTypeConstraints2.ts(51,52): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'. mappedTypeConstraints2.ts(82,9): error TS2322: Type 'ObjectWithUnderscoredKeys<K>[`_${K}`]' is not assignable to type 'true'. Type 'ObjectWithUnderscoredKeys<K>[`_${string}`]' is not assignable to type 'true'. @@ -75,7 +75,7 @@ mappedTypeConstraints2.ts(82,9): error TS2322: Type 'ObjectWithUnderscoredKeys<K }; const get = <T extends string>(t: T, foo: Foo<T>): T => foo[`get${t}`]; // Type 'Foo<T>[`get${T}`]' is not assignable to type 'T' - ~~~~~~~~~~~~~~ + ~ !!! error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'. !!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'. diff --git a/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt b/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt index 28091b1745..73c2b637f0 100644 --- a/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt +++ b/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt @@ -1,12 +1,12 @@ fileJs.js(1,1): error TS2304: Cannot find name 'a'. fileJs.js(1,5): error TS2304: Cannot find name 'b'. fileJs.js(1,15): error TS2304: Cannot find name 'd'. +fileJs.js(1,15): error TS2304: Cannot find name 'e'. fileJs.js(1,15): error TS8010: Type annotations can only be used in TypeScript files. -fileJs.js(1,20): error TS2304: Cannot find name 'e'. fileTs.ts(1,1): error TS2304: Cannot find name 'a'. fileTs.ts(1,5): error TS2304: Cannot find name 'b'. fileTs.ts(1,15): error TS2304: Cannot find name 'd'. -fileTs.ts(1,20): error TS2304: Cannot find name 'e'. +fileTs.ts(1,15): error TS2304: Cannot find name 'e'. ==== fileJs.js (5 errors) ==== @@ -18,9 +18,9 @@ fileTs.ts(1,20): error TS2304: Cannot find name 'e'. ~ !!! error TS2304: Cannot find name 'd'. ~ -!!! error TS8010: Type annotations can only be used in TypeScript files. - ~ !!! error TS2304: Cannot find name 'e'. + ~ +!!! error TS8010: Type annotations can only be used in TypeScript files. ==== fileTs.ts (4 errors) ==== a ? b : (c) : d => e @@ -30,6 +30,6 @@ fileTs.ts(1,20): error TS2304: Cannot find name 'e'. !!! error TS2304: Cannot find name 'b'. ~ !!! error TS2304: Cannot find name 'd'. - ~ + ~ !!! error TS2304: Cannot find name 'e'. \ No newline at end of file
🔍 Search Terms
✅ Viability Checklist
⭐ Suggestion
For arrow functions with an expression body, the position of the return type error could be adjusted so it doesn't cover the entire expression. This would make it easier to identify more meaningful type errors that exist within the expression.
📃 Motivating Example
Consider the following example where we're using the
pipe
function inside arrow functions and theadd
function is missing.Both of these arrow functions have two type errors:
The first type error can be fixed by addressing the second type error.
When the arrow function has a block body, these two error messages are highlighted separately:
However, when the arrow function has an expression body, the range of the return type error covers the entire expression:
This makes it very difficult to spot the inner type error for
Cannot find name 'add'
, especially in more advanced examples.To help with this I was wondering if we could move the position of the return type so it doesn't cover the entire expression. Perhaps it could be positioned on the
=>
that appears immediately before the expression? This would be closer to the behaviour of arrow functions with body blocks.Note this issue does not occur when we're not using the
pipe
function. I believe this is because TypeScript treats the return type ofadd(1)
asany
, whereas withpipe
the type argumentB
will be inferred asunknown
(which is desired in other cases).💻 Use Cases
See above.
The text was updated successfully, but these errors were encountered: