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

Proposal: function return types #14765

Closed
mmkal opened this issue Mar 21, 2017 · 2 comments
Closed

Proposal: function return types #14765

mmkal opened this issue Mar 21, 2017 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@mmkal
Copy link

mmkal commented Mar 21, 2017

Index types are awesome. But it'd be even more awesome if advanced types could go a step further, and allow getting the types that a function returns:

Say you have a function that transforms some data:

const formatPerson = (person: Person) => ({
    name: person.firstName + person.lastName,
    age: Date.now() - person.birthTime
});

There's currently no (good) way to get the type of the return value, even though it's completely determinstic - the compiler knows that it's of type { name: string, age: number }.

It'd be great if we could do something like this:

const greetPerson = (formatted: formatPerson()) => {
    console.log('hi', formatted.name);
};

Or to reuse the type, type FormattedPerson = typeof formatPerson();.

Where using the () tells the compiler to use the return type of the formatPerson function.
Currently the only way something like this is possible is to trick the compiler into giving you this type information, but in a very hacky way that involves creating a real variable at runtime:

const dummyFormattedPerson = null as {} && formatPerson(null);

const greetPerson = (formatted: typeof dummyFormattedPerson) => {
    console.log('hi', formatted.name);
};

Is there any reason this couldn't be done? The compiler has done the hard part of tracking the type information already, so it would only require adding the syntax (which is always invalid right now, so it'd unambiguous and backwards compatible).

This might also be useful for doing things like tracking the types for utility function that promisify an entire object that uses callbacks:

type Promisified<T> = {
    [P in keyof T]: (...args: any[]) => Promise<T[P]()>;
};

The above example is pretty far from perfect though - to be complete there would need to be more advanced types, like function parameter types, and constraints for keyof to include only functions and not other properties.

Some potential edge-cases/pitfalls:

  • Overloaded functions - two different overloads of a function definition could have different return types. e.g. format(x: string): number and format(x: string, y: string): number[]. The solution for this could be either:

    • Have the return type be a intersection type. e.g. typeof format() is number | number[].
    • Allow "passing in" types to the function, as if they were real arguments. e.g. typeof format(string) is number and typeof format(string, string) is number[]. Then I guess as a convenience you could have typeof format() being number | number[] as above.
  • Clashing with the "real" typeof operator. This should be handled by only looking for this syntax when the compiler is expecting a type annotation, e.g. decorating a variable (x: format()) or in a type assignment (type formatted = typeof format()). I imagine this is exactly how index types work too.

@RyanCavanaugh
Copy link
Member

See #6606

@mmkal
Copy link
Author

mmkal commented Mar 27, 2017

@RyanCavanaugh great! Glad to see it might be in the pipeline.

@mmkal mmkal closed this as completed Mar 27, 2017
@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 27, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants