diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fe2ce42652af4..fbf2e920687bf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15317,6 +15317,32 @@ namespace ts { return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } + function getImpliedTypeFromTypeofCase(type: Type, text: string) { + switch (text) { + case "function": + return type.flags & TypeFlags.Any ? type : globalFunctionType; + case "object": + return type.flags & TypeFlags.Unknown ? getUnionType([nonPrimitiveType, nullType]) : type; + default: + return typeofTypesByName.get(text) || type; + } + } + + function narrowTypeForTypeofSwitch(candidate: Type) { + return (type: Type) => { + if (isTypeSubtypeOf(candidate, type)) { + return candidate; + } + if (type.flags & TypeFlags.Instantiable) { + const constraint = getBaseConstraintOfType(type) || anyType; + if (isTypeSubtypeOf(candidate, constraint)) { + return getIntersectionType([type, candidate]); + } + } + return type; + }; + } + function narrowBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type { const switchWitnesses = getSwitchClauseTypeOfWitnesses(switchStatement); if (!switchWitnesses.length) { @@ -15334,7 +15360,7 @@ namespace ts { // that we don't have to worry about undefined // in the witness array. const witnesses = switchWitnesses.filter(witness => witness !== undefined); - // The adjust clause start and end after removing the `default` statement. + // The adjusted clause start and end after removing the `default` statement. const fixedClauseStart = defaultCaseLocation < clauseStart ? clauseStart - 1 : clauseStart; const fixedClauseEnd = defaultCaseLocation < clauseEnd ? clauseEnd - 1 : clauseEnd; clauseWitnesses = witnesses.slice(fixedClauseStart, fixedClauseEnd); @@ -15344,6 +15370,9 @@ namespace ts { clauseWitnesses = switchWitnesses.slice(clauseStart, clauseEnd); switchFacts = getFactsFromTypeofSwitch(clauseStart, clauseEnd, switchWitnesses, hasDefaultClause); } + if (hasDefaultClause) { + return filterType(type, t => (getTypeFacts(t) & switchFacts) === switchFacts); + } /* The implied type is the raw type suggested by a value being caught in this clause. @@ -15372,26 +15401,11 @@ namespace ts { boolean. We know that number cannot be selected because it is caught in the first clause. */ - if (!(hasDefaultClause || (type.flags & TypeFlags.Union))) { - let impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => typeofTypesByName.get(text) || neverType)), switchFacts); - if (impliedType.flags & TypeFlags.Union) { - impliedType = getAssignmentReducedType(impliedType as UnionType, getBaseConstraintOfType(type) || type); - } - if (!(impliedType.flags & TypeFlags.Never)) { - if (isTypeSubtypeOf(impliedType, type)) { - return impliedType; - } - if (type.flags & TypeFlags.Instantiable) { - const constraint = getBaseConstraintOfType(type) || anyType; - if (isTypeSubtypeOf(impliedType, constraint)) { - return getIntersectionType([type, impliedType]); - } - } - } + let impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => getImpliedTypeFromTypeofCase(type, text))), switchFacts); + if (impliedType.flags & TypeFlags.Union) { + impliedType = getAssignmentReducedType(impliedType as UnionType, getBaseConstraintOrType(type)); } - return hasDefaultClause ? - filterType(type, t => (getTypeFacts(t) & switchFacts) === switchFacts) : - getTypeWithFacts(type, switchFacts); + return getTypeWithFacts(mapType(type, narrowTypeForTypeofSwitch(impliedType)), switchFacts); } function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { diff --git a/tests/baselines/reference/narrowingByTypeofInSwitch.js b/tests/baselines/reference/narrowingByTypeofInSwitch.js index 95ec120a85d2d..2b99da05e1357 100644 --- a/tests/baselines/reference/narrowingByTypeofInSwitch.js +++ b/tests/baselines/reference/narrowingByTypeofInSwitch.js @@ -27,6 +27,10 @@ function assertObject(x: object) { return x; } +function assertObjectOrNull(x: object | null) { + return x; +} + function assertUndefined(x: undefined) { return x; } @@ -35,11 +39,11 @@ function assertAll(x: Basic) { return x; } -function assertStringOrNumber(x: string | number) { +function assertStringOrNumber(x: string | number) { return x; } -function assertBooleanOrObject(x: boolean | object) { +function assertBooleanOrObject(x: boolean | object) { return x; } @@ -210,6 +214,41 @@ function fallThroughTest(x: string | number | boolean | object) { break; } } + +function unknownNarrowing(x: unknown) { + switch (typeof x) { + case 'number': assertNumber(x); return; + case 'boolean': assertBoolean(x); return; + case 'function': assertFunction(x); return; + case 'symbol': assertSymbol(x); return; + case 'object': assertObjectOrNull(x); return; + case 'string': assertString(x); return; + case 'undefined': assertUndefined(x); return; + } +} + +function keyofNarrowing(k: keyof S) { + function assertKeyofS(k1: keyof S) { } + switch (typeof k) { + case 'number': assertNumber(k); assertKeyofS(k); return; + case 'symbol': assertSymbol(k); assertKeyofS(k); return; + case 'string': assertString(k); assertKeyofS(k); return; + } +} + +function narrowingNarrows(x: {} | undefined) { + switch (typeof x) { + case 'number': assertNumber(x); return; + case 'boolean': assertBoolean(x); return; + case 'function': assertFunction(x); return; + case 'symbol': assertSymbol(x); return; + case 'object': const _: {} = x; return; + case 'string': assertString(x); return; + case 'undefined': assertUndefined(x); return; + case 'number': assertNever(x); return; + default: const _y: {} = x; return; + } +} //// [narrowingByTypeofInSwitch.js] @@ -234,6 +273,9 @@ function assertFunction(x) { function assertObject(x) { return x; } +function assertObjectOrNull(x) { + return x; +} function assertUndefined(x) { return x; } @@ -470,3 +512,76 @@ function fallThroughTest(x) { break; } } +function unknownNarrowing(x) { + switch (typeof x) { + case 'number': + assertNumber(x); + return; + case 'boolean': + assertBoolean(x); + return; + case 'function': + assertFunction(x); + return; + case 'symbol': + assertSymbol(x); + return; + case 'object': + assertObjectOrNull(x); + return; + case 'string': + assertString(x); + return; + case 'undefined': + assertUndefined(x); + return; + } +} +function keyofNarrowing(k) { + function assertKeyofS(k1) { } + switch (typeof k) { + case 'number': + assertNumber(k); + assertKeyofS(k); + return; + case 'symbol': + assertSymbol(k); + assertKeyofS(k); + return; + case 'string': + assertString(k); + assertKeyofS(k); + return; + } +} +function narrowingNarrows(x) { + switch (typeof x) { + case 'number': + assertNumber(x); + return; + case 'boolean': + assertBoolean(x); + return; + case 'function': + assertFunction(x); + return; + case 'symbol': + assertSymbol(x); + return; + case 'object': + var _ = x; + return; + case 'string': + assertString(x); + return; + case 'undefined': + assertUndefined(x); + return; + case 'number': + assertNever(x); + return; + default: + var _y = x; + return; + } +} diff --git a/tests/baselines/reference/narrowingByTypeofInSwitch.symbols b/tests/baselines/reference/narrowingByTypeofInSwitch.symbols index 8024625181509..f1ff39725b39f 100644 --- a/tests/baselines/reference/narrowingByTypeofInSwitch.symbols +++ b/tests/baselines/reference/narrowingByTypeofInSwitch.symbols @@ -56,536 +56,662 @@ function assertObject(x: object) { >x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 24, 22)) } +function assertObjectOrNull(x: object | null) { +>assertObjectOrNull : Symbol(assertObjectOrNull, Decl(narrowingByTypeofInSwitch.ts, 26, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 28, 28)) + + return x; +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 28, 28)) +} + function assertUndefined(x: undefined) { ->assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 26, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 28, 25)) +>assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 32, 25)) return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 28, 25)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 32, 25)) } function assertAll(x: Basic) { ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 32, 19)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 36, 19)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 32, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 36, 19)) } -function assertStringOrNumber(x: string | number) { ->assertStringOrNumber : Symbol(assertStringOrNumber, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 36, 30)) +function assertStringOrNumber(x: string | number) { +>assertStringOrNumber : Symbol(assertStringOrNumber, Decl(narrowingByTypeofInSwitch.ts, 38, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 40, 30)) return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 36, 30)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 40, 30)) } -function assertBooleanOrObject(x: boolean | object) { ->assertBooleanOrObject : Symbol(assertBooleanOrObject, Decl(narrowingByTypeofInSwitch.ts, 38, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 40, 31)) +function assertBooleanOrObject(x: boolean | object) { +>assertBooleanOrObject : Symbol(assertBooleanOrObject, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 44, 31)) return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 40, 31)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 44, 31)) } type Basic = number | boolean | string | symbol | object | Function | undefined; ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) >Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) function testUnion(x: Basic) { ->testUnion : Symbol(testUnion, Decl(narrowingByTypeofInSwitch.ts, 44, 80)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>testUnion : Symbol(testUnion, Decl(narrowingByTypeofInSwitch.ts, 48, 80)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'function': assertFunction(x); return; >assertFunction : Symbol(assertFunction, Decl(narrowingByTypeofInSwitch.ts, 18, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'object': assertObject(x); return; >assertObject : Symbol(assertObject, Decl(narrowingByTypeofInSwitch.ts, 22, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'string': assertString(x); return; >assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) case 'undefined': assertUndefined(x); return; ->assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 26, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) } assertNever(x); >assertNever : Symbol(assertNever, Decl(narrowingByTypeofInSwitch.ts, 0, 0)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 46, 19)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 50, 19)) } function testExtendsUnion(x: T) { ->testExtendsUnion : Symbol(testExtendsUnion, Decl(narrowingByTypeofInSwitch.ts, 57, 1)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 59, 26)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 59, 26)) +>testExtendsUnion : Symbol(testExtendsUnion, Decl(narrowingByTypeofInSwitch.ts, 61, 1)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 63, 26)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 63, 26)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'function': assertAll(x); return; ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'object': assertAll(x); return; ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'string': assertString(x); return; >assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) case 'undefined': assertUndefined(x); return; ->assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 26, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) } assertAll(x); ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 59, 43)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 63, 43)) } function testAny(x: any) { ->testAny : Symbol(testAny, Decl(narrowingByTypeofInSwitch.ts, 70, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>testAny : Symbol(testAny, Decl(narrowingByTypeofInSwitch.ts, 74, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'function': assertFunction(x); return; >assertFunction : Symbol(assertFunction, Decl(narrowingByTypeofInSwitch.ts, 18, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'object': assertObject(x); return; >assertObject : Symbol(assertObject, Decl(narrowingByTypeofInSwitch.ts, 22, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'string': assertString(x); return; >assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) case 'undefined': assertUndefined(x); return; ->assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 26, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) } assertAll(x); // is any ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 72, 17)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 76, 17)) } function a1(x: string | object | undefined) { ->a1 : Symbol(a1, Decl(narrowingByTypeofInSwitch.ts, 83, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 85, 12)) +>a1 : Symbol(a1, Decl(narrowingByTypeofInSwitch.ts, 87, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 12)) return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 85, 12)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 12)) } function testUnionExplicitDefault(x: Basic) { ->testUnionExplicitDefault : Symbol(testUnionExplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 87, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>testUnionExplicitDefault : Symbol(testUnionExplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 91, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) case 'function': assertFunction(x); return; >assertFunction : Symbol(assertFunction, Decl(narrowingByTypeofInSwitch.ts, 18, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) default: a1(x); return; ->a1 : Symbol(a1, Decl(narrowingByTypeofInSwitch.ts, 83, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 89, 34)) +>a1 : Symbol(a1, Decl(narrowingByTypeofInSwitch.ts, 87, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 93, 34)) } } function testUnionImplicitDefault(x: Basic) { ->testUnionImplicitDefault : Symbol(testUnionImplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 97, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>testUnionImplicitDefault : Symbol(testUnionImplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 101, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) case 'function': assertFunction(x); return; >assertFunction : Symbol(assertFunction, Decl(narrowingByTypeofInSwitch.ts, 18, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) } return a1(x); ->a1 : Symbol(a1, Decl(narrowingByTypeofInSwitch.ts, 83, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 99, 34)) +>a1 : Symbol(a1, Decl(narrowingByTypeofInSwitch.ts, 87, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 103, 34)) } function testExtendsExplicitDefault(x: T) { ->testExtendsExplicitDefault : Symbol(testExtendsExplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 107, 1)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 109, 36)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 109, 36)) +>testExtendsExplicitDefault : Symbol(testExtendsExplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 111, 1)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 113, 36)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 113, 36)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) case 'function': assertAll(x); return; ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) default: assertAll(x); return; ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 109, 53)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 113, 53)) } } function testExtendsImplicitDefault(x: T) { ->testExtendsImplicitDefault : Symbol(testExtendsImplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 118, 1)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 120, 36)) ->Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 120, 36)) +>testExtendsImplicitDefault : Symbol(testExtendsImplicitDefault, Decl(narrowingByTypeofInSwitch.ts, 122, 1)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 124, 36)) +>Basic : Symbol(Basic, Decl(narrowingByTypeofInSwitch.ts, 46, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 124, 36)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) case 'number': assertNumber(x); return; >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) case 'boolean': assertBoolean(x); return; >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) case 'function': assertAll(x); return; ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) case 'symbol': assertSymbol(x); return; >assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) } return assertAll(x); ->assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 120, 53)) +>assertAll : Symbol(assertAll, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 124, 53)) } type L = (x: number) => string; ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 130, 10)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 134, 10)) type R = { x: string, y: number } ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 131, 10)) ->y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 131, 21)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 135, 10)) +>y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 135, 21)) function exhaustiveChecks(x: number | string | L | R): string { ->exhaustiveChecks : Symbol(exhaustiveChecks, Decl(narrowingByTypeofInSwitch.ts, 131, 33)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 133, 26)) ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) +>exhaustiveChecks : Symbol(exhaustiveChecks, Decl(narrowingByTypeofInSwitch.ts, 135, 33)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 137, 26)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 133, 26)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 137, 26)) case 'number': return x.toString(2); >x.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 133, 26)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 137, 26)) >toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) case 'string': return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 133, 26)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 137, 26)) case 'function': return x(42); ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 133, 26)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 137, 26)) case 'object': return x.x; ->x.x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 131, 10)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 133, 26)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 131, 10)) +>x.x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 135, 10)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 137, 26)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 135, 10)) } } function exhaustiveChecksGenerics(x: T): string { ->exhaustiveChecksGenerics : Symbol(exhaustiveChecksGenerics, Decl(narrowingByTypeofInSwitch.ts, 140, 1)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 142, 34)) ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 142, 69)) ->T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 142, 34)) +>exhaustiveChecksGenerics : Symbol(exhaustiveChecksGenerics, Decl(narrowingByTypeofInSwitch.ts, 144, 1)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 146, 34)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 146, 69)) +>T : Symbol(T, Decl(narrowingByTypeofInSwitch.ts, 146, 34)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 142, 69)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 146, 69)) case 'number': return x.toString(2); >x.toString : Symbol(toString, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 2 more) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 142, 69)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 146, 69)) >toString : Symbol(toString, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 2 more) case 'string': return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 142, 69)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 146, 69)) case 'function': return (x as L)(42); // Can't narrow generic ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 142, 69)) ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 146, 69)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) case 'object': return (x as R).x; // Can't narrow generic ->(x as R).x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 131, 10)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 142, 69)) ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 131, 10)) +>(x as R).x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 135, 10)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 146, 69)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 135, 10)) } } function multipleGeneric(xy: X | Y): [X, string] | [Y, number] { ->multipleGeneric : Symbol(multipleGeneric, Decl(narrowingByTypeofInSwitch.ts, 149, 1)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 151, 25)) ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 151, 37)) ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 151, 25)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 151, 37)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 151, 25)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 151, 37)) +>multipleGeneric : Symbol(multipleGeneric, Decl(narrowingByTypeofInSwitch.ts, 153, 1)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 155, 25)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 155, 37)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 155, 25)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 155, 37)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 155, 25)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 155, 37)) switch (typeof xy) { ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) case 'function': return [xy, xy(42)]; ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) case 'object': return [xy, xy.y]; ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) ->xy.y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 131, 21)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) ->y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 131, 21)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) +>xy.y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 135, 21)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) +>y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 135, 21)) default: return assertNever(xy); >assertNever : Symbol(assertNever, Decl(narrowingByTypeofInSwitch.ts, 0, 0)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 151, 51)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 155, 51)) } } function multipleGenericFuse(xy: X | Y): [X, number] | [Y, string] | [(X | Y)] { ->multipleGenericFuse : Symbol(multipleGenericFuse, Decl(narrowingByTypeofInSwitch.ts, 157, 1)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 159, 29)) ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 159, 50)) ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 159, 73)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 159, 29)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 159, 50)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 159, 29)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 159, 50)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 159, 29)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 159, 50)) +>multipleGenericFuse : Symbol(multipleGenericFuse, Decl(narrowingByTypeofInSwitch.ts, 161, 1)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 163, 29)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 163, 50)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 163, 73)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 163, 29)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 163, 50)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 163, 29)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 163, 50)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 163, 29)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 163, 50)) switch (typeof xy) { ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 159, 73)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 163, 73)) case 'function': return [xy, 1]; ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 159, 73)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 163, 73)) case 'object': return [xy, 'two']; ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 159, 73)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 163, 73)) case 'number': return [xy] ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 159, 73)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 163, 73)) } } function multipleGenericExhaustive(xy: X | Y): [X, string] | [Y, number] { ->multipleGenericExhaustive : Symbol(multipleGenericExhaustive, Decl(narrowingByTypeofInSwitch.ts, 165, 1)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 167, 35)) ->L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 128, 1)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 167, 47)) ->R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 130, 31)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 167, 61)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 167, 35)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 167, 47)) ->X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 167, 35)) ->Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 167, 47)) +>multipleGenericExhaustive : Symbol(multipleGenericExhaustive, Decl(narrowingByTypeofInSwitch.ts, 169, 1)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 171, 35)) +>L : Symbol(L, Decl(narrowingByTypeofInSwitch.ts, 132, 1)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 171, 47)) +>R : Symbol(R, Decl(narrowingByTypeofInSwitch.ts, 134, 31)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 171, 61)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 171, 35)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 171, 47)) +>X : Symbol(X, Decl(narrowingByTypeofInSwitch.ts, 171, 35)) +>Y : Symbol(Y, Decl(narrowingByTypeofInSwitch.ts, 171, 47)) switch (typeof xy) { ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 167, 61)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 171, 61)) case 'object': return [xy, xy.y]; ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 167, 61)) ->xy.y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 131, 21)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 167, 61)) ->y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 131, 21)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 171, 61)) +>xy.y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 135, 21)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 171, 61)) +>y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 135, 21)) case 'function': return [xy, xy(42)]; ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 167, 61)) ->xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 167, 61)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 171, 61)) +>xy : Symbol(xy, Decl(narrowingByTypeofInSwitch.ts, 171, 61)) } } function switchOrdering(x: string | number | boolean) { ->switchOrdering : Symbol(switchOrdering, Decl(narrowingByTypeofInSwitch.ts, 172, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 174, 24)) +>switchOrdering : Symbol(switchOrdering, Decl(narrowingByTypeofInSwitch.ts, 176, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 178, 24)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 174, 24)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 178, 24)) case 'string': return assertString(x); >assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 174, 24)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 178, 24)) case 'number': return assertNumber(x); >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 174, 24)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 178, 24)) case 'boolean': return assertBoolean(x); >assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 174, 24)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 178, 24)) case 'number': return assertNever(x); >assertNever : Symbol(assertNever, Decl(narrowingByTypeofInSwitch.ts, 0, 0)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 174, 24)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 178, 24)) } } function switchOrderingWithDefault(x: string | number | boolean) { ->switchOrderingWithDefault : Symbol(switchOrderingWithDefault, Decl(narrowingByTypeofInSwitch.ts, 181, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 183, 35)) +>switchOrderingWithDefault : Symbol(switchOrderingWithDefault, Decl(narrowingByTypeofInSwitch.ts, 185, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 187, 35)) function local(y: string | number | boolean) { ->local : Symbol(local, Decl(narrowingByTypeofInSwitch.ts, 183, 66)) ->y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 184, 19)) +>local : Symbol(local, Decl(narrowingByTypeofInSwitch.ts, 187, 66)) +>y : Symbol(y, Decl(narrowingByTypeofInSwitch.ts, 188, 19)) return x; ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 183, 35)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 187, 35)) } switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 183, 35)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 187, 35)) case 'string': case 'number': default: return local(x) ->local : Symbol(local, Decl(narrowingByTypeofInSwitch.ts, 183, 66)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 183, 35)) +>local : Symbol(local, Decl(narrowingByTypeofInSwitch.ts, 187, 66)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 187, 35)) case 'string': return assertNever(x); >assertNever : Symbol(assertNever, Decl(narrowingByTypeofInSwitch.ts, 0, 0)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 183, 35)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 187, 35)) case 'number': return assertNever(x); >assertNever : Symbol(assertNever, Decl(narrowingByTypeofInSwitch.ts, 0, 0)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 183, 35)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 187, 35)) } } function fallThroughTest(x: string | number | boolean | object) { ->fallThroughTest : Symbol(fallThroughTest, Decl(narrowingByTypeofInSwitch.ts, 194, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 196, 25)) +>fallThroughTest : Symbol(fallThroughTest, Decl(narrowingByTypeofInSwitch.ts, 198, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 200, 25)) switch (typeof x) { ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 196, 25)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 200, 25)) case 'number': assertNumber(x) >assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 196, 25)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 200, 25)) case 'string': assertStringOrNumber(x) ->assertStringOrNumber : Symbol(assertStringOrNumber, Decl(narrowingByTypeofInSwitch.ts, 34, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 196, 25)) +>assertStringOrNumber : Symbol(assertStringOrNumber, Decl(narrowingByTypeofInSwitch.ts, 38, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 200, 25)) break; default: assertObject(x); >assertObject : Symbol(assertObject, Decl(narrowingByTypeofInSwitch.ts, 22, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 196, 25)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 200, 25)) case 'number': case 'boolean': assertBooleanOrObject(x); ->assertBooleanOrObject : Symbol(assertBooleanOrObject, Decl(narrowingByTypeofInSwitch.ts, 38, 1)) ->x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 196, 25)) +>assertBooleanOrObject : Symbol(assertBooleanOrObject, Decl(narrowingByTypeofInSwitch.ts, 42, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 200, 25)) break; } } +function unknownNarrowing(x: unknown) { +>unknownNarrowing : Symbol(unknownNarrowing, Decl(narrowingByTypeofInSwitch.ts, 214, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + switch (typeof x) { +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'number': assertNumber(x); return; +>assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'boolean': assertBoolean(x); return; +>assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'function': assertFunction(x); return; +>assertFunction : Symbol(assertFunction, Decl(narrowingByTypeofInSwitch.ts, 18, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'symbol': assertSymbol(x); return; +>assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'object': assertObjectOrNull(x); return; +>assertObjectOrNull : Symbol(assertObjectOrNull, Decl(narrowingByTypeofInSwitch.ts, 26, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'string': assertString(x); return; +>assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + + case 'undefined': assertUndefined(x); return; +>assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 216, 26)) + } +} + +function keyofNarrowing(k: keyof S) { +>keyofNarrowing : Symbol(keyofNarrowing, Decl(narrowingByTypeofInSwitch.ts, 226, 1)) +>S : Symbol(S, Decl(narrowingByTypeofInSwitch.ts, 228, 24)) +>K : Symbol(K, Decl(narrowingByTypeofInSwitch.ts, 228, 37)) +>S : Symbol(S, Decl(narrowingByTypeofInSwitch.ts, 228, 24)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) +>S : Symbol(S, Decl(narrowingByTypeofInSwitch.ts, 228, 24)) + + function assertKeyofS(k1: keyof S) { } +>assertKeyofS : Symbol(assertKeyofS, Decl(narrowingByTypeofInSwitch.ts, 228, 75)) +>k1 : Symbol(k1, Decl(narrowingByTypeofInSwitch.ts, 229, 26)) +>S : Symbol(S, Decl(narrowingByTypeofInSwitch.ts, 228, 24)) + + switch (typeof k) { +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) + + case 'number': assertNumber(k); assertKeyofS(k); return; +>assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) +>assertKeyofS : Symbol(assertKeyofS, Decl(narrowingByTypeofInSwitch.ts, 228, 75)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) + + case 'symbol': assertSymbol(k); assertKeyofS(k); return; +>assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) +>assertKeyofS : Symbol(assertKeyofS, Decl(narrowingByTypeofInSwitch.ts, 228, 75)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) + + case 'string': assertString(k); assertKeyofS(k); return; +>assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) +>assertKeyofS : Symbol(assertKeyofS, Decl(narrowingByTypeofInSwitch.ts, 228, 75)) +>k : Symbol(k, Decl(narrowingByTypeofInSwitch.ts, 228, 62)) + } +} + +function narrowingNarrows(x: {} | undefined) { +>narrowingNarrows : Symbol(narrowingNarrows, Decl(narrowingByTypeofInSwitch.ts, 235, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + switch (typeof x) { +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'number': assertNumber(x); return; +>assertNumber : Symbol(assertNumber, Decl(narrowingByTypeofInSwitch.ts, 2, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'boolean': assertBoolean(x); return; +>assertBoolean : Symbol(assertBoolean, Decl(narrowingByTypeofInSwitch.ts, 6, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'function': assertFunction(x); return; +>assertFunction : Symbol(assertFunction, Decl(narrowingByTypeofInSwitch.ts, 18, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'symbol': assertSymbol(x); return; +>assertSymbol : Symbol(assertSymbol, Decl(narrowingByTypeofInSwitch.ts, 14, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'object': const _: {} = x; return; +>_ : Symbol(_, Decl(narrowingByTypeofInSwitch.ts, 243, 28)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'string': assertString(x); return; +>assertString : Symbol(assertString, Decl(narrowingByTypeofInSwitch.ts, 10, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'undefined': assertUndefined(x); return; +>assertUndefined : Symbol(assertUndefined, Decl(narrowingByTypeofInSwitch.ts, 30, 1)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + case 'number': assertNever(x); return; +>assertNever : Symbol(assertNever, Decl(narrowingByTypeofInSwitch.ts, 0, 0)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + + default: const _y: {} = x; return; +>_y : Symbol(_y, Decl(narrowingByTypeofInSwitch.ts, 247, 22)) +>x : Symbol(x, Decl(narrowingByTypeofInSwitch.ts, 237, 26)) + } +} + diff --git a/tests/baselines/reference/narrowingByTypeofInSwitch.types b/tests/baselines/reference/narrowingByTypeofInSwitch.types index 000eea75f7908..e93acb2bf0950 100644 --- a/tests/baselines/reference/narrowingByTypeofInSwitch.types +++ b/tests/baselines/reference/narrowingByTypeofInSwitch.types @@ -55,6 +55,15 @@ function assertObject(x: object) { >x : object } +function assertObjectOrNull(x: object | null) { +>assertObjectOrNull : (x: object | null) => object | null +>x : object | null +>null : null + + return x; +>x : object | null +} + function assertUndefined(x: undefined) { >assertUndefined : (x: undefined) => undefined >x : undefined @@ -71,7 +80,7 @@ function assertAll(x: Basic) { >x : Basic } -function assertStringOrNumber(x: string | number) { +function assertStringOrNumber(x: string | number) { >assertStringOrNumber : (x: string | number) => string | number >x : string | number @@ -79,7 +88,7 @@ function assertStringOrNumber(x: string | number) { >x : string | number } -function assertBooleanOrObject(x: boolean | object) { +function assertBooleanOrObject(x: boolean | object) { >assertBooleanOrObject : (x: boolean | object) => boolean | object >x : boolean | object @@ -170,7 +179,7 @@ function testExtendsUnion(x: T) { >'function' : "function" >assertAll(x) : Basic >assertAll : (x: Basic) => Basic ->x : T +>x : T & Function case 'symbol': assertSymbol(x); return; >'symbol' : "symbol" @@ -367,7 +376,7 @@ function testExtendsExplicitDefault(x: T) { >'function' : "function" >assertAll(x) : Basic >assertAll : (x: Basic) => Basic ->x : T +>x : T & Function case 'symbol': assertSymbol(x); return; >'symbol' : "symbol" @@ -407,7 +416,7 @@ function testExtendsImplicitDefault(x: T) { >'function' : "function" >assertAll(x) : Basic >assertAll : (x: Basic) => Basic ->x : T +>x : T & Function case 'symbol': assertSymbol(x); return; >'symbol' : "symbol" @@ -555,8 +564,8 @@ function multipleGenericFuse(xy: X | case 'number': return [xy] >'number' : "number" ->[xy] : [X | Y] ->xy : X | Y +>[xy] : [(X & number) | (Y & number)] +>xy : (X & number) | (Y & number) } } @@ -706,3 +715,157 @@ function fallThroughTest(x: string | number | boolean | object) { } } +function unknownNarrowing(x: unknown) { +>unknownNarrowing : (x: unknown) => void +>x : unknown + + switch (typeof x) { +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown + + case 'number': assertNumber(x); return; +>'number' : "number" +>assertNumber(x) : number +>assertNumber : (x: number) => number +>x : number + + case 'boolean': assertBoolean(x); return; +>'boolean' : "boolean" +>assertBoolean(x) : boolean +>assertBoolean : (x: boolean) => boolean +>x : boolean + + case 'function': assertFunction(x); return; +>'function' : "function" +>assertFunction(x) : Function +>assertFunction : (x: Function) => Function +>x : Function + + case 'symbol': assertSymbol(x); return; +>'symbol' : "symbol" +>assertSymbol(x) : symbol +>assertSymbol : (x: symbol) => symbol +>x : symbol + + case 'object': assertObjectOrNull(x); return; +>'object' : "object" +>assertObjectOrNull(x) : object | null +>assertObjectOrNull : (x: object | null) => object | null +>x : object | null + + case 'string': assertString(x); return; +>'string' : "string" +>assertString(x) : string +>assertString : (x: string) => string +>x : string + + case 'undefined': assertUndefined(x); return; +>'undefined' : "undefined" +>assertUndefined(x) : undefined +>assertUndefined : (x: undefined) => undefined +>x : undefined + } +} + +function keyofNarrowing(k: keyof S) { +>keyofNarrowing : (k: keyof S) => void +>k : keyof S + + function assertKeyofS(k1: keyof S) { } +>assertKeyofS : (k1: keyof S) => void +>k1 : keyof S + + switch (typeof k) { +>typeof k : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>k : keyof S + + case 'number': assertNumber(k); assertKeyofS(k); return; +>'number' : "number" +>assertNumber(k) : number +>assertNumber : (x: number) => number +>k : keyof S & number +>assertKeyofS(k) : void +>assertKeyofS : (k1: keyof S) => void +>k : keyof S & number + + case 'symbol': assertSymbol(k); assertKeyofS(k); return; +>'symbol' : "symbol" +>assertSymbol(k) : symbol +>assertSymbol : (x: symbol) => symbol +>k : keyof S & symbol +>assertKeyofS(k) : void +>assertKeyofS : (k1: keyof S) => void +>k : keyof S & symbol + + case 'string': assertString(k); assertKeyofS(k); return; +>'string' : "string" +>assertString(k) : string +>assertString : (x: string) => string +>k : keyof S & string +>assertKeyofS(k) : void +>assertKeyofS : (k1: keyof S) => void +>k : keyof S & string + } +} + +function narrowingNarrows(x: {} | undefined) { +>narrowingNarrows : (x: {} | undefined) => void +>x : {} | undefined + + switch (typeof x) { +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : {} | undefined + + case 'number': assertNumber(x); return; +>'number' : "number" +>assertNumber(x) : number +>assertNumber : (x: number) => number +>x : number + + case 'boolean': assertBoolean(x); return; +>'boolean' : "boolean" +>assertBoolean(x) : boolean +>assertBoolean : (x: boolean) => boolean +>x : boolean + + case 'function': assertFunction(x); return; +>'function' : "function" +>assertFunction(x) : Function +>assertFunction : (x: Function) => Function +>x : Function + + case 'symbol': assertSymbol(x); return; +>'symbol' : "symbol" +>assertSymbol(x) : symbol +>assertSymbol : (x: symbol) => symbol +>x : symbol + + case 'object': const _: {} = x; return; +>'object' : "object" +>_ : {} +>x : {} + + case 'string': assertString(x); return; +>'string' : "string" +>assertString(x) : string +>assertString : (x: string) => string +>x : string + + case 'undefined': assertUndefined(x); return; +>'undefined' : "undefined" +>assertUndefined(x) : undefined +>assertUndefined : (x: undefined) => undefined +>x : undefined + + case 'number': assertNever(x); return; +>'number' : "number" +>assertNever(x) : never +>assertNever : (x: never) => never +>x : never + + default: const _y: {} = x; return; +>_y : {} +>x : {} + } +} + diff --git a/tests/cases/compiler/narrowingByTypeofInSwitch.ts b/tests/cases/compiler/narrowingByTypeofInSwitch.ts index 252c1d9445ac9..39f04168684d1 100644 --- a/tests/cases/compiler/narrowingByTypeofInSwitch.ts +++ b/tests/cases/compiler/narrowingByTypeofInSwitch.ts @@ -29,6 +29,10 @@ function assertObject(x: object) { return x; } +function assertObjectOrNull(x: object | null) { + return x; +} + function assertUndefined(x: undefined) { return x; } @@ -37,11 +41,11 @@ function assertAll(x: Basic) { return x; } -function assertStringOrNumber(x: string | number) { +function assertStringOrNumber(x: string | number) { return x; } -function assertBooleanOrObject(x: boolean | object) { +function assertBooleanOrObject(x: boolean | object) { return x; } @@ -212,3 +216,38 @@ function fallThroughTest(x: string | number | boolean | object) { break; } } + +function unknownNarrowing(x: unknown) { + switch (typeof x) { + case 'number': assertNumber(x); return; + case 'boolean': assertBoolean(x); return; + case 'function': assertFunction(x); return; + case 'symbol': assertSymbol(x); return; + case 'object': assertObjectOrNull(x); return; + case 'string': assertString(x); return; + case 'undefined': assertUndefined(x); return; + } +} + +function keyofNarrowing(k: keyof S) { + function assertKeyofS(k1: keyof S) { } + switch (typeof k) { + case 'number': assertNumber(k); assertKeyofS(k); return; + case 'symbol': assertSymbol(k); assertKeyofS(k); return; + case 'string': assertString(k); assertKeyofS(k); return; + } +} + +function narrowingNarrows(x: {} | undefined) { + switch (typeof x) { + case 'number': assertNumber(x); return; + case 'boolean': assertBoolean(x); return; + case 'function': assertFunction(x); return; + case 'symbol': assertSymbol(x); return; + case 'object': const _: {} = x; return; + case 'string': assertString(x); return; + case 'undefined': assertUndefined(x); return; + case 'number': assertNever(x); return; + default: const _y: {} = x; return; + } +}