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

TS 3.9 - No overload matches this call #38241

Closed
alan-agius4 opened this issue Apr 29, 2020 · 8 comments
Closed

TS 3.9 - No overload matches this call #38241

alan-agius4 opened this issue Apr 29, 2020 · 8 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@alan-agius4
Copy link
Contributor

TypeScript Version: 3.9.1-rc

Search Terms:
No overload matches this call

Code

export interface SyncNgccOptions {
    basePath: string;
    targetEntryPointPath?: string;
    async?: false;
}

export type AsyncNgccOptions = Omit<SyncNgccOptions, 'async'> & { async: true };

export function process(options: AsyncNgccOptions): Promise<void>;
export function process(options: SyncNgccOptions): void;
export function process(options: AsyncNgccOptions | SyncNgccOptions): void | Promise<void> {
    return mainNgcc(options);
}


export function mainNgcc(options: AsyncNgccOptions): Promise<void>;
export function mainNgcc(options: SyncNgccOptions): void;
export function mainNgcc(options: AsyncNgccOptions | SyncNgccOptions): void | Promise<void> {
}

Expected behavior:
No error as per TS 3.8

Actual behavior:
Error

No overload matches this call. Overload 1 of 2, '(options: AsyncNgccOptions): Promise', gave the following error. Argument of type 'SyncNgccOptions | AsyncNgccOptions' is not assignable to parameter of type 'AsyncNgccOptions'. Type 'SyncNgccOptions' is not assignable to type 'AsyncNgccOptions'. Type 'SyncNgccOptions' is not assignable to type '{ async: true; }'. Types of property 'async' are incompatible. Type 'false | undefined' is not assignable to type 'true'. Type 'undefined' is not assignable to type 'true'. Overload 2 of 2, '(options: SyncNgccOptions): void', gave the following error. Argument of type 'SyncNgccOptions | AsyncNgccOptions' is not assignable to parameter of type 'SyncNgccOptions'. Type 'AsyncNgccOptions' is not assignable to type 'SyncNgccOptions'. Types of property 'async' are incompatible. Type 'true' is not assignable to type 'false | undefined'.

Playground Link: https://www.typescriptlang.org/v2/en/play?ts=3.9.0-beta#code/KYDwDg9gTgLgBASwHY2FAZgQwMbDgZQE8lsA5Ac22wHkwYEIkBnOAbwCg4u4AjTJ4AAVMMABYAuOExhRk5ANyduMTFHLAYAURRRCgiMhjCxAfknTZSBUq79i2M3CwAbAYoC+7dqEiw4MQjA8AEEmewoqWnpGFgBeOGoAWwQYAB4iEgiaOgZmABo4AHI7EkKAPjgAMjY4EuxJGQBXPHdFb3BoeHRGkmikODAoCFwmJgAKCByYyVDwymy+pgBKSUEh5IFUgDcDABMyxR9Opx7sPoGhkfHJxckMsnmo3OXJHYRdw46-bt7ci+HgKMJlNmDMwplHiCWAAfAhzSJQlZwN67OCwtYQDbAbZ7CocbhwKAaRpQfqJTDILLAxZLDxedq+Lqnc7kynzanPMHwhbPJEYrE494HBnHH5nP6spBUm6cuEQhE0157T6Mk6-RhwSXSqFc+U8mJouUPBW8pXvQ38hCbFF49ieIA

Related Issues:

@kitsonk
Copy link
Contributor

kitsonk commented Apr 29, 2020

It is a breaking changed covered in #37195. async? being optional is causing your problem. It was unsound code before that is now being caught.

@petebacondarwin
Copy link
Contributor

This convoluted typing was created because we could not work out a better way to support a function that if invoked with async: true would return a Promise or void otherwise.

@kitsonk - do you have a suggestion for how we can support this scenario?

@gkalpak
Copy link

gkalpak commented Apr 29, 2020

@DanielRosenwasser
Copy link
Member

I'm tempted to mark Working as Intended but I'm not totally clear exactly why Omit<..., "async"> & { async: true } causes issues. @ahejlsberg care to weigh in?

@kitsonk
Copy link
Contributor

kitsonk commented Apr 29, 2020

@DanielRosenwasser not to step on Ander's toes, but I believe it is very intentional, because #37195 was specifically to fix unsafe situations with Omit and intersection types brought up in #36604.

@DanielRosenwasser
Copy link
Member

Oh, I see - I wasn't looking at where the error was being issued. This makes sense.

@gkalpak technically you could condense the whole thing down to

// Overload
export function process<T extends AsyncNgccOptions | SyncNgccOptions>(options: T):
  T extends AsyncNgccOptions ? Promise<void> : void;

// Implementation
export function process(options: AsyncNgccOptions | SyncNgccOptions): void | Promise<void> {
    return mainNgcc(options);
}

@DanielRosenwasser DanielRosenwasser added the Working as Intended The behavior described is the intended behavior; this is not a bug label Apr 29, 2020
@alan-agius4
Copy link
Contributor Author

Thanks guys for your input.

@gkalpak
Copy link

gkalpak commented Apr 30, 2020

Thx, @DanielRosenwasser!

FWIW, I still find overloads more readable (and wish TypeScript would recognize the 3rd overload signature from the implementation):

function process(options: SyncNgccOptions): void;
function process(options: AsyncNgccOptions): Promise<void>;
function process(options: SyncNgccOptions | AsyncNgccOptions): void | Promise<void> {
    // ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants