Repository navigation
narrowing doesn't work for literal strings in switch when united with unconstrained string #10417
Description
Activity
RyanCavanaugh commented
on Aug 18, 2016 MemberMore actionsSide question: what was your intent declaring something
string | 'a' | 'b'?zpdDG4gta8XKpMCd commented
on Aug 18, 2016 AuthorMore actionsexample1: DB guys introduced a new possible value to a set of well-known values, without letting anyone know, this new case has to be treated separately as a failure/default case/you name it
example2: this one is lengthy, gradual open-ended narrowing via composing resolving functions
SomeStuffis a union ofOneandAnotherwhy not to take advantage of their resolver functionstype One = 'a' | 'b'; interface ViaOne<r> { caseOfA: (value: 'a') => r; caseOfB: (value: 'b') => r; } function viaOne<r>(kind: One | string, via: ViaOne<r>) : Optional<r> { switch (kind) { case 'a': return someFrom(via.caseOfA(kind)); case 'b': return someFrom(via.caseOfB(kind)); default: return none; } } type Another = 'c' | 'd'; interface ViaAnother<r> { caseOfC: (value: 'c') => r; caseOfD: (value: 'd') => r; } function viaAnother<r>(kind: Another | string, via: ViaAnother<r>): Optional<r> { switch (kind) { case 'c': return someFrom(via.caseOfA(kind)); case 'd': return someFrom(via.caseOfB(kind)); default: return none; } } type CrazyStuff = One | Another; interface ViaCrazyStuff<r> extends ViaOne<r>, ViaAnother<r> {} function viaCrazyStuff<r>(value: CrazyStuff, via: ViaCrazyStuff<r>): Optional<r> { const tryOne = viaOne(value, via); if (isSome(tryOne)) { return tryOne; } else { return viaAnother(value, via); } }
This is working as intended, so I'm changing the label to a suggestion. We currently only narrow in a
switchstatement when the type of the switch expression is a union of unit types. In your example, there's really no difference between the typestringandstring | 'a' | 'b'.- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptand removedBugA bug in TypeScriptA bug in TypeScript
on Aug 18, 2016 zpdDG4gta8XKpMCd commented
on Aug 19, 2016 AuthorMore actionsfyi, there is a workaround using
T extends stringrather than plainstringfunction useA(value: 'a'): void { } function useB(value: 'b'): void { } function useSomethingElse(value: string): void { } function test<c extends string>(kind: 'a' | 'b' | c) { switch (kind) { case 'a': useA(kind); break; case 'b': useB(kind); break; default: useSomethingElse(kind); } }
Reacted by Sean Vieira- addedIn DiscussionNot yet reached consensusNot yet reached consensus
on Aug 19, 2016 RyanCavanaugh commented
on Aug 19, 2016 MemberMore actionsAnders Hejlsberg (@ahejlsberg) why wouldn't we narrow whenever a literal value matches a literal in a union?
Reacted by Yahiko Uzumaki- addedFixedA PR has been merged for this issueA PR has been merged for this issueand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Oct 14, 2016 - locked and limited conversation to collaborators
on Jun 19, 2018
nightly build, August 18, 2016