Skip to content

Generic parameter of function is inferred to be {} when argument of conditional type is passed in #25301

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

Closed
andriy-kudrya opened this issue Jun 28, 2018 · 2 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@andriy-kudrya
Copy link

andriy-kudrya commented Jun 28, 2018

TypeScript Version:
2.8.1, 2.9.2, 3.0.0-dev.20180628

Search Terms:
conditional type inference

Code

// very contrived code to demonstrate the issue

// this conditional type trips type inference
type Action<P> = P extends void
    ? { type: string }
    : { type: string, payload: P }

interface Dispatch {
    // this conditional type seems to have no negative impact on type inference
    <P>(action: Action<P>): P extends void ? undefined : P
}

declare const dispatch: Dispatch

const numberAction: Action<number> = {
        type: 'dummy',
        payload: 0,
    }
    // infered result type is {}, expected one is number
    , numberResult: number = dispatch(numberAction)

const voidAction: Action<void> = {
        type: 'dummy',
    }
    // seems infered P is {}, so it is not allowed to pass voidAction to dispatch
    , voidResult: undefined = dispatch(voidAction)

Expected behavior:
Type checking succeedes

Actual behavior:
Type checking fails for two places:

  • numberResult: number = dispatch(numberAction)
  • voidResult: undefined = dispatch(voidAction)

Playground Link:
Playground

I believe this sample captures the issue but just in case there is a more verbose sample with original types

Related Issues:
Not sure #25299 #24784

@mhegazy
Copy link
Contributor

mhegazy commented Jun 30, 2018

Conditional types do not participate in inference really. for these cases i would recommend using overloads instead.

@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jun 30, 2018
@andriy-kudrya
Copy link
Author

@mhegazy Thanks for overloads direction. It really helped.

type NonVoidAction<P> = { type: string, payload: P }
type VoidAction = { type: string }

interface Dispatch {
    <P>(action: NonVoidAction<P>): P
    (action: VoidAction): undefined
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

2 participants