Skip to content

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

Closed
@tempname11

Description

@tempname11

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions