Skip to content

Type inference issue related to usage of conditional type #25299

Closed
@andriy-kudrya

Description

@andriy-kudrya

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

Search Terms:
conditional type inference

Code

// Don't know what causes the problem so cannot come up with a shorter sample

type ActionType<P> = string & { attachPayloadTypeHack?: P & never }

/*
// irrelevant type to reproduce my issue
// but gives context that action might have no additional payload to handle

type Action<P> = P extends void
    ? { type: ActionType<P> }
    : { type: ActionType<P>, payload: P }
*/

type Handler<S, P> = P extends void
    ? (state: S) => S
    : (state: S, payload: P) => S

interface ActionHandler<S, P> {
    actionType: ActionType<P>
    handler: Handler<S, P>
}

declare function handler<S, P>(actionType: ActionType<P>, handler: Handler<S, P>): ActionHandler<S, P>

declare function createReducer<S>(
        defaultState: S,
        ...actionHandlers: ActionHandler<S /* force state S for every action handler*/, any>[]
    ): any

interface AppState {
    dummy: string
}

const defaultState: AppState = {
    dummy: ''
}

const NON_VOID_ACTION: ActionType<number> = 'NON_VOID_ACTION'
    , VOID_ACTION: ActionType<void> = 'VOID_ACTION'

handler<AppState, number>(NON_VOID_ACTION, (state, _payload) => state), // ok - state is AppState
handler<AppState, void>(VOID_ACTION, state => state) // ok - state is AppState

createReducer(
    defaultState,
    handler(NON_VOID_ACTION, (state, _payload) => state), // ok - state is AppState
    handler(VOID_ACTION, state => state) // unexpected - state is any
)

Expected behavior:
state parameter is infered to be "AppState" in the expression at the end

handler(VOID_ACTION, state => state)

Actual behavior:
state parameter is infered to be "any"

Playground Link:
Playground
(use noImplicitAny flag)

Related Issues:
Not sure #25301

Workaround:
When Handler is defined as follows

type Handler<S, P> = (state: S, payload: P) => S

it still allows to pass single argument handler and state is infered to be AppState

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: Conditional TypesThe issue relates to conditional typesFixedA PR has been merged for this issue

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions