Skip to content
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 messages for return values within annotated arrow functions. #40163

Open
5 tasks done
threehams opened this issue Aug 21, 2020 · 0 comments
Open
5 tasks done
Labels
Experience Enhancement Noncontroversial enhancements Suggestion An idea for TypeScript
Milestone

Comments

@threehams
Copy link

Search Terms

Domain: Error Messages arrow function annotation fresh return type

Suggestion

Currently, when an arrow function is annotated with a function signature type, any errors which occur point to the variable being assigned. Here's an example:

type SplitName = (name: string) => {
    first: string;
    last: string;
}

const splitName: SplitName = (name) => {
    // ^ Type '(name: string) => { first: string; }' is not assignable to type 'SplitName'.
    //     Property 'last' is missing in type '{ first: string; }' but required in type '{ first: string; last: string; }'.(2322)
    //   input.tsx(3, 5): 'last' is declared here.
    const [first, lost] = name.split(" ");
    return { first, lost };
}

Because this function's arguments match the signature, it should be possible to give a more specific error:

const splitName: SplitName = (name) => {
    const [first, lost] = name.split(" ");
    return { first, lost };
    //              ^ Type '{ first: string; lost: string; }' is not assignable to type '{ first: string; last: string; }'.
    //                  Object literal may only specify known properties, and 'lost' does not exist in type '{ first: string; last: string; }'.
}

This is very helpful in more complex cases.

This behavior would match the error message shown when manually annotating the return value of the function. Using ReturnType<> matches the proposed error message exactly, for all return values I've tried, provided that the type is not a union:

const splitName: SplitName = (name): ReturnType<SplitName> => {
    const [first, lost] = name.split(" ");
    return { first, lost };
    //              ^ Type '{ first: string; lost: string; }' is not assignable to type '{ first: string; last: string; }'.
    //                  Object literal may only specify known properties, and 'lost' does not exist in type '{ first: string; last: string; }'.
}

It might be best to avoid applying this elaboration to union types of any kind, as the error messages end up being applied to both the variable and the return value, which ends up being worse than the current error:

type SplitNameObj = (name: string) => {first: string, last: string};
type SplitNameTuple = (name: string) => [first: string, last: string];
type SplitName = SplitNameObj | SplitNameTuple;

const splitName: SplitName = (name): ReturnType<SplitName> => {
    // ^ Type '(name: string) => { first: string; last: string; } | [first: string, last: string]' is not assignable to type 'SplitName'.
    //     Type '(name: string) => { first: string; last: string; } | [first: string, last: string]' is not assignable to type 'SplitNameObj'.
    //       Type '{ first: string; last: string; } | [first: string, last: string]' is not assignable to type '{ first: string; last: string; }'.
    //         Type '[first: string, last: string]' is not assignable to type '{ first: string; last: string; }'.(2322)

    const [first, lost] = name.split(" ");
    const returnValue = { first, lost };
    return returnValue;
    //     ^ Type '{ first: string; lost: string; }' is not assignable to type '{ first: string; last: string; } | [first: string, last: string]'.
    //         Property 'last' is missing in type '{ first: string; lost: string; }' but required in type '{ first: string; last: string; }'.(2322)
    //       input.tsx(1, 55): 'last' is declared here.
}

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@RyanCavanaugh RyanCavanaugh added Experience Enhancement Noncontroversial enhancements Suggestion An idea for TypeScript labels Aug 25, 2020
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Experience Enhancement Noncontroversial enhancements Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants