Open OliverJAsh opened 8 months ago
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
This function returns the type 'unknown' which is not assignable to its declared type 'number'.
I recall that I once suggested putting the error span on the =>
for this exact reason, by analogy to the return
in the block function. IIRC @Andarist objected.
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 prefer to highlight smaller spans over huge ones
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.
checkFunctionExpressionOrObjectLiteralMethodDeferred
passed down effectiveCheckNode
to checkTypeAssignableToAndOptionallyElaborate
both as the checked expression and the error node. The error node reaches getErrorSpanForNode
and that's where the error span gets computed.
One way to fix this would be to pass node
(aka the whole arrow function) as errorNode
to checkTypeAssignableToAndOptionallyElaborate
and then tweak the logic in getErrorSpanForArrowFunction
. As it is, this wouldn't fix the issue because getErrorSpanForArrowFunction
highlights the first line... but in your case that's the whole thing ;p
π 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.