microsoft / microsoft/TypeScript

Improve error position/range for arrow functions with expression body

Open
#57,866 8 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Domain: Error Messages Experience Enhancement Help Wanted Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
1d 19h
Merged PRs (30d)
117

Description

🔍 Search Terms
  • arrow function
  • return type
  • type error position/range
✅ 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 the add function is missing.

declare const pipe: <A, B, C>(a: A, ab: (a: A) => B, bc: (b: B) => C) => C;

// declare const add: (x: number) => (n: number) => number;
declare const identity: <T>(x: T) => T;

// Arrow function with block body
const f = (): number => {
  return pipe(1, add(1), identity);
};

// Arrow function with expression body
const g = (): number => pipe(1, add(1), identity);

Both of these arrow functions have two type errors:

  • For the return value: Type 'unknown' is not assignable to type 'number'.
  • Cannot find name 'add'.

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:

image

However, when the arrow function has an expression body, the range of the return type error covers the entire expression:

image

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 of add(1) as any, whereas with pipe the type argument B will be inferred as unknown (which is desired in other cases).

const g2 = (): number => identity(add(1)(1));
image
💻 Use Cases

See above.

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

No source file or test is named. Start by compiling the motivating example with expression-bodied and block-bodied arrow functions, then trace where the return-type diagnostic range is produced. Done means the expression-bodied return error no longer covers the whole expression while the inner missing-name error remains separately reported.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.