- Notifications
You must be signed in to change notification settings - Fork 13.2k
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: check: Control FlowThe issue relates to control flow analysisThe issue relates to control flow analysisFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Milestone
Description
TypeScript Version:[email protected]
Search Terms: discriminated, exhaustiveness, type guard, narrowing
Code
// Legal action types for ValidActionenumActionTypes{INCREMENT='INCREMENT',// DECREMENT = 'DECREMENT',}interfaceIIncrement{payload: {};type: ActionTypes.INCREMENT;}// interface IDecrement{// payload:{};// type: ActionTypes.DECREMENT;// }// Any string not present in TtypeAnyStringExcept<Textendsstring>={[PinT]: never;};// ValidAction is an interface with a type in ActionTypestypeValidAction=IIncrement;// type ValidAction = IIncrement | IDecrement;// UnhandledAction in an interface with a type that is not within ActionTypestypeUnhandledAction={type: AnyStringExcept<ActionTypes>;};// The set of all actionstypePossibleAction=ValidAction|UnhandledAction;// Discriminates to ValidActionfunctionisUnhandled(x: PossibleAction): x is UnhandledAction{return!(x.typeinActionTypes);}typeCounterState=number;constinitialState: CounterState=0;functionreceiveAction(state=initialState,action: PossibleAction){// typeof action === PossibleActionif(isUnhandled(action)){// typeof action === UnhandledActionreturnstate;}// typeof action === ValidActionswitch(action.type){caseActionTypes.INCREMENT: // typeof action === IIncrementreturnstate+1;// case ActionTypes.DECREMENT:// return state - 1;}// typeof action === IIncrement// Since INCREMENT is handled above, this should be impossible,// However the compiler will say that assertNever cannot receive an argument of type IIncrementreturnassertNever(action);}functionassertNever(x: UnhandledAction): never{thrownewError(`Unhandled action type: ${x.type}`);}Expected behavior: No error would be thrown, as the switch statement is exhaustive. If the ActionTypes.DECREMENT parts are uncommented (resulting in two possible values for ActionTypes) there is no error. An error only occurs when ActionTypes takes on a single value. The error occurs even if the never assertion happens in the default statement, which is obviously unreachable from IIncrement.
Actual behavior: An error is thrown despite the only possible value being explicitly handled. If ActionTypes.DECREMENT is uncommented the expected behavior is present.
krryan, anAgent, dustin-rcg, koutaro-masaki and zxTheXCopilot
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: check: Control FlowThe issue relates to control flow analysisThe issue relates to control flow analysisFix AvailableA PR has been opened for this issueA PR has been opened for this issue