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

Compiler fails to infer type in overloaded functions #33704

Closed
boris-kolar opened this issue Oct 1, 2019 · 6 comments
Closed

Compiler fails to infer type in overloaded functions #33704

boris-kolar opened this issue Oct 1, 2019 · 6 comments
Labels
Duplicate An existing issue was already created

Comments

@boris-kolar
Copy link

TypeScript Version: 3.6.3
Search Terms: overload overloaded infer type flow

Code

function foo(): void
function foo(a: string, b: string): void
function foo(a?: string, b?: string): void {
    if (!a) return
    console.log(a.length + b.length)
}

Expected behavior:
The code compiles (the compiler deduces b != null from the set of possible overloads)

Actual behavior:
bug.ts:5:28 - error TS2532: Object is possibly 'undefined'.

Playground Link:
https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABMOcAUBKAXIgbnGAEwChRJYFlU0BDHAZygCcYwBzAGkQCMHnW22PARJlo8JCnQ0A-Hxbsu3OYkYLBOfEUQBvYogOIYwRGgCENDIiYBTKCCZh9hiAnpwANjYB0HuG1pfG3YoAAtEAGoeIJDQjGIAXyA

Related Issues: N/A

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Oct 1, 2019
@RyanCavanaugh
Copy link
Member

Duplicate #14515

@AnyhowStep
Copy link
Contributor

AnyhowStep commented Oct 1, 2019

Overloads are a real pain in the butt, honestly.
Often times, if you're not dealing with generic functions and the overload does not affect the return type, I find that you're better off using rest args on tuple types.

function foo(...args : []|[number, number]): void {
    if (args.length == 0) return;
    const [a, b] = args;
    console.log(a.length + b.length);
}

foo(); //OK
foo(1,2); //OK
foo(1); //Error

I'm on mobile now, so I might have made a mistake but the above should work

@AnyhowStep
Copy link
Contributor

Another example I posted on Gitter earlier on,

interface Data {
    someUsefulPieceOfInfo : string
}
function callback (...args : [Error]|[null|undefined, Data]) {
    if (args[0] == undefined) {
        console.log(args[1].someUsefulPieceOfInfo);
    } else {
        console.error(args[0].message);
    }
}

callback(new Error("blah"));
callback(undefined, { someUsefulPieceOfInfo : "Hello, world" });

Playground

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@afreix
Copy link

afreix commented Nov 16, 2019

@AnyhowStep in response to #33704 (comment)

Is there any workaround for when you are using generics?

export function allLoaded<TData1>(
  responses: [Response<TData1>]
): responses is [ResponseSuccessful<TData1>];
export function allLoaded<TData1, TData2>(
  responses: [Response<TData1>, Response<TData2>]
): responses is [ResponseSuccessful<TData1>, ResponseSuccessful<TData2>];
export function allLoaded(responses: Response<any>[]) {
  return responses.every(isLoaded);
}

// Type Guard
export function isLoaded<TData>(
  response: Response<TData>
): response is ResponseSuccessful {
  return response.status === QueryStatus.Success;
}

I'd like be able to define my overloads like above and be able to call allLoaded with a parameter of type [Response<TData1>] | [Response<TData1>, Response<TData2>]

@AnyhowStep
Copy link
Contributor

AnyhowStep commented Nov 16, 2019

Seems like the same pattern as Promise.all()

See, #33707

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