Skip to content

Implicit function typesΒ #44681

@mindplay-dk

Description

@mindplay-dk

Suggestion

πŸ” Search Terms

implicit function types

βœ… Viability 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, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

function literals should implicitly have a type - the same way class literals do.

πŸ“ƒ Motivating Example

Currently, to use dependency injection with functions, I have to explicitly add types for function literals, like so:

function sayHello(user: string) {
    window.alert(`Hello, ${user}!`);
}

type sayHello = typeof sayHello; // πŸ‘ˆ this

function start(sayHello: sayHello) {
    // ...
}

Intuitively, before you try that, you're going to try something this:

function sayHello(user: string) {
    window.alert(`Hello, ${user}!`);
}

function start(sayHello: typeof sayHello) {
    // ...
}

That doesn't work.

Contrast function declarations with class declarations, which "just works":

class HelloSayer {
    // ...
}

function start(sayHello: HelloSayer) {
    // ...
}

Why do class declarations get a type, and function declarations don't?

It's also not unconventional in JS to write "constructor" functions like this:

function HelloSayer(user: string) {
    return {
        sayHello() {
            window.alert(`Hello, ${user}!`);
        }
    }
}

function start(sayHello: HelloSayer) {
    // ...
}

There's even been popular talk of "new keyword considered harmful" over the years.

In JavaScript, the result of a class declaration isn't very different from the result of a function declaration - both result in a function type value in the same scope. Both are declarations parsed during the first pass, meaning you can reference them recursively.

And functions do have a type in TypeScript: you can extract it with typeof, and you can import it from another module with import type, so why is this type "hidden" or inaccessible from type-hints? Why do classes have this special status?

I think this could be "fixed" retroactively without any breaking changes, if declaration merging could be applied, allowing existing code to explicitly declare an identical function-type with e.g. type HelloSayer = typeof HelloSayer, since these would almost definitely have identical types. (Or, at least, this would be a very minor breaking change, only affecting codebases where some types are currently inconsistent with the types of function literals with the same name.)

πŸ’» Use Cases

Dependency injection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions