Skip to content

Allow contextual typing for "one-shot" functions #30017

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

Closed
5 tasks done
tempname11 opened this issue Feb 21, 2019 · 3 comments
Closed
5 tasks done

Allow contextual typing for "one-shot" functions #30017

tempname11 opened this issue Feb 21, 2019 · 3 comments
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript

Comments

@tempname11
Copy link

tempname11 commented Feb 21, 2019

Search Terms

contextual typing
infer function arguments
noImplicitAny

Suggestion

TypeScript has contextual typing. It could be extended in a single specific way, improving its usability.

These two code snippets are fully equivalent. The only difference is naming the function (and using it exactly once). Yet, with noImplicitAny you are required to add type annotations for all arguments of the function.

The proposal is to allow contextual typing to include functions which are only ever used exactly once and are defined in the same module (i.e. they could be inlined at the use site). This seems a relatively cheap addition to the inference mechanism, compared to the benefits.

Use Cases

This would help whenever you want to factor out code into a separate helper function for clarity. Currently this incurs a cost of having to provide all types for the arguments, which can be cumbersome (not all types may be in scope and you might have to import them; some may be derivations or refinements of types you can name).

Examples

This could be applied to any code, here's a Redux-like example which probably looks familiar to most.

// types.ts

type State = {/* ... */};
type Action =
    | { type: 'FOO', foo: { inner: number } }
    | { type: 'BAR', bar: string }

// example.ts
import { State, Action } from './types';

const fooLogic = (foo) => { // inferred as `any`!
    return {/* ... */}
}

const reducer = (state: State, action: Action) => {
    switch (action.type) {
        case 'FOO': {
          return fooLogic(action.foo);
        }
        default: return state;
    }
}

// there is no good way to provide a type annotation
// for `foo` in `fooLogic` without exporting more specific
// types in `types.ts`. Which, if they are only ever
// used here once, is just boilerplate and code noise.

This feature could also potentially help with splitting React function components:

function A(props) {
    return null; // * some content here */
}

function B(props) {
    return null; // * some content here */
}

function Component(props: Props) {
    return (
        <>
            <A a={someTransformation(props)} />
            <B b={someOtherTransformation(props)} />
        </>
    )
}

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.
@DanielRosenwasser DanielRosenwasser added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Feb 22, 2019
@RyanCavanaugh RyanCavanaugh added Declined The issue was declined as something which matches the TypeScript vision and removed In Discussion Not yet reached consensus labels Apr 1, 2019
@RyanCavanaugh
Copy link
Member

See notes in #30696 - this behavior would manifest itself as appearing to be a bug in the compiler ("Function gets implicit any type if used twice") and the general solution of finding all references to form a unified contextual type is contrary to our current inference approach.

@zpdDG4gta8XKpMCd
Copy link

zpdDG4gta8XKpMCd commented Apr 2, 2019

a cost of having to provide all types for the arguments, which can be cumbersome

and it is considered, without any discussion and thumbs up, wow...

@tempname11
Copy link
Author

@RyanCavanaugh Thanks for the feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Declined The issue was declined as something which matches the TypeScript vision Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants