question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add support for explicitly indicating that a function's return type is inferred.

See original GitHub issue

Search Terms

explicit infer return type

Suggestion

Add support for a special infer type that can be used to explicitly indicate that the return type of a function should be inferred from its implementation.

The presence of an explicit infer return type for a function (or arrow function) would have identical observable behavior as if the return type wasn’t specified: the return type is inferred from the implementation.

The difference is that the function now technically has a return type specified to indicate that the developer explicitly made a decision to allow the return type to be inferred, rather than simply forgetting to think about what the return type should be.

Use Cases

In a project with strict/explicit code style, it is desirable in general to use a linting rule that requires all functions to have a return type specified (The tslint “typedef” rule for “call-signature”, for example: https://palantir.github.io/tslint/rules/typedef/).

There are, however, some situations where the return type of a function is a complex type (involving generics, etc.), such that the return type is more naturally inferred from the implementation of the method, as opposed to it being natural to know the intended return type ahead of time.

In such situations, it would be nice to have the option to explicitly indicate the intent for the compiler to infer the return type of the function. This would both clearly communicate this explicit intent to other developers reading the code, and could be used to satisfy code style and linting rules that require functions to have a return type specified.

Why not just disable the linting rule on a case-by-case basis?

Yes, tslint’s support of line-level rule disabling could be used to temporarily disable the linting rule and allow you to omit the return type in such situations. But I feel that language-level support for an explicit infer return type would be much more powerfully clear and expressive. It is especially worthwhile if it is fairly low effort/risk to implement.

Additionally, there is not enough granularity to disable the “typedef” rule ONLY for the “call-signature” context. Disabling “typedef” on that line would also disable checks for parameter types in the signature, which is undesirable.

Examples

A simple example is helper methods for unit tests that use enzyme. Let’s say you have a custom React component named MyButtonComponent, and you would like a helper function to find the “close” button within some other outer component:

import { ReactWrapper } from "enzyme";
import { MyButtonComponent } from "./MyButtonComponent";

function findCloseButton(wrapper: ReactWrapper): infer {
    return wrapper.find(MyButtonComponent).filter(".close-button");
}

In this case, the line return wrapper.find(MyButtonComponent).filter(".close-button") returns a strictly typed ReactWrapper<P> type where P is the Props type of the MyButtonComponent component, which allows type-safe access to the current values of the component’s props via ReactWrapper’s props() method .

Manually writing out the correct return type of the helper function above would be quite tedious and provide very little benefit. Especially if the Props interface for MyButtonComponent is not readily available either because it is not exported, or because MyButtonComponent was created by a complex generic higher order component (HOC). The effort of correctly writing out the return type outweighs its benefits in a situation like this.

Inferring implicit any

In the following examples, there is no implementation to infer the return type from:

declare function foo(a: number): infer;

interface Bar {
    bar(b: string): infer;
}

The infer type is actually quite useless here and is guaranteed to be an implicit any type. Perhaps it would make sense to ONLY allow the infer type in contexts where there is something to infer from? If so, then the above examples would be compiler errors because there is nothing to infer from.

Another reasonable option may be to allow it to infer an implicit any type in such a way that will fail to compile when using the --noImplicitAny compiler option. This option is a bit less direct, but perfectly acceptable if it is the most “natural” and low-risk/effort option based on the current structure of code.

Partially Inferred Types

An expansion on this idea would be partially inferred return types:

function foo(value: number): Promise<infer> {
    // return value must be assignable to Promise<any>
    // return type is inferred to be Promise<number>
    return Promise.resolve(value);
}

interface Pair<A, B> {
    a: A;
    b: B
}

function bar(value: number): Pair<infer, infer> {
    // return value must be assignable to Pair<any, any>
    // return type is inferred to be Pair<number, boolean>
    return {
        a: value,
        b: value % 2 === 0
    };
}

This would provide a nice blend of compile time validation that you are returning something in the basic format that you intend, but let the compiler infer complicated parts of the type that are not worth the effort of manually constructing/writing.

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. new expression-level syntax)

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:2
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
UselessPicklescommented, Dec 6, 2018

(EDIT: Added this to the main issue comment)

An expansion on this idea would be partially inferred return types:

function foo(value: number): Promise<infer> {
    // return value must be assignable to Promise<any>
    // return type is inferred to be Promise<number>
    return Promise.resolve(value);
}

interface Pair<A, B> {
    a: A;
    b: B
}

function bar(value: number): Pair<infer, infer> {
    // return value must be assignable to Pair<any, any>
    // return type is inferred to be Pair<number, boolean>
    return {
        a: value,
        b: value % 2 === 0
    };
}

This would provide a nice blend of compile time validation that you are returning something in the basic format that you intend, but let the compiler infer complicated parts of the type that are not worth the effort of manually constructing/writing.

1reaction
RyanCavanaughcommented, Aug 22, 2018

What will we do when TSLint adds a rule that bans : infer ? 🤔

Read more comments on GitHub >

github_iconTop Results From Across the Web

Add support for explicitly indicating that a function's return type ...
Add support for a special infer type that can be used to explicitly indicate that the return type of a function should be...
Read more >
Type inference on method return type - scala - Stack Overflow
The return type of a method is either the type of the last statement in the block that defines it, or the type...
Read more >
explicit-function-return-type | typescript-eslint
This rule enforces that functions do have an explicit return type annotation. .eslintrc.cjs. module.exports = {
Read more >
The Infer function return type refactoring for TypeScript
Today's VS Code tip: Infer function return typeUse this refactoring to quickly add explicit type annotations to functions /methods in ...
Read more >
how to infer a return type from this function? : r/typescript - Reddit
Thanks for any help. ... Also, I'm a fan of explicit return types. ... Gives 100 Reddit Coins and a week of r/lounge...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found