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

Typing a non-arrow function makes for some partially working result #56636

Closed
ericmorand opened this issue Dec 1, 2023 · 8 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@ericmorand
Copy link

ericmorand commented Dec 1, 2023

πŸ”Ž Search Terms

type function
type non arrow function

πŸ•— Version & Regression Information

I didn't test outside of TS 5.2.2 but I assume it was not working before either.

⏯ Playground Link

No response

πŸ’» Code

type MyFunction = (foo: number) => string;

<MyFunction>function doSomething(foo) {
    return `${foo}`;
}

doSomething(5);

πŸ™ Actual behavior

Here, both foo and the return type of doSomething are perfectly inferred - returning a string would fail the compilation, just like using foo as anything else than a number.

But...the next instruction doSomething(5); throws a "TS2552: Cannot find name doSomething." which obviously makes the code useless.

πŸ™‚ Expected behavior

I'm not sure. Ideally I would expect that it works - i.e. that using doSomething remains possible - but I'm not sure it was ever intended to type non-arrow function at all.

What is strange though is that it seems to work just fine, until we try to actually use the function.

Additional information about the issue

This is related to Rollup plugin development where plugin hooks are non-arrow function. It would be amazing if we could type them individually to organize the code better instead of having to put everything under an object definition typed as a Plugin, like this:

const plugin: Plugin = {
    transform(this, code, id) { // all parameters types are perfectly inferred
    }
};

With this syntax, obviously, the transform method type is correctly inferred but it would be cool if we were allowed to write it this way for better reusability:

<Plugin["transform"]>function transform(this, code, id) { // all parameters types are perfectly inferred
}

const plugin: Plugin = {
    transform
};

See rollup/rollup#5277

@ericmorand ericmorand changed the title Typing a non-arriw function leads to some partially working result Typing a non-arrow function makes for some partially working result Dec 1, 2023
@jcalz
Copy link
Contributor

jcalz commented Dec 1, 2023

Duplicate of #22063. This is a missing feature, not a bug.

@ericmorand
Copy link
Author

Interesting, thanks for the heads-up. What tricked me is the fact that it seems to work using the <Type>function ... syntax.

@MartinJohns
Copy link
Contributor

Functions can be expressions as well, so TypeScript probably interprets it as an expression that is being type asserted, not a top-level function declaration.

const test = <any>function foo() {}

@ericmorand
Copy link
Author

Good point.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Dec 1, 2023
@nmain
Copy link

nmain commented Dec 1, 2023

Functions can be expressions as well, so TypeScript probably interprets it as an expression that is being type asserted, not a top-level function declaration.

I believe that's what's happening, as you can see in the JS output it uses parens to maintain the function expression (and not function definition) syntax:

(function doSomething(foo) { ... })

Given that JS output, the runtime JS behavior is understandable

@ericmorand
Copy link
Author

So basically everything works as expected and it is perfectly possible to type a function - but it is considered as an expression that needs to be assigned to a variable to be referenced later. Did I understand things properly?

@nmain
Copy link

nmain commented Dec 1, 2023

Yes, that's always been allowed (and will get a good contextual type and everything):

var x: (value: string) => string = function bah(a) {
    return a + 4;
}

But it's a different thing than a function definition and behaves differently at runtime.

@ericmorand
Copy link
Author

Many thanks. I was totally unaware of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants