diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9c5beffc61130..888b7ec6626c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8440,8 +8440,8 @@ namespace ts { return prop ? getTypeOfSymbol(prop) : undefined; } - function getTypeOfPropertyOrIndexSignature(type: Type, name: __String): Type { - return getTypeOfPropertyOfType(type, name) || getApplicableIndexInfoForName(type, name)?.type || unknownType; + function getTypeOfPropertyOrIndexSignature(type: Type, name: __String): Type | undefined { + return getTypeOfPropertyOfType(type, name) || getApplicableIndexInfoForName(type, name)?.type; } function isTypeAny(type: Type | undefined) { @@ -14996,7 +14996,7 @@ namespace ts { links.resolvedType = getTypeFromTypeNode(node.type); break; default: - throw Debug.assertNever(node.operator); + throw new Error("never"); } } return links.resolvedType; @@ -21051,6 +21051,12 @@ namespace ts { && ((target.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.Boolean)) !== 0); } + // `nullable == SomeType|nullable` should be true + function isNullableComparableUnderDoubleEquals(source: Type, target: Type): boolean { + return !!(source.flags & TypeFlags.Nullable) && maybeTypeOfKind(target, TypeFlags.Nullable) + || !!(target.flags & TypeFlags.Nullable) && maybeTypeOfKind(source, TypeFlags.Nullable); + } + /** * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module * with no call or construct signatures. @@ -22698,7 +22704,8 @@ namespace ts { target.kind === SyntaxKind.Identifier && getResolvedSymbol(source as Identifier) === getResolvedSymbol(target as Identifier) || (target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) && getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfNode(target); - case SyntaxKind.ThisKeyword: + return false; + case SyntaxKind.ThisKeyword: return target.kind === SyntaxKind.ThisKeyword; case SyntaxKind.SuperKeyword: return target.kind === SyntaxKind.SuperKeyword; @@ -23986,7 +23993,7 @@ namespace ts { if (isMatchingReference(reference, expr)) { type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } - else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) { + else if (expr.kind === SyntaxKind.TypeOfExpression) { type = narrowBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } else { @@ -23995,10 +24002,6 @@ namespace ts { type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never))); } - else if (expr.kind === SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as TypeOfExpression).expression, reference)) { - type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, - t => !(t.flags & TypeFlags.Never || t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === "undefined")); - } } const access = getDiscriminantPropertyAccess(expr, type); if (access) { @@ -24173,25 +24176,20 @@ namespace ts { } } else if (isAccessExpression(expr)) { - // An access expression is a candidate if the reference matches the left hand expression. - if (isMatchingReference(reference, expr.expression)) { - return expr; - } + return expr; } else if (isIdentifier(expr)) { const symbol = getResolvedSymbol(expr); if (isConstVariable(symbol)) { const declaration = symbol.valueDeclaration!; // Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind' - if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && - isMatchingReference(reference, declaration.initializer.expression)) { + if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer)) { return declaration.initializer; } // Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind' if (isBindingElement(declaration) && !declaration.initializer) { const parent = declaration.parent.parent; - if (isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && - isMatchingReference(reference, parent.initializer)) { + if (isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer))) { return declaration; } } @@ -24201,60 +24199,118 @@ namespace ts { } function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) { - const type = declaredType.flags & TypeFlags.Union ? declaredType : computedType; - if (type.flags & TypeFlags.Union) { - const access = getCandidateDiscriminantPropertyAccess(expr); - if (access) { - const name = getAccessedPropertyName(access); - if (name && isDiscriminantProperty(type, name)) { - return access; + const access = getCandidateDiscriminantPropertyAccess(expr); + if (!access) { + return undefined; + } + const propertyTypeInfo = getPropertyTypesFromTypeByBindingElementOrExpression(computedType, access); + if (!propertyTypeInfo) { + return undefined; + } + const reachableFinalType = mapDefined(propertyTypeInfo, t => t.finalType); + const rootNullable: Type[] = (computedType.flags & TypeFlags.Union) ? (computedType as UnionType).types.filter(t => t.id === undefinedType.id || t.id === nullType.id) : []; + + if (reachableFinalType.length < propertyTypeInfo.length && !some(rootNullable, t => some(propertyTypeInfo, info => info.typeId === t.id))) { + return access; + } + + if (!(computedType.flags & TypeFlags.Union)) { + if (isThisTypeParameter(computedType)) { + return undefined; + } + if (isElementAccessExpression(expr)) { + const type = getReducedApparentType(computedType); + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); + if (resolved.indexInfos) { + return undefined; + } } } + return access; + } + return areTypesDiscriminable(reachableFinalType) ? access : undefined; + + // main part is copied from function createUnionOrIntersectionProperty + function areTypesDiscriminable(types: Type[]) { + let checkFlags = 0; + let firstType: Type | undefined; + for (const type of types) { + if (!firstType) { + firstType = type; + } + else if (type !== firstType) { + checkFlags |= CheckFlags.HasNonUniformType; + } + if (isLiteralType(type)) { + checkFlags |= CheckFlags.HasLiteralType; + } + if (type.flags & TypeFlags.Never) { + checkFlags |= CheckFlags.HasNeverType; + } + } + // next line is copied from isDiscriminantProperty + return (checkFlags & CheckFlags.Discriminant) === CheckFlags.Discriminant && !maybeTypeOfKind(getUnionType(types), TypeFlags.Instantiable); } - return undefined; } - function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowType: (t: Type) => Type): Type { - const propName = getAccessedPropertyName(access); - if (propName === undefined) { + function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowTypeCb: (t: Type) => Type): Type { + const propertyTypeArray = getPropertyTypesFromTypeByBindingElementOrExpression(type, access); + if (!propertyTypeArray) { return type; } - const removeNullable = strictNullChecks && isOptionalChain(access) && maybeTypeOfKind(type, TypeFlags.Nullable); - let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName); - if (!propType) { - return type; + const reachableFinalType = mapDefined(propertyTypeArray, t => t.finalType); + const containsEffectiveOptionalChainTypes = propertyTypeArray.filter(t => t.containsEffectiveOptionalChain); + const subtypes: Type[] = []; + forEach(reachableFinalType, propType => { + forEachType(propType, t => { + subtypes.push(t); + }); + }); + const isAnyConstituentContainsEffectiveOptionalChain = containsEffectiveOptionalChainTypes.length !== 0; + if (isAnyConstituentContainsEffectiveOptionalChain) { + subtypes.push(undefinedType); } - propType = removeNullable ? getOptionalType(propType) : propType; - const narrowedPropType = narrowType(propType); - return filterType(type, t => { - const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName); - return !(narrowedPropType.flags & TypeFlags.Never) && isTypeComparableTo(narrowedPropType, discriminantType); + const bigUnion = getUnionType(subtypes); + const narrowedPropType = narrowTypeCb(bigUnion); + const markSet = new Set(); + propertyTypeArray.forEach(propertyType => { + if (propertyType.finalType && !(narrowedPropType.flags & TypeFlags.Never) && isTypeComparableTo(narrowedPropType, propertyType.finalType)) { + markSet.add(propertyType.typeId); + } }); + containsEffectiveOptionalChainTypes.forEach(t => { + if (maybeTypeOfKind(narrowedPropType, TypeFlags.Undefined)) { + markSet.add(t.typeId); + } + }); + return filterType(type, (t) => markSet.has(t.id)); } function narrowTypeByDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, operator: SyntaxKind, value: Expression, assumeTrue: boolean) { - if ((operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & TypeFlags.Union) { - const keyPropertyName = getKeyPropertyName(type as UnionType); - if (keyPropertyName && keyPropertyName === getAccessedPropertyName(access)) { - const candidate = getConstituentTypeForKeyType(type as UnionType, getTypeOfExpression(value)); - if (candidate) { - return operator === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate : - isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? removeType(type, candidate) : - type; - } - } - } + // if ((operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & TypeFlags.Union) { + // const keyPropertyName = getKeyPropertyName(type as UnionType); + // if (keyPropertyName && keyPropertyName === getAccessedPropertyName(access)) { + // const candidate = getConstituentTypeForKeyType(type as UnionType, getTypeOfExpression(value)); + // if (candidate) { + // return operator === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate : + // isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? removeType(type, candidate) : + // type; + // } + // } + // } return narrowTypeByDiscriminant(type, access, t => narrowTypeByEquality(t, operator, value, assumeTrue)); } function narrowTypeBySwitchOnDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) { - if (clauseStart < clauseEnd && type.flags & TypeFlags.Union && getKeyPropertyName(type as UnionType) === getAccessedPropertyName(access)) { - const clauseTypes = getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd); - const candidate = getUnionType(map(clauseTypes, t => getConstituentTypeForKeyType(type as UnionType, t) || unknownType)); - if (candidate !== unknownType) { - return candidate; - } - } + // if (clauseStart < clauseEnd && type.flags & TypeFlags.Union && getKeyPropertyName(type as UnionType) === getAccessedPropertyName(access)) { + // const clauseTypes = getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd); + // const candidate = getUnionType(map(clauseTypes, t => getConstituentTypeForKeyType(type as UnionType, t) || unknownType)); + // if (candidate !== unknownType) { + // return candidate; + // } + // } + return narrowTypeByDiscriminant(type, access, t => narrowTypeBySwitchOnDiscriminant(t, switchStatement, clauseStart, clauseEnd)); } @@ -24266,8 +24322,9 @@ namespace ts { if (strictNullChecks && assumeTrue && optionalChainContainsReference(expr, reference)) { type = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); } - const access = getDiscriminantPropertyAccess(expr, type); - if (access) { + // the union check could reference this condition: https://github.com/microsoft/TypeScript/pull/38839#pullrequestreview-618968924 + let access; + if ((type.flags & TypeFlags.Union) && (access = getDiscriminantPropertyAccess(expr, type))) { return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy)); } return type; @@ -24447,8 +24504,8 @@ namespace ts { } if (assumeTrue) { const filterFn: (t: Type) => boolean = operator === SyntaxKind.EqualsEqualsToken ? - t => areTypesComparable(t, valueType) || isCoercibleUnderDoubleEquals(t, valueType) : - t => areTypesComparable(t, valueType); + (t => areTypesComparable(t, valueType) || isCoercibleUnderDoubleEquals(t, valueType) || isNullableComparableUnderDoubleEquals(t, valueType)) : + t => areTypesComparable(t, valueType); return replacePrimitivesWithLiterals(filterType(type, filterFn), valueType); } if (isUnitType(valueType)) { @@ -24457,18 +24514,208 @@ namespace ts { return type; } + interface NarrowDeepPropertyInfo { + // Direct constituent of one union type. + typeId: TypeId; + // Get the type according to path from direct constituent. `undefined` means impossiable to reach type according to path. + finalType: Type | undefined; + // whether one type contains effective optional chain + // This is especially important when narrow condition is equal to undefined, as a result of optional chain. + containsEffectiveOptionalChain: boolean; + } + + /** + * Assume there is variable `foo` whose type is `A`, try to get the final type of foo.property1.proerty2... + * @param type Assume this should be just the type of 'reference' + * @param expressionWithOutKeyword an expression without any keyword. "typeof root.a" is not acceptable. + */ + function getPropertyTypesFromTypeByBindingElementOrExpression(type: Type, expressionWithOutKeyword: BindingElement | Expression | ParameterDeclaration): NarrowDeepPropertyInfo[] | undefined { + interface PathInfo { + path: __String; + isOptionalChain: boolean; + } + + let callExpressionFlag = false; + if (isCallExpression(expressionWithOutKeyword)) { + callExpressionFlag = true; + expressionWithOutKeyword = expressionWithOutKeyword.expression; + } + + const nonCallExpressionWithOutKeyword = expressionWithOutKeyword; + + // check some condition, if not meet, it means we could not handle this confition for now. + if (nonCallExpressionWithOutKeyword.kind !== SyntaxKind.Identifier && nonCallExpressionWithOutKeyword.kind !== SyntaxKind.BindingElement && nonCallExpressionWithOutKeyword.kind !== SyntaxKind.Parameter && !isAccessExpression(nonCallExpressionWithOutKeyword)) {// || (expressionWithOutKeyword).expression.kind === SyntaxKind.ThisKeyword) { + return undefined; + } + + const propertyPaths = tryGetPropertyPathsOfReferenceFromExpression(nonCallExpressionWithOutKeyword, reference); + if (!propertyPaths) { + return undefined; + } + + // In most case, if sometype in the union type could not reach the path, + // it should be an error which is not handled by this function, and we just not continue filter types. + // But, we must consider some edge cases, like: + // 1. type A is { a: undefined }. + // 2. type B is { a: never }. + // Now we have `type C = { a: {innerType: 1} }` + // for case 1, create `type X = A|C`, it should be filtered through optional chain, and not cause any error, although A.a does not have any inner type. Like `root.a?.innerType` is valid. + // for case 2, it is similar, and we do not even need optional chain. Like `root.a.innerType` + + let propertyTypeArray: NarrowDeepPropertyInfo[] | undefined; + forEachType(type, t => { + const propType = getPropertyTypeFromTypeAccordingToPath(t, propertyPaths, callExpressionFlag); + if (propType) { + propertyTypeArray = append(propertyTypeArray, propType); + } + else { + propertyTypeArray = undefined; + return true; + } + }); + + return propertyTypeArray; + + // Assume reference is a + // If expression is a, return [] + // If expression is a.b["c"].d(), return ["b","c","d"] + // If element is BindingElement 'const x = a.b.c', return ["b", "c"] + // If element is BindingElement 'const { c: x } = a.b', return ["b", "c"] + // if element is ParameterDeclaration '(a, b)=>{a.x.y}' return the index of parameters, in this example, returns ["0", "x", "y"] + // NOTE: If element expression is not known in compile progress like a.b[f()].d, the result would be undefined + // NOTE: Binding element is restricted for now: reference must be more "expanded" than node, which might be a binding element. See this example: + // const tmp1 = root.a.b; const { b : tmp2 } = root.a; + // if (tmp1.c.d === "A") root.a.b // root would be narrowed + // if (root.a.b.c.d === "A") tmp1.c.d // however, tmp1 would not be narrowed for now + // The result is similar for tmp2 + // //NOTE: this function need improvement, ElementAccessExpression argument might could be known in compile time, like "1"+"2", we should check "12" in the path, but how to get the value? + function tryGetPropertyPathsOfReferenceFromExpression(node: Expression | BindingElement | ParameterDeclaration, reference: Node): PathInfo[] | undefined { + const properties = []; + let exprOrBindingElement: BindingElement | Expression | ParameterDeclaration | undefined = node; + let access: Expression | undefined; + + while (exprOrBindingElement && !isMatchingReference(reference, currentNode()) && (isAccessExpression(exprOrBindingElement) || isBindingElement(exprOrBindingElement) || isParameter(exprOrBindingElement))) { + const propName = getAccessedPropertyName(exprOrBindingElement); + if (!propName) { + return undefined; + } + properties.unshift({ path: propName, isOptionalChain: isOptionalChain(exprOrBindingElement) }); + // When `exprOrBindingElement` is ParameterDeclaration, we have got all property paths. + // When `exprOrBindingElement` is bindElement, there are two conditions: + // 1. const { bindingElement } = parentObject; + // 2. function foo({ bindingElement }) {...} + // For 1, `access` is `parentObject` + // For 2, we have got all property paths + if (isParameter(exprOrBindingElement) || (isBindingElement(exprOrBindingElement) && !exprOrBindingElement.initializer && !exprOrBindingElement.dotDotDotToken && reference === exprOrBindingElement.parent)) { + return properties; + } + access = isBindingElement(exprOrBindingElement) ? exprOrBindingElement.parent.parent.initializer : exprOrBindingElement.expression; + if (!access) { + return undefined; + } + if (isMatchingReference(reference, access)) { + return properties; + } + exprOrBindingElement = getCandidateDiscriminantPropertyAccess(access); + } + + if (isMatchingReference(reference, currentNode())) { + return properties; + } + + function currentNode() { + if (exprOrBindingElement) return exprOrBindingElement; + if (access) return access; + throw new Error("Never"); + } + } + + function getPropertyTypeFromTypeAccordingToPath(constituentType: Type, pathInfos: PathInfo[], isCallExpression: boolean): NarrowDeepPropertyInfo | undefined { + let propType: Type | undefined = constituentType; + const typeId = constituentType.id; + let containsEffectiveOptionalChain = false; + for (const pathInfo of pathInfos) { + const path = pathInfo.path; + const isEffectiveOptionalChain = strictNullChecks && pathInfo.isOptionalChain && maybeTypeOfKind(propType, TypeFlags.Nullable); + if (isEffectiveOptionalChain) { + containsEffectiveOptionalChain = true; + } + if (propType.flags & TypeFlags.Nullable) { + return { typeId, finalType: undefined, containsEffectiveOptionalChain }; + } + const nonNullableTypeIfStrict = getNonNullableTypeIfNeeded(propType); + if (nonNullableTypeIfStrict.flags & TypeFlags.UnionOrIntersection) { + // although getTypeOfPropertyOfType use getPropertyOfUnionOrIntersectionType, but in getReducedApparentType + // intersection type that contains mutually exclusive discriminant properties returns never. + const prop = getPropertyOfUnionOrIntersectionType(nonNullableTypeIfStrict as UnionOrIntersectionType, path); + propType = prop && getTypeOfSymbol(prop); // unknownType is to keep coninstance with the return value of getTypeOfPropertyOrIndexSignature + } + else { + propType = getTypeOfPropertyOrIndexSignature(nonNullableTypeIfStrict, path); + } + + if (!propType) { + return undefined; + } + } + + // here could be improved, now, we access all return type for the signature, but it could use parameter to get reduced return types. + if (isCallExpression && propType && propType.flags & TypeFlags.Object) { + const returnTypes = (propType as ObjectType).callSignatures?.map(getReturnTypeOfSignature); + return returnTypes && { + typeId, + finalType: getUnionType(returnTypes), + containsEffectiveOptionalChain + }; + } + + return { + typeId, + finalType: propType, + containsEffectiveOptionalChain + }; + } + } + function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type { // We have '==', '!=', '===', or !==' operator with 'typeof xxx' and string literal operands if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } + const facts = assumeTrue ? + typeofEQFacts.get(literal.text) || TypeFacts.TypeofEQHostObject : + typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject; const target = getReferenceCandidate(typeOfExpr.expression); if (!isMatchingReference(reference, target)) { - if (strictNullChecks && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) { - return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); + if (type.flags & TypeFlags.Union) { + const propertyTypes = getPropertyTypesFromTypeByBindingElementOrExpression(type as UnionType, typeOfExpr.expression); + const impliedUndefined = (assumeTrue && literal.text === "undefined") || (!assumeTrue && literal.text !== "undefined"); + if (!propertyTypes) { + return type; + } + const markSet = new Set(); + + propertyTypes.forEach(propertyType => { + if (!propertyType.finalType && !propertyType.containsEffectiveOptionalChain) { + return; + } + const reachableFinalType = propertyType.finalType; + if (propertyType.containsEffectiveOptionalChain && impliedUndefined) { + markSet.add(propertyType.typeId); + } + else if (!!reachableFinalType) { + const propertyTypeFacts = getTypeFacts(reachableFinalType); + if ((propertyTypeFacts & facts) === facts) { + markSet.add(propertyType.typeId); + } + } + }); + return filterType(type, (t) => markSet.has(t.id)); } return type; } + + // following code is all for typeof expression. if (type.flags & TypeFlags.Any && literal.text === "function") { return type; } @@ -24478,9 +24725,6 @@ namespace ts { // unknown type, and then narrows that to the non-primitive type. return type === nonNullUnknownType ? nonPrimitiveType : getUnionType([nonPrimitiveType, nullType]); } - const facts = assumeTrue ? - typeofEQFacts.get(literal.text) || TypeFacts.TypeofEQHostObject : - typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject; const impliedType = getImpliedTypeFromTypeofGuard(type, literal.text); return getTypeWithFacts(assumeTrue && impliedType ? mapType(type, narrowUnionMemberByTypeof(impliedType)) : type, facts); } @@ -24593,9 +24837,6 @@ namespace ts { clauseWitnesses = switchWitnesses.slice(clauseStart, clauseEnd) as string[]; switchFacts = getFactsFromTypeofSwitch(clauseStart, clauseEnd, switchWitnesses as string[], 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. @@ -24624,8 +24865,38 @@ namespace ts { boolean. We know that number cannot be selected because it is caught in the first clause. */ + const expr = (switchStatement.expression as TypeOfExpression).expression; const impliedType = getTypeWithFacts(getUnionType(clauseWitnesses.map(text => getImpliedTypeFromTypeofGuard(type, text) || type)), switchFacts); - return getTypeWithFacts(mapType(type, narrowUnionMemberByTypeof(impliedType)), switchFacts); + if (isMatchingReference(reference, expr)) { + if (hasDefaultClause) { + return filterType(type, t => (getTypeFacts(t) & switchFacts) === switchFacts); + } + return getTypeWithFacts(mapType(type, narrowUnionMemberByTypeof(impliedType)), switchFacts); + } + const impliedUndefined = hasDefaultClause ? !(switchFacts & TypeFacts.NEUndefined) : (switchFacts & TypeFacts.EQUndefined); + const propertyTypeArray = getPropertyTypesFromTypeByBindingElementOrExpression(type as UnionType, expr); + + if (!propertyTypeArray) { + return type; + } + const markSet = new Set(); + + propertyTypeArray.forEach(propertyType => { + if (!propertyType.finalType && !propertyType.containsEffectiveOptionalChain) { + return; + } + const reachableFinalType = propertyType.finalType; + if (propertyType.containsEffectiveOptionalChain && impliedUndefined) { + markSet.add(propertyType.typeId); + } + else if (!!reachableFinalType) { + const propertyTypeFacts = getTypeFacts(reachableFinalType); + if (!hasDefaultClause ? propertyTypeFacts & switchFacts : ((propertyTypeFacts & switchFacts) === switchFacts)) { + markSet.add(propertyType.typeId); + } + } + }); + return filterType(type, (t) => markSet.has(t.id)); } function isMatchingConstructorReference(expr: Expression) { @@ -24798,8 +25069,7 @@ namespace ts { // will be a subtype or the same type as the argument. function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { // for `a?.b`, we emulate a synthetic `a !== null && a !== undefined` condition for `a` - if (isExpressionOfOptionalChainRoot(expr) || - isBinaryExpression(expr.parent) && expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken && expr.parent.left === expr) { + if (isExpressionOfOptionalChainRoot(expr) || isInQuestionQuestionTokenBranch(expr)) { return narrowTypeByOptionality(type, expr, assumeTrue); } switch (expr.kind) { @@ -24840,6 +25110,27 @@ namespace ts { return type; } + function isInQuestionQuestionTokenBranch(expression: Expression) { + let outAccessExpression = expression; + let depth = 0; + let lastExpression; + do { + depth = depth + 1; + lastExpression = outAccessExpression; + if (!isExpression(outAccessExpression.parent)) {// or isExpressionNode? which one should be used? + return false; + } + outAccessExpression = outAccessExpression.parent; + } + while (isAccessExpression(outAccessExpression)); + const isQuestionQuestionTokenExpression = isBinaryExpression(outAccessExpression) && outAccessExpression.operatorToken.kind === SyntaxKind.QuestionQuestionToken; + if (!isQuestionQuestionTokenExpression) { + return false; + } + const isExpressOnLeft = (outAccessExpression as BinaryExpression).left === lastExpression; + return isQuestionQuestionTokenExpression && isExpressOnLeft; + } + function narrowTypeByOptionality(type: Type, expr: Expression, assumePresent: boolean): Type { if (isMatchingReference(reference, expr)) { return getTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull); @@ -33978,6 +34269,7 @@ namespace ts { return quickType; } // If a type has been cached for the node, return it. + // Note: this is not only cache, without this, some test case would keep running, such as binaryArithmeticControlFlowGraphNotTooLarge. if (node.flags & NodeFlags.TypeCached && flowTypeCache) { const cachedType = flowTypeCache[getNodeId(node)]; if (cachedType) { @@ -40150,8 +40442,8 @@ namespace ts { // If we hit an export assignment in an illegal context, just bail out to avoid cascading errors. return; } - - const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent as ModuleDeclaration; + // use any to avoid type narrow + const container = (node.parent as any).kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent as ModuleDeclaration; if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) { if (node.isExportEquals) { error(node, Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace); diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 48ac670c8bea3..38729c172126c 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1283,8 +1283,8 @@ namespace ts { const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); - const realpathSync = _fs.realpathSync.native ?? _fs.realpathSync; - + // Use `any` to avoid type narrow. + const realpathSync = (_fs as any).realpathSync.native ?? _fs.realpathSync; const fsSupportsRecursiveFsWatch = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin"); const getCurrentDirectory = memoize(() => process.cwd()); const { watchFile, watchDirectory } = createSystemWatchFunctions({ diff --git a/src/server/session.ts b/src/server/session.ts index b0bb42dade1ca..fcd1aef197604 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1516,7 +1516,8 @@ namespace ts.server { // filter handles case when 'projects' is undefined projects = filter(projects, p => p.languageServiceEnabled && !p.isOrphan()); if (!ignoreNoProjectError && (!projects || !projects.length) && !symLinkedProjects) { - this.projectService.logErrorForScriptInfoNotFound(args.file ?? args.projectFileName); + // use `any` to avoid type narrow + this.projectService.logErrorForScriptInfoNotFound((args as any).file ?? args.projectFileName); return Errors.ThrowNoProject(); } return symLinkedProjects ? { projects: projects!, symLinkedProjects } : projects!; // TODO: GH#18217 diff --git a/tests/baselines/reference/controlFlowOptionalChain.errors.txt b/tests/baselines/reference/controlFlowOptionalChain.errors.txt index 1dfe8e9e328a0..17fbb84f7d7e2 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.errors.txt +++ b/tests/baselines/reference/controlFlowOptionalChain.errors.txt @@ -57,11 +57,10 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(463,9): error TS tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(498,13): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(501,13): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(515,13): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(518,13): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error TS2532: Object is possibly 'undefined'. -==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (61 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (60 errors) ==== // assignments in shortcutting chain declare const o: undefined | { [key: string]: any; @@ -697,9 +696,7 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T !!! error TS2532: Object is possibly 'undefined'. break; default: - o.foo; // Error - ~ -!!! error TS2532: Object is possibly 'undefined'. + o.foo; break; } } diff --git a/tests/baselines/reference/controlFlowOptionalChain.js b/tests/baselines/reference/controlFlowOptionalChain.js index dc2361d860984..25386b69c2746 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.js +++ b/tests/baselines/reference/controlFlowOptionalChain.js @@ -516,7 +516,7 @@ function f41(o: Thing | undefined) { o.foo; // Error break; default: - o.foo; // Error + o.foo; break; } } @@ -1049,7 +1049,7 @@ function f41(o) { o.foo; // Error break; default: - o.foo; // Error + o.foo; break; } } diff --git a/tests/baselines/reference/controlFlowOptionalChain.symbols b/tests/baselines/reference/controlFlowOptionalChain.symbols index be03f36c67da6..5e1f91aafd56f 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.symbols +++ b/tests/baselines/reference/controlFlowOptionalChain.symbols @@ -1438,9 +1438,7 @@ function f23(o: Thing | undefined) { >foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) o.foo; // Error ->o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) >o : Symbol(o, Decl(controlFlowOptionalChain.ts, 439, 13)) ->foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) } else { o.foo; @@ -1460,9 +1458,7 @@ function f23(o: Thing | undefined) { } else { o.foo; // Error ->o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) >o : Symbol(o, Decl(controlFlowOptionalChain.ts, 439, 13)) ->foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) } if (typeof o?.foo == "undefined") { >o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) @@ -1470,9 +1466,7 @@ function f23(o: Thing | undefined) { >foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) o.foo; // Error ->o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) >o : Symbol(o, Decl(controlFlowOptionalChain.ts, 439, 13)) ->foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) } else { o.foo; @@ -1492,9 +1486,7 @@ function f23(o: Thing | undefined) { } else { o.foo; // Error ->o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) >o : Symbol(o, Decl(controlFlowOptionalChain.ts, 439, 13)) ->foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) } } @@ -1636,13 +1628,11 @@ function f41(o: Thing | undefined) { break; case "undefined": o.foo; // Error ->o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) >o : Symbol(o, Decl(controlFlowOptionalChain.ts, 505, 13)) ->foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) break; default: - o.foo; // Error + o.foo; >o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) >o : Symbol(o, Decl(controlFlowOptionalChain.ts, 505, 13)) >foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14)) diff --git a/tests/baselines/reference/controlFlowOptionalChain.types b/tests/baselines/reference/controlFlowOptionalChain.types index 4e335fca6d287..9b404b7a02c26 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.types +++ b/tests/baselines/reference/controlFlowOptionalChain.types @@ -1618,9 +1618,9 @@ function f23(o: Thing | undefined) { >"undefined" : "undefined" o.foo; // Error ->o.foo : never ->o : Thing | undefined ->foo : never +>o.foo : any +>o : undefined +>foo : any } else { o.foo; @@ -1643,9 +1643,9 @@ function f23(o: Thing | undefined) { } else { o.foo; // Error ->o.foo : never ->o : Thing | undefined ->foo : never +>o.foo : any +>o : undefined +>foo : any } if (typeof o?.foo == "undefined") { >typeof o?.foo == "undefined" : boolean @@ -1656,9 +1656,9 @@ function f23(o: Thing | undefined) { >"undefined" : "undefined" o.foo; // Error ->o.foo : never ->o : Thing | undefined ->foo : never +>o.foo : any +>o : undefined +>foo : any } else { o.foo; @@ -1681,9 +1681,9 @@ function f23(o: Thing | undefined) { } else { o.foo; // Error ->o.foo : never ->o : Thing | undefined ->foo : never +>o.foo : any +>o : undefined +>foo : any } } @@ -1852,15 +1852,15 @@ function f41(o: Thing | undefined) { >"undefined" : "undefined" o.foo; // Error ->o.foo : never ->o : Thing | undefined ->foo : never +>o.foo : any +>o : undefined +>foo : any break; default: - o.foo; // Error + o.foo; >o.foo : never ->o : Thing | undefined +>o : Thing >foo : never break; diff --git a/tests/baselines/reference/destructuringControlFlow.types b/tests/baselines/reference/destructuringControlFlow.types index 02deb39200688..a9852433f239d 100644 --- a/tests/baselines/reference/destructuringControlFlow.types +++ b/tests/baselines/reference/destructuringControlFlow.types @@ -63,34 +63,34 @@ function f2(obj: [number, string] | null[]) { >obj[0] : number | null >obj : [number, string] | null[] >0 : 0 ->obj[1] : string | null ->obj : [number, string] | null[] +>obj[1] : string +>obj : [number, string] >1 : 1 let c0 = obj[0]; // number >c0 : number >obj[0] : number ->obj : [number, string] | null[] +>obj : [number, string] >0 : 0 let c1 = obj[1]; // string >c1 : string >obj[1] : string ->obj : [number, string] | null[] +>obj : [number, string] >1 : 1 let [d0, d1] = obj; >d0 : number >d1 : string ->obj : [number, string] | null[] +>obj : [number, string] ([c0, c1] = obj); ->([c0, c1] = obj) : [number, string] | null[] ->[c0, c1] = obj : [number, string] | null[] +>([c0, c1] = obj) : [number, string] +>[c0, c1] = obj : [number, string] >[c0, c1] : [number, string] >c0 : number >c1 : string ->obj : [number, string] | null[] +>obj : [number, string] } } diff --git a/tests/baselines/reference/discriminatedUnionTypes2.errors.txt b/tests/baselines/reference/discriminatedUnionTypes2.errors.txt index f2ced8d19fa6c..0cb87c1aa5931 100644 --- a/tests/baselines/reference/discriminatedUnionTypes2.errors.txt +++ b/tests/baselines/reference/discriminatedUnionTypes2.errors.txt @@ -2,9 +2,10 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(27,30): error TS Object literal may only specify known properties, and 'c' does not exist in type '{ a: null; b: string; }'. tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(32,11): error TS2339: Property 'b' does not exist on type '{ a: 0; b: string; } | { a: T; c: number; }'. Property 'b' does not exist on type '{ a: T; c: number; }'. +tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(132,11): error TS2339: Property 'value' does not exist on type 'never'. -==== tests/cases/conformance/types/union/discriminatedUnionTypes2.ts (2 errors) ==== +==== tests/cases/conformance/types/union/discriminatedUnionTypes2.ts (3 errors) ==== function f10(x : { kind: false, a: string } | { kind: true, b: string } | { kind: string, c: string }) { if (x.kind === false) { x.a; @@ -142,7 +143,9 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(32,11): error TS x.value; // number } else { - x.value; // number + x.value; // Error, x is never + ~~~~~ +!!! error TS2339: Property 'value' does not exist on type 'never'. } } diff --git a/tests/baselines/reference/discriminatedUnionTypes2.js b/tests/baselines/reference/discriminatedUnionTypes2.js index b94c386b4699e..584678ee7fa53 100644 --- a/tests/baselines/reference/discriminatedUnionTypes2.js +++ b/tests/baselines/reference/discriminatedUnionTypes2.js @@ -130,7 +130,7 @@ function foo1(x: RuntimeValue & { type: 'number' }) { x.value; // number } else { - x.value; // number + x.value; // Error, x is never } } @@ -226,7 +226,7 @@ function foo1(x) { x.value; // number } else { - x.value; // number + x.value; // Error, x is never } } function foo2(x) { diff --git a/tests/baselines/reference/discriminatedUnionTypes2.symbols b/tests/baselines/reference/discriminatedUnionTypes2.symbols index 747f43ac21e4c..f2a511b6d23dc 100644 --- a/tests/baselines/reference/discriminatedUnionTypes2.symbols +++ b/tests/baselines/reference/discriminatedUnionTypes2.symbols @@ -366,10 +366,8 @@ function foo1(x: RuntimeValue & { type: 'number' }) { >value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23)) } else { - x.value; // number ->x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23)) + x.value; // Error, x is never >x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 126, 14)) ->value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23)) } } diff --git a/tests/baselines/reference/discriminatedUnionTypes2.types b/tests/baselines/reference/discriminatedUnionTypes2.types index 695f0c3768f00..285c4dd4a6839 100644 --- a/tests/baselines/reference/discriminatedUnionTypes2.types +++ b/tests/baselines/reference/discriminatedUnionTypes2.types @@ -379,10 +379,10 @@ function foo1(x: RuntimeValue & { type: 'number' }) { >value : number } else { - x.value; // number ->x.value : number ->x : { type: "number"; value: number; } & { type: "number"; } ->value : number + x.value; // Error, x is never +>x.value : any +>x : never +>value : any } } diff --git a/tests/baselines/reference/discriminatedUnionTypes3.errors.txt b/tests/baselines/reference/discriminatedUnionTypes3.errors.txt new file mode 100644 index 0000000000000..6d365202ad06a --- /dev/null +++ b/tests/baselines/reference/discriminatedUnionTypes3.errors.txt @@ -0,0 +1,91 @@ +tests/cases/conformance/types/union/discriminatedUnionTypes3.ts(59,11): error TS2339: Property 's' does not exist on type 'T'. +tests/cases/conformance/types/union/discriminatedUnionTypes3.ts(78,10): error TS2339: Property 'property' does not exist on type 'SomeReturnType'. + Property 'property' does not exist on type 'Err'. + + +==== tests/cases/conformance/types/union/discriminatedUnionTypes3.ts (2 errors) ==== + type A = { type2: "a", a: number } + type B = { type2: "b", b: number } + type C = { type2: "c", b: number | string } + + type X = { type1: A, x: string } + type Y = { type1: B, y: string } + type Z = { type1: C, z: string } + type W = { type1: undefined } + + function f32(x: X | Y) { + switch (x.type1.type2) { + case "a": + x.x // typeof x is X + break; + case "b": + x.y // typeof x is Y + break; + } + } + + function f33(x: A | B) { + switch (x.type2) { + case "a": + x // typeof x is X + break; + case "b": + x // typeof x is Y + break; + } + } + + function f34(x: X | Y) { + if (x.type1.type2 === "a") { + x.x // typeof x is X + } else if (x.type1.type2 === "b") { + x.y // typeof x is Y + } + } + + function f35(x: X | W) { + if (x.type1?.type2 === "a") { + x.x + } + } + + function f36(x: X | W) { + x.type1?.type2 ?? x; + } + + type S = { sub: { type0: X }, s: string } + type T = { sub: { type0: Y }, t: string } + + function f37(s: S | T) { + if (s.sub.type0.type1.type2 === "a") { + s.s // typeof s is S + s.sub.type0.x // type of s.sub.type is X + s.sub.type0.type1.a // type of s.sub.type.type is A + } else { + s.s // type error! + ~ +!!! error TS2339: Property 's' does not exist on type 'T'. + } + } + + // Repro from #44435 + + type Correct = { + code: string + property: true + err: undefined + } + type Err = { + err: `${string} is wrong!` + } + type SomeReturnType = Correct | Err; + + const example: SomeReturnType = {} as SomeReturnType; + + if (example.err === undefined) { + example.property; // true + ~~~~~~~~ +!!! error TS2339: Property 'property' does not exist on type 'SomeReturnType'. +!!! error TS2339: Property 'property' does not exist on type 'Err'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/discriminatedUnionTypes3.js b/tests/baselines/reference/discriminatedUnionTypes3.js index 74edcd85ac0be..92a940be65141 100644 --- a/tests/baselines/reference/discriminatedUnionTypes3.js +++ b/tests/baselines/reference/discriminatedUnionTypes3.js @@ -1,4 +1,66 @@ //// [discriminatedUnionTypes3.ts] +type A = { type2: "a", a: number } +type B = { type2: "b", b: number } +type C = { type2: "c", b: number | string } + +type X = { type1: A, x: string } +type Y = { type1: B, y: string } +type Z = { type1: C, z: string } +type W = { type1: undefined } + +function f32(x: X | Y) { + switch (x.type1.type2) { + case "a": + x.x // typeof x is X + break; + case "b": + x.y // typeof x is Y + break; + } +} + +function f33(x: A | B) { + switch (x.type2) { + case "a": + x // typeof x is X + break; + case "b": + x // typeof x is Y + break; + } +} + +function f34(x: X | Y) { + if (x.type1.type2 === "a") { + x.x // typeof x is X + } else if (x.type1.type2 === "b") { + x.y // typeof x is Y + } +} + +function f35(x: X | W) { + if (x.type1?.type2 === "a") { + x.x + } +} + +function f36(x: X | W) { + x.type1?.type2 ?? x; +} + +type S = { sub: { type0: X }, s: string } +type T = { sub: { type0: Y }, t: string } + +function f37(s: S | T) { + if (s.sub.type0.type1.type2 === "a") { + s.s // typeof s is S + s.sub.type0.x // type of s.sub.type is X + s.sub.type0.type1.a // type of s.sub.type.type is A + } else { + s.s // type error! + } +} + // Repro from #44435 type Correct = { @@ -15,11 +77,59 @@ const example: SomeReturnType = {} as SomeReturnType; if (example.err === undefined) { example.property; // true -} +} + //// [discriminatedUnionTypes3.js] "use strict"; -// Repro from #44435 +function f32(x) { + switch (x.type1.type2) { + case "a": + x.x; // typeof x is X + break; + case "b": + x.y; // typeof x is Y + break; + } +} +function f33(x) { + switch (x.type2) { + case "a": + x; // typeof x is X + break; + case "b": + x; // typeof x is Y + break; + } +} +function f34(x) { + if (x.type1.type2 === "a") { + x.x; // typeof x is X + } + else if (x.type1.type2 === "b") { + x.y; // typeof x is Y + } +} +function f35(x) { + var _a; + if (((_a = x.type1) === null || _a === void 0 ? void 0 : _a.type2) === "a") { + x.x; + } +} +function f36(x) { + var _a, _b; + (_b = (_a = x.type1) === null || _a === void 0 ? void 0 : _a.type2) !== null && _b !== void 0 ? _b : x; +} +function f37(s) { + if (s.sub.type0.type1.type2 === "a") { + s.s; // typeof s is S + s.sub.type0.x; // type of s.sub.type is X + s.sub.type0.type1.a; // type of s.sub.type.type is A + } + else { + s.s; // type error! + } +} var example = {}; if (example.err === undefined) { example.property; // true diff --git a/tests/baselines/reference/discriminatedUnionTypes3.symbols b/tests/baselines/reference/discriminatedUnionTypes3.symbols index 65fdd49877055..b88fb150d6e81 100644 --- a/tests/baselines/reference/discriminatedUnionTypes3.symbols +++ b/tests/baselines/reference/discriminatedUnionTypes3.symbols @@ -1,42 +1,261 @@ === tests/cases/conformance/types/union/discriminatedUnionTypes3.ts === +type A = { type2: "a", a: number } +>A : Symbol(A, Decl(discriminatedUnionTypes3.ts, 0, 0)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10)) +>a : Symbol(a, Decl(discriminatedUnionTypes3.ts, 0, 22)) + +type B = { type2: "b", b: number } +>B : Symbol(B, Decl(discriminatedUnionTypes3.ts, 0, 34)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 1, 10)) +>b : Symbol(b, Decl(discriminatedUnionTypes3.ts, 1, 22)) + +type C = { type2: "c", b: number | string } +>C : Symbol(C, Decl(discriminatedUnionTypes3.ts, 1, 34)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 2, 10)) +>b : Symbol(b, Decl(discriminatedUnionTypes3.ts, 2, 22)) + +type X = { type1: A, x: string } +>X : Symbol(X, Decl(discriminatedUnionTypes3.ts, 2, 43)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10)) +>A : Symbol(A, Decl(discriminatedUnionTypes3.ts, 0, 0)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) + +type Y = { type1: B, y: string } +>Y : Symbol(Y, Decl(discriminatedUnionTypes3.ts, 4, 32)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 5, 10)) +>B : Symbol(B, Decl(discriminatedUnionTypes3.ts, 0, 34)) +>y : Symbol(y, Decl(discriminatedUnionTypes3.ts, 5, 20)) + +type Z = { type1: C, z: string } +>Z : Symbol(Z, Decl(discriminatedUnionTypes3.ts, 5, 32)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 6, 10)) +>C : Symbol(C, Decl(discriminatedUnionTypes3.ts, 1, 34)) +>z : Symbol(z, Decl(discriminatedUnionTypes3.ts, 6, 20)) + +type W = { type1: undefined } +>W : Symbol(W, Decl(discriminatedUnionTypes3.ts, 6, 32)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 7, 10)) + +function f32(x: X | Y) { +>f32 : Symbol(f32, Decl(discriminatedUnionTypes3.ts, 7, 29)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 9, 13)) +>X : Symbol(X, Decl(discriminatedUnionTypes3.ts, 2, 43)) +>Y : Symbol(Y, Decl(discriminatedUnionTypes3.ts, 4, 32)) + + switch (x.type1.type2) { +>x.type1.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) +>x.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 5, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 9, 13)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 5, 10)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) + + case "a": + x.x // typeof x is X +>x.x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 9, 13)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) + + break; + case "b": + x.y // typeof x is Y +>x.y : Symbol(y, Decl(discriminatedUnionTypes3.ts, 5, 20)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 9, 13)) +>y : Symbol(y, Decl(discriminatedUnionTypes3.ts, 5, 20)) + + break; + } +} + +function f33(x: A | B) { +>f33 : Symbol(f33, Decl(discriminatedUnionTypes3.ts, 18, 1)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 20, 13)) +>A : Symbol(A, Decl(discriminatedUnionTypes3.ts, 0, 0)) +>B : Symbol(B, Decl(discriminatedUnionTypes3.ts, 0, 34)) + + switch (x.type2) { +>x.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 20, 13)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) + + case "a": + x // typeof x is X +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 20, 13)) + + break; + case "b": + x // typeof x is Y +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 20, 13)) + + break; + } +} + +function f34(x: X | Y) { +>f34 : Symbol(f34, Decl(discriminatedUnionTypes3.ts, 29, 1)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 31, 13)) +>X : Symbol(X, Decl(discriminatedUnionTypes3.ts, 2, 43)) +>Y : Symbol(Y, Decl(discriminatedUnionTypes3.ts, 4, 32)) + + if (x.type1.type2 === "a") { +>x.type1.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) +>x.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 5, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 31, 13)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 5, 10)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) + + x.x // typeof x is X +>x.x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 31, 13)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) + + } else if (x.type1.type2 === "b") { +>x.type1.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 1, 10)) +>x.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 5, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 31, 13)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 5, 10)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 1, 10)) + + x.y // typeof x is Y +>x.y : Symbol(y, Decl(discriminatedUnionTypes3.ts, 5, 20)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 31, 13)) +>y : Symbol(y, Decl(discriminatedUnionTypes3.ts, 5, 20)) + } +} + +function f35(x: X | W) { +>f35 : Symbol(f35, Decl(discriminatedUnionTypes3.ts, 37, 1)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 39, 13)) +>X : Symbol(X, Decl(discriminatedUnionTypes3.ts, 2, 43)) +>W : Symbol(W, Decl(discriminatedUnionTypes3.ts, 6, 32)) + + if (x.type1?.type2 === "a") { +>x.type1?.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10)) +>x.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 7, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 39, 13)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 7, 10)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10)) + + x.x +>x.x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 39, 13)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) + } +} + +function f36(x: X | W) { +>f36 : Symbol(f36, Decl(discriminatedUnionTypes3.ts, 43, 1)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 45, 13)) +>X : Symbol(X, Decl(discriminatedUnionTypes3.ts, 2, 43)) +>W : Symbol(W, Decl(discriminatedUnionTypes3.ts, 6, 32)) + + x.type1?.type2 ?? x; +>x.type1?.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10)) +>x.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 7, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 45, 13)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 7, 10)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 45, 13)) +} + +type S = { sub: { type0: X }, s: string } +>S : Symbol(S, Decl(discriminatedUnionTypes3.ts, 47, 1)) +>sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10)) +>type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17)) +>X : Symbol(X, Decl(discriminatedUnionTypes3.ts, 2, 43)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 49, 29)) + +type T = { sub: { type0: Y }, t: string } +>T : Symbol(T, Decl(discriminatedUnionTypes3.ts, 49, 41)) +>sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 50, 10)) +>type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 50, 17)) +>Y : Symbol(Y, Decl(discriminatedUnionTypes3.ts, 4, 32)) +>t : Symbol(t, Decl(discriminatedUnionTypes3.ts, 50, 29)) + +function f37(s: S | T) { +>f37 : Symbol(f37, Decl(discriminatedUnionTypes3.ts, 50, 41)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 52, 13)) +>S : Symbol(S, Decl(discriminatedUnionTypes3.ts, 47, 1)) +>T : Symbol(T, Decl(discriminatedUnionTypes3.ts, 49, 41)) + + if (s.sub.type0.type1.type2 === "a") { +>s.sub.type0.type1.type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) +>s.sub.type0.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 5, 10)) +>s.sub.type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17), Decl(discriminatedUnionTypes3.ts, 50, 17)) +>s.sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10), Decl(discriminatedUnionTypes3.ts, 50, 10)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 52, 13)) +>sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10), Decl(discriminatedUnionTypes3.ts, 50, 10)) +>type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17), Decl(discriminatedUnionTypes3.ts, 50, 17)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10), Decl(discriminatedUnionTypes3.ts, 5, 10)) +>type2 : Symbol(type2, Decl(discriminatedUnionTypes3.ts, 0, 10), Decl(discriminatedUnionTypes3.ts, 1, 10)) + + s.s // typeof s is S +>s.s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 49, 29)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 52, 13)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 49, 29)) + + s.sub.type0.x // type of s.sub.type is X +>s.sub.type0.x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) +>s.sub.type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17)) +>s.sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 52, 13)) +>sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10)) +>type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17)) +>x : Symbol(x, Decl(discriminatedUnionTypes3.ts, 4, 20)) + + s.sub.type0.type1.a // type of s.sub.type.type is A +>s.sub.type0.type1.a : Symbol(a, Decl(discriminatedUnionTypes3.ts, 0, 22)) +>s.sub.type0.type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10)) +>s.sub.type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17)) +>s.sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10)) +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 52, 13)) +>sub : Symbol(sub, Decl(discriminatedUnionTypes3.ts, 49, 10)) +>type0 : Symbol(type0, Decl(discriminatedUnionTypes3.ts, 49, 17)) +>type1 : Symbol(type1, Decl(discriminatedUnionTypes3.ts, 4, 10)) +>a : Symbol(a, Decl(discriminatedUnionTypes3.ts, 0, 22)) + + } else { + s.s // type error! +>s : Symbol(s, Decl(discriminatedUnionTypes3.ts, 52, 13)) + } +} + // Repro from #44435 type Correct = { ->Correct : Symbol(Correct, Decl(discriminatedUnionTypes3.ts, 0, 0)) +>Correct : Symbol(Correct, Decl(discriminatedUnionTypes3.ts, 60, 1)) code: string ->code : Symbol(code, Decl(discriminatedUnionTypes3.ts, 2, 16)) +>code : Symbol(code, Decl(discriminatedUnionTypes3.ts, 64, 16)) property: true ->property : Symbol(property, Decl(discriminatedUnionTypes3.ts, 3, 13)) +>property : Symbol(property, Decl(discriminatedUnionTypes3.ts, 65, 13)) err: undefined ->err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 4, 15)) +>err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 66, 15)) } type Err = { ->Err : Symbol(Err, Decl(discriminatedUnionTypes3.ts, 6, 1)) +>Err : Symbol(Err, Decl(discriminatedUnionTypes3.ts, 68, 1)) err: `${string} is wrong!` ->err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 7, 12)) +>err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 69, 12)) } type SomeReturnType = Correct | Err; ->SomeReturnType : Symbol(SomeReturnType, Decl(discriminatedUnionTypes3.ts, 9, 1)) ->Correct : Symbol(Correct, Decl(discriminatedUnionTypes3.ts, 0, 0)) ->Err : Symbol(Err, Decl(discriminatedUnionTypes3.ts, 6, 1)) +>SomeReturnType : Symbol(SomeReturnType, Decl(discriminatedUnionTypes3.ts, 71, 1)) +>Correct : Symbol(Correct, Decl(discriminatedUnionTypes3.ts, 60, 1)) +>Err : Symbol(Err, Decl(discriminatedUnionTypes3.ts, 68, 1)) const example: SomeReturnType = {} as SomeReturnType; ->example : Symbol(example, Decl(discriminatedUnionTypes3.ts, 12, 5)) ->SomeReturnType : Symbol(SomeReturnType, Decl(discriminatedUnionTypes3.ts, 9, 1)) ->SomeReturnType : Symbol(SomeReturnType, Decl(discriminatedUnionTypes3.ts, 9, 1)) +>example : Symbol(example, Decl(discriminatedUnionTypes3.ts, 74, 5)) +>SomeReturnType : Symbol(SomeReturnType, Decl(discriminatedUnionTypes3.ts, 71, 1)) +>SomeReturnType : Symbol(SomeReturnType, Decl(discriminatedUnionTypes3.ts, 71, 1)) if (example.err === undefined) { ->example.err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 4, 15), Decl(discriminatedUnionTypes3.ts, 7, 12)) ->example : Symbol(example, Decl(discriminatedUnionTypes3.ts, 12, 5)) ->err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 4, 15), Decl(discriminatedUnionTypes3.ts, 7, 12)) +>example.err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 66, 15), Decl(discriminatedUnionTypes3.ts, 69, 12)) +>example : Symbol(example, Decl(discriminatedUnionTypes3.ts, 74, 5)) +>err : Symbol(err, Decl(discriminatedUnionTypes3.ts, 66, 15), Decl(discriminatedUnionTypes3.ts, 69, 12)) >undefined : Symbol(undefined) example.property; // true ->example.property : Symbol(property, Decl(discriminatedUnionTypes3.ts, 3, 13)) ->example : Symbol(example, Decl(discriminatedUnionTypes3.ts, 12, 5)) ->property : Symbol(property, Decl(discriminatedUnionTypes3.ts, 3, 13)) +>example : Symbol(example, Decl(discriminatedUnionTypes3.ts, 74, 5)) } + diff --git a/tests/baselines/reference/discriminatedUnionTypes3.types b/tests/baselines/reference/discriminatedUnionTypes3.types index 8c645a1773592..b3a62457bfd99 100644 --- a/tests/baselines/reference/discriminatedUnionTypes3.types +++ b/tests/baselines/reference/discriminatedUnionTypes3.types @@ -1,4 +1,226 @@ === tests/cases/conformance/types/union/discriminatedUnionTypes3.ts === +type A = { type2: "a", a: number } +>A : A +>type2 : "a" +>a : number + +type B = { type2: "b", b: number } +>B : B +>type2 : "b" +>b : number + +type C = { type2: "c", b: number | string } +>C : C +>type2 : "c" +>b : string | number + +type X = { type1: A, x: string } +>X : X +>type1 : A +>x : string + +type Y = { type1: B, y: string } +>Y : Y +>type1 : B +>y : string + +type Z = { type1: C, z: string } +>Z : Z +>type1 : C +>z : string + +type W = { type1: undefined } +>W : W +>type1 : undefined + +function f32(x: X | Y) { +>f32 : (x: X | Y) => void +>x : X | Y + + switch (x.type1.type2) { +>x.type1.type2 : "a" | "b" +>x.type1 : A | B +>x : X | Y +>type1 : A | B +>type2 : "a" | "b" + + case "a": +>"a" : "a" + + x.x // typeof x is X +>x.x : string +>x : X +>x : string + + break; + case "b": +>"b" : "b" + + x.y // typeof x is Y +>x.y : string +>x : Y +>y : string + + break; + } +} + +function f33(x: A | B) { +>f33 : (x: A | B) => void +>x : A | B + + switch (x.type2) { +>x.type2 : "a" | "b" +>x : A | B +>type2 : "a" | "b" + + case "a": +>"a" : "a" + + x // typeof x is X +>x : A + + break; + case "b": +>"b" : "b" + + x // typeof x is Y +>x : B + + break; + } +} + +function f34(x: X | Y) { +>f34 : (x: X | Y) => void +>x : X | Y + + if (x.type1.type2 === "a") { +>x.type1.type2 === "a" : boolean +>x.type1.type2 : "a" | "b" +>x.type1 : A | B +>x : X | Y +>type1 : A | B +>type2 : "a" | "b" +>"a" : "a" + + x.x // typeof x is X +>x.x : string +>x : X +>x : string + + } else if (x.type1.type2 === "b") { +>x.type1.type2 === "b" : boolean +>x.type1.type2 : "b" +>x.type1 : B +>x : Y +>type1 : B +>type2 : "b" +>"b" : "b" + + x.y // typeof x is Y +>x.y : string +>x : Y +>y : string + } +} + +function f35(x: X | W) { +>f35 : (x: X | W) => void +>x : X | W + + if (x.type1?.type2 === "a") { +>x.type1?.type2 === "a" : boolean +>x.type1?.type2 : "a" | undefined +>x.type1 : A | undefined +>x : X | W +>type1 : A | undefined +>type2 : "a" | undefined +>"a" : "a" + + x.x +>x.x : string +>x : X +>x : string + } +} + +function f36(x: X | W) { +>f36 : (x: X | W) => void +>x : X | W + + x.type1?.type2 ?? x; +>x.type1?.type2 ?? x : "a" | W +>x.type1?.type2 : "a" | undefined +>x.type1 : A | undefined +>x : X | W +>type1 : A | undefined +>type2 : "a" | undefined +>x : W +} + +type S = { sub: { type0: X }, s: string } +>S : S +>sub : { type0: X; } +>type0 : X +>s : string + +type T = { sub: { type0: Y }, t: string } +>T : T +>sub : { type0: Y; } +>type0 : Y +>t : string + +function f37(s: S | T) { +>f37 : (s: S | T) => void +>s : S | T + + if (s.sub.type0.type1.type2 === "a") { +>s.sub.type0.type1.type2 === "a" : boolean +>s.sub.type0.type1.type2 : "a" | "b" +>s.sub.type0.type1 : A | B +>s.sub.type0 : X | Y +>s.sub : { type0: X; } | { type0: Y; } +>s : S | T +>sub : { type0: X; } | { type0: Y; } +>type0 : X | Y +>type1 : A | B +>type2 : "a" | "b" +>"a" : "a" + + s.s // typeof s is S +>s.s : string +>s : S +>s : string + + s.sub.type0.x // type of s.sub.type is X +>s.sub.type0.x : string +>s.sub.type0 : X +>s.sub : { type0: X; } +>s : S +>sub : { type0: X; } +>type0 : X +>x : string + + s.sub.type0.type1.a // type of s.sub.type.type is A +>s.sub.type0.type1.a : number +>s.sub.type0.type1 : A +>s.sub.type0 : X +>s.sub : { type0: X; } +>s : S +>sub : { type0: X; } +>type0 : X +>type1 : A +>a : number + + } else { + s.s // type error! +>s.s : any +>s : T +>s : any + } +} + // Repro from #44435 type Correct = { @@ -36,7 +258,8 @@ if (example.err === undefined) { >undefined : undefined example.property; // true ->example.property : true ->example : Correct ->property : true +>example.property : any +>example : SomeReturnType +>property : any } + diff --git a/tests/baselines/reference/nonNullReferenceMatching.js b/tests/baselines/reference/nonNullReferenceMatching.js index abb0d5a96db30..713fc4e56e51b 100644 --- a/tests/baselines/reference/nonNullReferenceMatching.js +++ b/tests/baselines/reference/nonNullReferenceMatching.js @@ -10,6 +10,14 @@ type ComponentProps = { thumbXProps: ThumbProps; } +type ThumbProps2 = { + elementRef: ElementRef | null; +} + +type ComponentProps2 = { + thumbYProps: ThumbProps2 | null; +} + class Component { props!: ComponentProps; public thumbYElementRef = (ref: HTMLElement | null) => { @@ -31,6 +39,17 @@ class Component { typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); }; +} + +class Component2 { + props!: ComponentProps2; + public thumbYElementRef = (ref: HTMLElement | null) => { + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); + } } //// [nonNullReferenceMatching.js] @@ -52,3 +71,14 @@ var Component = /** @class */ (function () { } return Component; }()); +var Component2 = /** @class */ (function () { + function Component2() { + var _this = this; + this.thumbYElementRef = function (ref) { + typeof _this.props.thumbYProps.elementRef === 'function' && _this.props.thumbYProps.elementRef(ref); + typeof (_this.props.thumbYProps.elementRef) === 'function' && _this.props.thumbYProps.elementRef(ref); + typeof ((_this.props).thumbYProps.elementRef) === 'function' && _this.props.thumbYProps.elementRef(ref); + }; + } + return Component2; +}()); diff --git a/tests/baselines/reference/nonNullReferenceMatching.symbols b/tests/baselines/reference/nonNullReferenceMatching.symbols index ee9c608cea498..fe43bab39632f 100644 --- a/tests/baselines/reference/nonNullReferenceMatching.symbols +++ b/tests/baselines/reference/nonNullReferenceMatching.symbols @@ -24,170 +24,251 @@ type ComponentProps = { >ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56)) } +type ThumbProps2 = { +>ThumbProps2 : Symbol(ThumbProps2, Decl(nonNullReferenceMatching.ts, 9, 1)) + + elementRef: ElementRef | null; +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>ElementRef : Symbol(ElementRef, Decl(nonNullReferenceMatching.ts, 0, 0)) +} + +type ComponentProps2 = { +>ComponentProps2 : Symbol(ComponentProps2, Decl(nonNullReferenceMatching.ts, 13, 1)) + + thumbYProps: ThumbProps2 | null; +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>ThumbProps2 : Symbol(ThumbProps2, Decl(nonNullReferenceMatching.ts, 9, 1)) +} + class Component { ->Component : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>Component : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) props!: ComponentProps; ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >ComponentProps : Symbol(ComponentProps, Decl(nonNullReferenceMatching.ts, 4, 1)) public thumbYElementRef = (ref: HTMLElement | null) => { ->thumbYElementRef : Symbol(Component.thumbYElementRef, Decl(nonNullReferenceMatching.ts, 12, 27)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>thumbYElementRef : Symbol(Component.thumbYElementRef, Decl(nonNullReferenceMatching.ts, 20, 27)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) >HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); >this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); >this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); >(this.props).thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props).thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); >this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); >this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props).thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props).thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); >this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props.thumbXProps).elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); >this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); >(this.props.thumbXProps).elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); >this.props!.thumbXProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >this.props!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) >(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) ->this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) ->this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) ->props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 17, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 19, 17)) >thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) >elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) ->ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 21, 31)) }; } + +class Component2 { +>Component2 : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) + + props!: ComponentProps2; +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>ComponentProps2 : Symbol(ComponentProps2, Decl(nonNullReferenceMatching.ts, 13, 1)) + + public thumbYElementRef = (ref: HTMLElement | null) => { +>thumbYElementRef : Symbol(Component2.thumbYElementRef, Decl(nonNullReferenceMatching.ts, 43, 28)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 44, 31)) +>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>this.props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>this : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>this.props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>this : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 44, 31)) + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>this.props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>this : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>this.props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>this : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 44, 31)) + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); +>(this.props).thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>(this.props).thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>this.props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>this : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>this.props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>this : Symbol(Component2, Decl(nonNullReferenceMatching.ts, 40, 1)) +>props : Symbol(Component2.props, Decl(nonNullReferenceMatching.ts, 42, 18)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 15, 24)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 11, 20)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 44, 31)) + } +} diff --git a/tests/baselines/reference/nonNullReferenceMatching.types b/tests/baselines/reference/nonNullReferenceMatching.types index 03ef70177c07f..8a4335bc0fc63 100644 --- a/tests/baselines/reference/nonNullReferenceMatching.types +++ b/tests/baselines/reference/nonNullReferenceMatching.types @@ -21,6 +21,22 @@ type ComponentProps = { >thumbXProps : ThumbProps } +type ThumbProps2 = { +>ThumbProps2 : ThumbProps2 + + elementRef: ElementRef | null; +>elementRef : ElementRef | null +>null : null +} + +type ComponentProps2 = { +>ComponentProps2 : ComponentProps2 + + thumbYProps: ThumbProps2 | null; +>thumbYProps : ThumbProps2 | null +>null : null +} + class Component { >Component : Component @@ -49,11 +65,11 @@ class Component { >this.props.thumbYProps!.elementRef(ref) : void >this.props.thumbYProps!.elementRef : ElementRef >this.props.thumbYProps! : ThumbProps ->this.props.thumbYProps : ThumbProps | undefined +>this.props.thumbYProps : ThumbProps >this.props : ComponentProps >this : this >props : ComponentProps ->thumbYProps : ThumbProps | undefined +>thumbYProps : ThumbProps >elementRef : ElementRef >ref : HTMLElement | null @@ -64,21 +80,21 @@ class Component { >(this.props.thumbYProps!.elementRef) : ElementRef | undefined >this.props.thumbYProps!.elementRef : ElementRef | undefined >this.props.thumbYProps! : ThumbProps ->this.props.thumbYProps : ThumbProps | undefined +>this.props.thumbYProps : ThumbProps >this.props : ComponentProps >this : this >props : ComponentProps ->thumbYProps : ThumbProps | undefined +>thumbYProps : ThumbProps >elementRef : ElementRef | undefined >'function' : "function" >this.props.thumbYProps!.elementRef(ref) : void >this.props.thumbYProps!.elementRef : ElementRef >this.props.thumbYProps! : ThumbProps ->this.props.thumbYProps : ThumbProps | undefined +>this.props.thumbYProps : ThumbProps >this.props : ComponentProps >this : this >props : ComponentProps ->thumbYProps : ThumbProps | undefined +>thumbYProps : ThumbProps >elementRef : ElementRef >ref : HTMLElement | null @@ -90,22 +106,22 @@ class Component { >((this.props).thumbYProps!.elementRef) : ElementRef | undefined >(this.props).thumbYProps!.elementRef : ElementRef | undefined >(this.props).thumbYProps! : ThumbProps ->(this.props).thumbYProps : ThumbProps | undefined +>(this.props).thumbYProps : ThumbProps >(this.props) : ComponentProps >this.props : ComponentProps >this : this >props : ComponentProps ->thumbYProps : ThumbProps | undefined +>thumbYProps : ThumbProps >elementRef : ElementRef | undefined >'function' : "function" >this.props.thumbYProps!.elementRef(ref) : void >this.props.thumbYProps!.elementRef : ElementRef >this.props.thumbYProps! : ThumbProps ->this.props.thumbYProps : ThumbProps | undefined +>this.props.thumbYProps : ThumbProps >this.props : ComponentProps >this : this >props : ComponentProps ->thumbYProps : ThumbProps | undefined +>thumbYProps : ThumbProps >elementRef : ElementRef >ref : HTMLElement | null @@ -260,3 +276,93 @@ class Component { }; } + +class Component2 { +>Component2 : Component2 + + props!: ComponentProps2; +>props : ComponentProps2 + + public thumbYElementRef = (ref: HTMLElement | null) => { +>thumbYElementRef : (ref: HTMLElement | null) => void +>(ref: HTMLElement | null) => { typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); } : (ref: HTMLElement | null) => void +>ref : HTMLElement | null +>null : null + + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof this.props.thumbYProps!.elementRef === 'function' : boolean +>typeof this.props.thumbYProps!.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbYProps!.elementRef : ElementRef | null +>this.props.thumbYProps! : ThumbProps2 +>this.props.thumbYProps : ThumbProps2 | null +>this.props : ComponentProps2 +>this : this +>props : ComponentProps2 +>thumbYProps : ThumbProps2 | null +>elementRef : ElementRef | null +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps2 +>this.props.thumbYProps : ThumbProps2 +>this.props : ComponentProps2 +>this : this +>props : ComponentProps2 +>thumbYProps : ThumbProps2 +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof (this.props.thumbYProps!.elementRef) === 'function' : boolean +>typeof (this.props.thumbYProps!.elementRef) : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>(this.props.thumbYProps!.elementRef) : ElementRef | null +>this.props.thumbYProps!.elementRef : ElementRef | null +>this.props.thumbYProps! : ThumbProps2 +>this.props.thumbYProps : ThumbProps2 +>this.props : ComponentProps2 +>this : this +>props : ComponentProps2 +>thumbYProps : ThumbProps2 +>elementRef : ElementRef | null +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps2 +>this.props.thumbYProps : ThumbProps2 +>this.props : ComponentProps2 +>this : this +>props : ComponentProps2 +>thumbYProps : ThumbProps2 +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof ((this.props).thumbYProps!.elementRef)! === 'function' : boolean +>typeof ((this.props).thumbYProps!.elementRef)! : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>((this.props).thumbYProps!.elementRef)! : ElementRef +>((this.props).thumbYProps!.elementRef) : ElementRef | null +>(this.props).thumbYProps!.elementRef : ElementRef | null +>(this.props).thumbYProps! : ThumbProps2 +>(this.props).thumbYProps : ThumbProps2 +>(this.props) : ComponentProps2 +>this.props : ComponentProps2 +>this : this +>props : ComponentProps2 +>thumbYProps : ThumbProps2 +>elementRef : ElementRef | null +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps2 +>this.props.thumbYProps : ThumbProps2 +>this.props : ComponentProps2 +>this : this +>props : ComponentProps2 +>thumbYProps : ThumbProps2 +>elementRef : ElementRef +>ref : HTMLElement | null + } +} diff --git a/tests/baselines/reference/templateLiteralTypes3.errors.txt b/tests/baselines/reference/templateLiteralTypes3.errors.txt index d9e2608ac88b6..eb1b4a8c3bc0f 100644 --- a/tests/baselines/reference/templateLiteralTypes3.errors.txt +++ b/tests/baselines/reference/templateLiteralTypes3.errors.txt @@ -7,9 +7,11 @@ tests/cases/conformance/types/literal/templateLiteralTypes3.ts(74,5): error TS23 Type '"*false*"' is not assignable to type '`*${number}*`'. tests/cases/conformance/types/literal/templateLiteralTypes3.ts(133,9): error TS2367: This condition will always return 'false' since the types '`foo-${string}`' and '`baz-${string}`' have no overlap. tests/cases/conformance/types/literal/templateLiteralTypes3.ts(141,9): error TS2367: This condition will always return 'false' since the types '`foo-${T}`' and '`baz-${T}`' have no overlap. +tests/cases/conformance/types/literal/templateLiteralTypes3.ts(169,16): error TS2339: Property 'response' does not exist on type 'Action'. + Property 'response' does not exist on type '{ type: `${string}_REQUEST`; }'. -==== tests/cases/conformance/types/literal/templateLiteralTypes3.ts (8 errors) ==== +==== tests/cases/conformance/types/literal/templateLiteralTypes3.ts (9 errors) ==== // Inference from template literal type to template literal type type Foo1 = T extends `*${infer U}*` ? U : never; @@ -196,6 +198,9 @@ tests/cases/conformance/types/literal/templateLiteralTypes3.ts(141,9): error TS2 if (action.type === 'FOO_SUCCESS') { action.type; action.response; + ~~~~~~~~ +!!! error TS2339: Property 'response' does not exist on type 'Action'. +!!! error TS2339: Property 'response' does not exist on type '{ type: `${string}_REQUEST`; }'. } } diff --git a/tests/baselines/reference/templateLiteralTypes3.symbols b/tests/baselines/reference/templateLiteralTypes3.symbols index 47f4ee7fe6e53..7443bee0540eb 100644 --- a/tests/baselines/reference/templateLiteralTypes3.symbols +++ b/tests/baselines/reference/templateLiteralTypes3.symbols @@ -505,14 +505,12 @@ function reducer(action: Action) { >type : Symbol(type, Decl(templateLiteralTypes3.ts, 162, 7), Decl(templateLiteralTypes3.ts, 163, 7)) action.type; ->action.type : Symbol(type, Decl(templateLiteralTypes3.ts, 163, 7)) +>action.type : Symbol(type, Decl(templateLiteralTypes3.ts, 162, 7), Decl(templateLiteralTypes3.ts, 163, 7)) >action : Symbol(action, Decl(templateLiteralTypes3.ts, 165, 17)) ->type : Symbol(type, Decl(templateLiteralTypes3.ts, 163, 7)) +>type : Symbol(type, Decl(templateLiteralTypes3.ts, 162, 7), Decl(templateLiteralTypes3.ts, 163, 7)) action.response; ->action.response : Symbol(response, Decl(templateLiteralTypes3.ts, 163, 34)) >action : Symbol(action, Decl(templateLiteralTypes3.ts, 165, 17)) ->response : Symbol(response, Decl(templateLiteralTypes3.ts, 163, 34)) } } diff --git a/tests/baselines/reference/templateLiteralTypes3.types b/tests/baselines/reference/templateLiteralTypes3.types index 27d780c7e22ac..c1c6b91f83bdd 100644 --- a/tests/baselines/reference/templateLiteralTypes3.types +++ b/tests/baselines/reference/templateLiteralTypes3.types @@ -503,13 +503,13 @@ function reducer(action: Action) { action.type; >action.type : "FOO_SUCCESS" ->action : { type: `${string}_SUCCESS`; response: string; } +>action : Action >type : "FOO_SUCCESS" action.response; ->action.response : string ->action : { type: `${string}_SUCCESS`; response: string; } ->response : string +>action.response : any +>action : Action +>response : any } } diff --git a/tests/baselines/reference/typeGuardAccordingToProperty.errors.txt b/tests/baselines/reference/typeGuardAccordingToProperty.errors.txt new file mode 100644 index 0000000000000..acff40b61bc67 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty.errors.txt @@ -0,0 +1,281 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts(66,11): error TS2339: Property 'b1' does not exist on type 'Boolean1 | Boolean2'. + Property 'b1' does not exist on type 'Boolean2'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts(67,11): error TS2339: Property 'b2' does not exist on type 'Boolean1 | Boolean2'. + Property 'b2' does not exist on type 'Boolean1'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts(80,11): error TS2339: Property 'b1' does not exist on type 'Boolean1 | Boolean2'. + Property 'b1' does not exist on type 'Boolean2'. +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts(81,11): error TS2339: Property 'b2' does not exist on type 'Boolean1 | Boolean2'. + Property 'b2' does not exist on type 'Boolean1'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts (4 errors) ==== + // Primitive value ---- boolean bigint number string symbol undefined function object + // ts special type ---- any, void, unknown, union, intersection + + //// Property Access ---- a.b + //// Element Access ---- a["b"] + + interface Boolean1 { + key: boolean; + b1: number; + }; + + interface Boolean2 { + key: boolean; + b2: number; + }; + + interface BigInt1 { + key: bigint; + bi1: number; + }; + + interface Number1 { + key: number; + n1: number; + }; + + interface String1 { + key: string; + st1: number; + } + + interface Symbol1 { + key: symbol; + sy1: number; + } + + interface Undefined1 { + key: undefined; + u1: number; + } + + interface Function1 { + key: () => void; + f1: number; + } + + interface Obejct1 { + key: { + notEmpty: number; + }; + o1: number; + } + + type Union1 = Boolean1 | Boolean2 | Number1; + type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; + + function f1_1(u: Union1) { + if (typeof u.key !== 'boolean') { + u; // Number1 + u.n1; // number + } + } + function f1_2(u: Union1) { + if (typeof u.key === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + ~~ +!!! error TS2339: Property 'b1' does not exist on type 'Boolean1 | Boolean2'. +!!! error TS2339: Property 'b1' does not exist on type 'Boolean2'. + u.b2; // Error + ~~ +!!! error TS2339: Property 'b2' does not exist on type 'Boolean1 | Boolean2'. +!!! error TS2339: Property 'b2' does not exist on type 'Boolean1'. + } + } + + function f1ElementAccess_1(u: Union1) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } + } + function f1ElementAccess_2(u: Union1) { + if (typeof u["key"] === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + ~~ +!!! error TS2339: Property 'b1' does not exist on type 'Boolean1 | Boolean2'. +!!! error TS2339: Property 'b1' does not exist on type 'Boolean2'. + u.b2; // Error + ~~ +!!! error TS2339: Property 'b2' does not exist on type 'Boolean1 | Boolean2'. +!!! error TS2339: Property 'b2' does not exist on type 'Boolean1'. + } + } + + function f1_Plus(u: Union1) { + if (typeof u.key !== 'boolean') { + throw new Error(); + } + u; // Bolean1 | Bolean2 + if (typeof u.key === 'boolean') { + throw new Error(); + } + u; // never + } + + // boolean bigint number string symbol undefined function object + function f2_1(u: Union2) { + if (typeof u.key === 'bigint') { + u; // BigInt1 + u.bi1; + } + if (typeof u.key == 'bigint') { + u; // BigInt1 + u.bi1; + } + } + function f2_2(u: Union2) { + if (typeof u.key === 'boolean') { + u; // Boolean1 + u.b1; + } + if (typeof u.key == 'boolean') { + u; // Boolean1 + u.b1; + } + } + function f2_3(u: Union2) { + if (typeof u.key === 'number') { + u; // Number1 + u.n1; + } + if (typeof u.key == 'number') { + u; // Number1 + u.n1; + } + } + function f2_4(u: Union2) { + if (typeof u.key === 'string') { + u; // String1 + u.st1; + } + if (typeof u.key == 'string') { + u; // String1 + u.st1; + } + } + function f2_5(u: Union2) { + if (typeof u.key === 'symbol') { + u; // Symbol1 + u.sy1; + } + if (typeof u.key == 'symbol') { + u; // Symbol1 + u.sy1; + } + } + function f2_6(u: Union2) { + if (typeof u.key === 'undefined') { + u; // Undefined1 + u.u1 + } + if (typeof u.key == 'undefined') { + u; // Undefined1 + u.u1 + } + } + function f2_7(u: Union2) { + if (typeof u.key === 'function') { + u; // Function1 + u.f1; + } + if (typeof u.key == 'function') { + u; // Function1 + u.f1; + } + } + function f2_8(u: Union2) { + if (typeof u.key === 'object') { + u; // Object1 + u.o1; + } + if (typeof u.key == 'object') { + u; // Object1 + u.o1; + } + } + + function f2Not_1(u: Union2) { + if (typeof u.key !== 'bigint') { + u; // not BigInt1 + } + if (typeof u.key != 'bigint') { + u; // not BigInt1 + } + } + function f2Not_2(u: Union2) { + if (typeof u.key !== 'boolean') { + u; // not Boolean1 + } + if (typeof u.key != 'boolean') { + u; // not Boolean1 + } + } + + function f2Not_3(u: Union2) { + if (typeof u.key !== 'number') { + u; // not Number1 + } + if (typeof u.key != 'number') { + u; // not Number1 + } + } + + function f2Not_4(u: Union2) { + if (typeof u.key !== 'string') { + u; // not String1 + } + if (typeof u.key != 'string') { + u; // not String1 + } + } + + function f2Not_5(u: Union2) { + if (typeof u.key !== 'symbol') { + u; // not Symbol1 + } + if (typeof u.key != 'symbol') { + u; // not Symbol1 + } + } + + function f2Not_6(u: Union2) { + if (typeof u.key !== 'undefined') { + u; // not Undefined1 + } + if (typeof u.key != 'undefined') { + u; // not Undefined1 + } + } + + function f2Not_7(u: Union2) { + if (typeof u.key !== 'function') { + u; // not Function1 + } + if (typeof u.key != 'function') { + u; // not Function1 + } + } + + function f2Not_8(u: Union2) { + if (typeof u.key !== 'object') { + u; // not Object1 + } + if (typeof u.key != 'object') { + u; // not Object1 + } + } + + interface A { x: string, y: string }; + interface B { x: number, y: number }; + type X = A | B; + + function f3(bar: X) { + if (typeof bar.x === 'string') { + let y = bar.y; // string + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardAccordingToProperty.js b/tests/baselines/reference/typeGuardAccordingToProperty.js new file mode 100644 index 0000000000000..3801c4de67008 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty.js @@ -0,0 +1,456 @@ +//// [typeGuardAccordingToProperty.ts] +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { + key: boolean; + b1: number; +}; + +interface Boolean2 { + key: boolean; + b2: number; +}; + +interface BigInt1 { + key: bigint; + bi1: number; +}; + +interface Number1 { + key: number; + n1: number; +}; + +interface String1 { + key: string; + st1: number; +} + +interface Symbol1 { + key: symbol; + sy1: number; +} + +interface Undefined1 { + key: undefined; + u1: number; +} + +interface Function1 { + key: () => void; + f1: number; +} + +interface Obejct1 { + key: { + notEmpty: number; + }; + o1: number; +} + +type Union1 = Boolean1 | Boolean2 | Number1; +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; + +function f1_1(u: Union1) { + if (typeof u.key !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +function f1_2(u: Union1) { + if (typeof u.key === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + u.b2; // Error + } +} + +function f1ElementAccess_1(u: Union1) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +function f1ElementAccess_2(u: Union1) { + if (typeof u["key"] === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + u.b2; // Error + } +} + +function f1_Plus(u: Union1) { + if (typeof u.key !== 'boolean') { + throw new Error(); + } + u; // Bolean1 | Bolean2 + if (typeof u.key === 'boolean') { + throw new Error(); + } + u; // never +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { + if (typeof u.key === 'bigint') { + u; // BigInt1 + u.bi1; + } + if (typeof u.key == 'bigint') { + u; // BigInt1 + u.bi1; + } +} +function f2_2(u: Union2) { + if (typeof u.key === 'boolean') { + u; // Boolean1 + u.b1; + } + if (typeof u.key == 'boolean') { + u; // Boolean1 + u.b1; + } +} +function f2_3(u: Union2) { + if (typeof u.key === 'number') { + u; // Number1 + u.n1; + } + if (typeof u.key == 'number') { + u; // Number1 + u.n1; + } +} +function f2_4(u: Union2) { + if (typeof u.key === 'string') { + u; // String1 + u.st1; + } + if (typeof u.key == 'string') { + u; // String1 + u.st1; + } +} +function f2_5(u: Union2) { + if (typeof u.key === 'symbol') { + u; // Symbol1 + u.sy1; + } + if (typeof u.key == 'symbol') { + u; // Symbol1 + u.sy1; + } +} +function f2_6(u: Union2) { + if (typeof u.key === 'undefined') { + u; // Undefined1 + u.u1 + } + if (typeof u.key == 'undefined') { + u; // Undefined1 + u.u1 + } +} +function f2_7(u: Union2) { + if (typeof u.key === 'function') { + u; // Function1 + u.f1; + } + if (typeof u.key == 'function') { + u; // Function1 + u.f1; + } +} +function f2_8(u: Union2) { + if (typeof u.key === 'object') { + u; // Object1 + u.o1; + } + if (typeof u.key == 'object') { + u; // Object1 + u.o1; + } +} + +function f2Not_1(u: Union2) { + if (typeof u.key !== 'bigint') { + u; // not BigInt1 + } + if (typeof u.key != 'bigint') { + u; // not BigInt1 + } +} +function f2Not_2(u: Union2) { + if (typeof u.key !== 'boolean') { + u; // not Boolean1 + } + if (typeof u.key != 'boolean') { + u; // not Boolean1 + } +} + +function f2Not_3(u: Union2) { + if (typeof u.key !== 'number') { + u; // not Number1 + } + if (typeof u.key != 'number') { + u; // not Number1 + } +} + +function f2Not_4(u: Union2) { + if (typeof u.key !== 'string') { + u; // not String1 + } + if (typeof u.key != 'string') { + u; // not String1 + } +} + +function f2Not_5(u: Union2) { + if (typeof u.key !== 'symbol') { + u; // not Symbol1 + } + if (typeof u.key != 'symbol') { + u; // not Symbol1 + } +} + +function f2Not_6(u: Union2) { + if (typeof u.key !== 'undefined') { + u; // not Undefined1 + } + if (typeof u.key != 'undefined') { + u; // not Undefined1 + } +} + +function f2Not_7(u: Union2) { + if (typeof u.key !== 'function') { + u; // not Function1 + } + if (typeof u.key != 'function') { + u; // not Function1 + } +} + +function f2Not_8(u: Union2) { + if (typeof u.key !== 'object') { + u; // not Object1 + } + if (typeof u.key != 'object') { + u; // not Object1 + } +} + +interface A { x: string, y: string }; +interface B { x: number, y: number }; +type X = A | B; + +function f3(bar: X) { + if (typeof bar.x === 'string') { + let y = bar.y; // string + } +} + + +//// [typeGuardAccordingToProperty.js] +"use strict"; +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection +; +; +; +; +function f1_1(u) { + if (typeof u.key !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +function f1_2(u) { + if (typeof u.key === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + u.b2; // Error + } +} +function f1ElementAccess_1(u) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +function f1ElementAccess_2(u) { + if (typeof u["key"] === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + u.b2; // Error + } +} +function f1_Plus(u) { + if (typeof u.key !== 'boolean') { + throw new Error(); + } + u; // Bolean1 | Bolean2 + if (typeof u.key === 'boolean') { + throw new Error(); + } + u; // never +} +// boolean bigint number string symbol undefined function object +function f2_1(u) { + if (typeof u.key === 'bigint') { + u; // BigInt1 + u.bi1; + } + if (typeof u.key == 'bigint') { + u; // BigInt1 + u.bi1; + } +} +function f2_2(u) { + if (typeof u.key === 'boolean') { + u; // Boolean1 + u.b1; + } + if (typeof u.key == 'boolean') { + u; // Boolean1 + u.b1; + } +} +function f2_3(u) { + if (typeof u.key === 'number') { + u; // Number1 + u.n1; + } + if (typeof u.key == 'number') { + u; // Number1 + u.n1; + } +} +function f2_4(u) { + if (typeof u.key === 'string') { + u; // String1 + u.st1; + } + if (typeof u.key == 'string') { + u; // String1 + u.st1; + } +} +function f2_5(u) { + if (typeof u.key === 'symbol') { + u; // Symbol1 + u.sy1; + } + if (typeof u.key == 'symbol') { + u; // Symbol1 + u.sy1; + } +} +function f2_6(u) { + if (typeof u.key === 'undefined') { + u; // Undefined1 + u.u1; + } + if (typeof u.key == 'undefined') { + u; // Undefined1 + u.u1; + } +} +function f2_7(u) { + if (typeof u.key === 'function') { + u; // Function1 + u.f1; + } + if (typeof u.key == 'function') { + u; // Function1 + u.f1; + } +} +function f2_8(u) { + if (typeof u.key === 'object') { + u; // Object1 + u.o1; + } + if (typeof u.key == 'object') { + u; // Object1 + u.o1; + } +} +function f2Not_1(u) { + if (typeof u.key !== 'bigint') { + u; // not BigInt1 + } + if (typeof u.key != 'bigint') { + u; // not BigInt1 + } +} +function f2Not_2(u) { + if (typeof u.key !== 'boolean') { + u; // not Boolean1 + } + if (typeof u.key != 'boolean') { + u; // not Boolean1 + } +} +function f2Not_3(u) { + if (typeof u.key !== 'number') { + u; // not Number1 + } + if (typeof u.key != 'number') { + u; // not Number1 + } +} +function f2Not_4(u) { + if (typeof u.key !== 'string') { + u; // not String1 + } + if (typeof u.key != 'string') { + u; // not String1 + } +} +function f2Not_5(u) { + if (typeof u.key !== 'symbol') { + u; // not Symbol1 + } + if (typeof u.key != 'symbol') { + u; // not Symbol1 + } +} +function f2Not_6(u) { + if (typeof u.key !== 'undefined') { + u; // not Undefined1 + } + if (typeof u.key != 'undefined') { + u; // not Undefined1 + } +} +function f2Not_7(u) { + if (typeof u.key !== 'function') { + u; // not Function1 + } + if (typeof u.key != 'function') { + u; // not Function1 + } +} +function f2Not_8(u) { + if (typeof u.key !== 'object') { + u; // not Object1 + } + if (typeof u.key != 'object') { + u; // not Object1 + } +} +; +; +function f3(bar) { + if (typeof bar.x === 'string') { + var y = bar.y; // string + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToProperty.symbols b/tests/baselines/reference/typeGuardAccordingToProperty.symbols new file mode 100644 index 0000000000000..36263507e4635 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty.symbols @@ -0,0 +1,702 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts === +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { +>Boolean1 : Symbol(Boolean1, Decl(typeGuardAccordingToProperty.ts, 0, 0)) + + key: boolean; +>key : Symbol(Boolean1.key, Decl(typeGuardAccordingToProperty.ts, 6, 20)) + + b1: number; +>b1 : Symbol(Boolean1.b1, Decl(typeGuardAccordingToProperty.ts, 7, 17)) + +}; + +interface Boolean2 { +>Boolean2 : Symbol(Boolean2, Decl(typeGuardAccordingToProperty.ts, 9, 2)) + + key: boolean; +>key : Symbol(Boolean2.key, Decl(typeGuardAccordingToProperty.ts, 11, 20)) + + b2: number; +>b2 : Symbol(Boolean2.b2, Decl(typeGuardAccordingToProperty.ts, 12, 17)) + +}; + +interface BigInt1 { +>BigInt1 : Symbol(BigInt1, Decl(typeGuardAccordingToProperty.ts, 14, 2)) + + key: bigint; +>key : Symbol(BigInt1.key, Decl(typeGuardAccordingToProperty.ts, 16, 19)) + + bi1: number; +>bi1 : Symbol(BigInt1.bi1, Decl(typeGuardAccordingToProperty.ts, 17, 16)) + +}; + +interface Number1 { +>Number1 : Symbol(Number1, Decl(typeGuardAccordingToProperty.ts, 19, 2)) + + key: number; +>key : Symbol(Number1.key, Decl(typeGuardAccordingToProperty.ts, 21, 19)) + + n1: number; +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) + +}; + +interface String1 { +>String1 : Symbol(String1, Decl(typeGuardAccordingToProperty.ts, 24, 2)) + + key: string; +>key : Symbol(String1.key, Decl(typeGuardAccordingToProperty.ts, 26, 19)) + + st1: number; +>st1 : Symbol(String1.st1, Decl(typeGuardAccordingToProperty.ts, 27, 16)) +} + +interface Symbol1 { +>Symbol1 : Symbol(Symbol1, Decl(typeGuardAccordingToProperty.ts, 29, 1)) + + key: symbol; +>key : Symbol(Symbol1.key, Decl(typeGuardAccordingToProperty.ts, 31, 19)) + + sy1: number; +>sy1 : Symbol(Symbol1.sy1, Decl(typeGuardAccordingToProperty.ts, 32, 16)) +} + +interface Undefined1 { +>Undefined1 : Symbol(Undefined1, Decl(typeGuardAccordingToProperty.ts, 34, 1)) + + key: undefined; +>key : Symbol(Undefined1.key, Decl(typeGuardAccordingToProperty.ts, 36, 22)) + + u1: number; +>u1 : Symbol(Undefined1.u1, Decl(typeGuardAccordingToProperty.ts, 37, 19)) +} + +interface Function1 { +>Function1 : Symbol(Function1, Decl(typeGuardAccordingToProperty.ts, 39, 1)) + + key: () => void; +>key : Symbol(Function1.key, Decl(typeGuardAccordingToProperty.ts, 41, 21)) + + f1: number; +>f1 : Symbol(Function1.f1, Decl(typeGuardAccordingToProperty.ts, 42, 20)) +} + +interface Obejct1 { +>Obejct1 : Symbol(Obejct1, Decl(typeGuardAccordingToProperty.ts, 44, 1)) + + key: { +>key : Symbol(Obejct1.key, Decl(typeGuardAccordingToProperty.ts, 46, 19)) + + notEmpty: number; +>notEmpty : Symbol(notEmpty, Decl(typeGuardAccordingToProperty.ts, 47, 10)) + + }; + o1: number; +>o1 : Symbol(Obejct1.o1, Decl(typeGuardAccordingToProperty.ts, 49, 6)) +} + +type Union1 = Boolean1 | Boolean2 | Number1; +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToProperty.ts, 51, 1)) +>Boolean1 : Symbol(Boolean1, Decl(typeGuardAccordingToProperty.ts, 0, 0)) +>Boolean2 : Symbol(Boolean2, Decl(typeGuardAccordingToProperty.ts, 9, 2)) +>Number1 : Symbol(Number1, Decl(typeGuardAccordingToProperty.ts, 19, 2)) + +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) +>Boolean1 : Symbol(Boolean1, Decl(typeGuardAccordingToProperty.ts, 0, 0)) +>BigInt1 : Symbol(BigInt1, Decl(typeGuardAccordingToProperty.ts, 14, 2)) +>Number1 : Symbol(Number1, Decl(typeGuardAccordingToProperty.ts, 19, 2)) +>String1 : Symbol(String1, Decl(typeGuardAccordingToProperty.ts, 24, 2)) +>Symbol1 : Symbol(Symbol1, Decl(typeGuardAccordingToProperty.ts, 29, 1)) +>Undefined1 : Symbol(Undefined1, Decl(typeGuardAccordingToProperty.ts, 34, 1)) +>Function1 : Symbol(Function1, Decl(typeGuardAccordingToProperty.ts, 39, 1)) +>Obejct1 : Symbol(Obejct1, Decl(typeGuardAccordingToProperty.ts, 44, 1)) + +function f1_1(u: Union1) { +>f1_1 : Symbol(f1_1, Decl(typeGuardAccordingToProperty.ts, 54, 98)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 56, 14)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToProperty.ts, 51, 1)) + + if (typeof u.key !== 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 56, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) + + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 56, 14)) + + u.n1; // number +>u.n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 56, 14)) +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) + } +} +function f1_2(u: Union1) { +>f1_2 : Symbol(f1_2, Decl(typeGuardAccordingToProperty.ts, 61, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 62, 14)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToProperty.ts, 51, 1)) + + if (typeof u.key === 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 62, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) + + u; // Bolean1 | Bolean2 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 62, 14)) + + u.b1; // Error +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 62, 14)) + + u.b2; // Error +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 62, 14)) + } +} + +function f1ElementAccess_1(u: Union1) { +>f1ElementAccess_1 : Symbol(f1ElementAccess_1, Decl(typeGuardAccordingToProperty.ts, 68, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 70, 27)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToProperty.ts, 51, 1)) + + if (typeof u["key"] !== 'boolean') { +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 70, 27)) +>"key" : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) + + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 70, 27)) + + u.n1; // number +>u.n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 70, 27)) +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) + } +} +function f1ElementAccess_2(u: Union1) { +>f1ElementAccess_2 : Symbol(f1ElementAccess_2, Decl(typeGuardAccordingToProperty.ts, 75, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 76, 27)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToProperty.ts, 51, 1)) + + if (typeof u["key"] === 'boolean') { +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 76, 27)) +>"key" : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) + + u; // Bolean1 | Bolean2 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 76, 27)) + + u.b1; // Error +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 76, 27)) + + u.b2; // Error +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 76, 27)) + } +} + +function f1_Plus(u: Union1) { +>f1_Plus : Symbol(f1_Plus, Decl(typeGuardAccordingToProperty.ts, 82, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 84, 17)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToProperty.ts, 51, 1)) + + if (typeof u.key !== 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 84, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20), Decl(typeGuardAccordingToProperty.ts, 21, 19)) + + throw new Error(); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + } + u; // Bolean1 | Bolean2 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 84, 17)) + + if (typeof u.key === 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 84, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 11, 20)) + + throw new Error(); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + } + u; // never +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 84, 17)) +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { +>f2_1 : Symbol(f2_1, Decl(typeGuardAccordingToProperty.ts, 93, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'bigint') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // BigInt1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) + + u.bi1; +>u.bi1 : Symbol(BigInt1.bi1, Decl(typeGuardAccordingToProperty.ts, 17, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) +>bi1 : Symbol(BigInt1.bi1, Decl(typeGuardAccordingToProperty.ts, 17, 16)) + } + if (typeof u.key == 'bigint') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // BigInt1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) + + u.bi1; +>u.bi1 : Symbol(BigInt1.bi1, Decl(typeGuardAccordingToProperty.ts, 17, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 96, 14)) +>bi1 : Symbol(BigInt1.bi1, Decl(typeGuardAccordingToProperty.ts, 17, 16)) + } +} +function f2_2(u: Union2) { +>f2_2 : Symbol(f2_2, Decl(typeGuardAccordingToProperty.ts, 105, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Boolean1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) + + u.b1; +>u.b1 : Symbol(Boolean1.b1, Decl(typeGuardAccordingToProperty.ts, 7, 17)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) +>b1 : Symbol(Boolean1.b1, Decl(typeGuardAccordingToProperty.ts, 7, 17)) + } + if (typeof u.key == 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Boolean1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) + + u.b1; +>u.b1 : Symbol(Boolean1.b1, Decl(typeGuardAccordingToProperty.ts, 7, 17)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 106, 14)) +>b1 : Symbol(Boolean1.b1, Decl(typeGuardAccordingToProperty.ts, 7, 17)) + } +} +function f2_3(u: Union2) { +>f2_3 : Symbol(f2_3, Decl(typeGuardAccordingToProperty.ts, 115, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'number') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) + + u.n1; +>u.n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) + } + if (typeof u.key == 'number') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) + + u.n1; +>u.n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 116, 14)) +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToProperty.ts, 22, 16)) + } +} +function f2_4(u: Union2) { +>f2_4 : Symbol(f2_4, Decl(typeGuardAccordingToProperty.ts, 125, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'string') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // String1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) + + u.st1; +>u.st1 : Symbol(String1.st1, Decl(typeGuardAccordingToProperty.ts, 27, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) +>st1 : Symbol(String1.st1, Decl(typeGuardAccordingToProperty.ts, 27, 16)) + } + if (typeof u.key == 'string') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // String1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) + + u.st1; +>u.st1 : Symbol(String1.st1, Decl(typeGuardAccordingToProperty.ts, 27, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 126, 14)) +>st1 : Symbol(String1.st1, Decl(typeGuardAccordingToProperty.ts, 27, 16)) + } +} +function f2_5(u: Union2) { +>f2_5 : Symbol(f2_5, Decl(typeGuardAccordingToProperty.ts, 135, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'symbol') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Symbol1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) + + u.sy1; +>u.sy1 : Symbol(Symbol1.sy1, Decl(typeGuardAccordingToProperty.ts, 32, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) +>sy1 : Symbol(Symbol1.sy1, Decl(typeGuardAccordingToProperty.ts, 32, 16)) + } + if (typeof u.key == 'symbol') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Symbol1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) + + u.sy1; +>u.sy1 : Symbol(Symbol1.sy1, Decl(typeGuardAccordingToProperty.ts, 32, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 136, 14)) +>sy1 : Symbol(Symbol1.sy1, Decl(typeGuardAccordingToProperty.ts, 32, 16)) + } +} +function f2_6(u: Union2) { +>f2_6 : Symbol(f2_6, Decl(typeGuardAccordingToProperty.ts, 145, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'undefined') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Undefined1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) + + u.u1 +>u.u1 : Symbol(Undefined1.u1, Decl(typeGuardAccordingToProperty.ts, 37, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) +>u1 : Symbol(Undefined1.u1, Decl(typeGuardAccordingToProperty.ts, 37, 19)) + } + if (typeof u.key == 'undefined') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Undefined1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) + + u.u1 +>u.u1 : Symbol(Undefined1.u1, Decl(typeGuardAccordingToProperty.ts, 37, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 146, 14)) +>u1 : Symbol(Undefined1.u1, Decl(typeGuardAccordingToProperty.ts, 37, 19)) + } +} +function f2_7(u: Union2) { +>f2_7 : Symbol(f2_7, Decl(typeGuardAccordingToProperty.ts, 155, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'function') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Function1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) + + u.f1; +>u.f1 : Symbol(Function1.f1, Decl(typeGuardAccordingToProperty.ts, 42, 20)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) +>f1 : Symbol(Function1.f1, Decl(typeGuardAccordingToProperty.ts, 42, 20)) + } + if (typeof u.key == 'function') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Function1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) + + u.f1; +>u.f1 : Symbol(Function1.f1, Decl(typeGuardAccordingToProperty.ts, 42, 20)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 156, 14)) +>f1 : Symbol(Function1.f1, Decl(typeGuardAccordingToProperty.ts, 42, 20)) + } +} +function f2_8(u: Union2) { +>f2_8 : Symbol(f2_8, Decl(typeGuardAccordingToProperty.ts, 165, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key === 'object') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Object1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) + + u.o1; +>u.o1 : Symbol(Obejct1.o1, Decl(typeGuardAccordingToProperty.ts, 49, 6)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) +>o1 : Symbol(Obejct1.o1, Decl(typeGuardAccordingToProperty.ts, 49, 6)) + } + if (typeof u.key == 'object') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // Object1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) + + u.o1; +>u.o1 : Symbol(Obejct1.o1, Decl(typeGuardAccordingToProperty.ts, 49, 6)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 166, 14)) +>o1 : Symbol(Obejct1.o1, Decl(typeGuardAccordingToProperty.ts, 49, 6)) + } +} + +function f2Not_1(u: Union2) { +>f2Not_1 : Symbol(f2Not_1, Decl(typeGuardAccordingToProperty.ts, 175, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 177, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'bigint') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 177, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not BigInt1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 177, 17)) + } + if (typeof u.key != 'bigint') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 177, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not BigInt1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 177, 17)) + } +} +function f2Not_2(u: Union2) { +>f2Not_2 : Symbol(f2Not_2, Decl(typeGuardAccordingToProperty.ts, 184, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 185, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 185, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Boolean1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 185, 17)) + } + if (typeof u.key != 'boolean') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 185, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Boolean1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 185, 17)) + } +} + +function f2Not_3(u: Union2) { +>f2Not_3 : Symbol(f2Not_3, Decl(typeGuardAccordingToProperty.ts, 192, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 194, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'number') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 194, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Number1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 194, 17)) + } + if (typeof u.key != 'number') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 194, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Number1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 194, 17)) + } +} + +function f2Not_4(u: Union2) { +>f2Not_4 : Symbol(f2Not_4, Decl(typeGuardAccordingToProperty.ts, 201, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 203, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'string') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 203, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not String1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 203, 17)) + } + if (typeof u.key != 'string') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 203, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not String1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 203, 17)) + } +} + +function f2Not_5(u: Union2) { +>f2Not_5 : Symbol(f2Not_5, Decl(typeGuardAccordingToProperty.ts, 210, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 212, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'symbol') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 212, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Symbol1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 212, 17)) + } + if (typeof u.key != 'symbol') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 212, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Symbol1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 212, 17)) + } +} + +function f2Not_6(u: Union2) { +>f2Not_6 : Symbol(f2Not_6, Decl(typeGuardAccordingToProperty.ts, 219, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 221, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'undefined') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 221, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Undefined1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 221, 17)) + } + if (typeof u.key != 'undefined') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 221, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Undefined1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 221, 17)) + } +} + +function f2Not_7(u: Union2) { +>f2Not_7 : Symbol(f2Not_7, Decl(typeGuardAccordingToProperty.ts, 228, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 230, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'function') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 230, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Function1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 230, 17)) + } + if (typeof u.key != 'function') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 230, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Function1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 230, 17)) + } +} + +function f2Not_8(u: Union2) { +>f2Not_8 : Symbol(f2Not_8, Decl(typeGuardAccordingToProperty.ts, 237, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 239, 17)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToProperty.ts, 53, 44)) + + if (typeof u.key !== 'object') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 239, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Object1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 239, 17)) + } + if (typeof u.key != 'object') { +>u.key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 239, 17)) +>key : Symbol(key, Decl(typeGuardAccordingToProperty.ts, 6, 20), Decl(typeGuardAccordingToProperty.ts, 16, 19), Decl(typeGuardAccordingToProperty.ts, 21, 19), Decl(typeGuardAccordingToProperty.ts, 26, 19), Decl(typeGuardAccordingToProperty.ts, 31, 19) ... and 3 more) + + u; // not Object1 +>u : Symbol(u, Decl(typeGuardAccordingToProperty.ts, 239, 17)) + } +} + +interface A { x: string, y: string }; +>A : Symbol(A, Decl(typeGuardAccordingToProperty.ts, 246, 1)) +>x : Symbol(A.x, Decl(typeGuardAccordingToProperty.ts, 248, 13)) +>y : Symbol(A.y, Decl(typeGuardAccordingToProperty.ts, 248, 24)) + +interface B { x: number, y: number }; +>B : Symbol(B, Decl(typeGuardAccordingToProperty.ts, 248, 37)) +>x : Symbol(B.x, Decl(typeGuardAccordingToProperty.ts, 249, 13)) +>y : Symbol(B.y, Decl(typeGuardAccordingToProperty.ts, 249, 24)) + +type X = A | B; +>X : Symbol(X, Decl(typeGuardAccordingToProperty.ts, 249, 37)) +>A : Symbol(A, Decl(typeGuardAccordingToProperty.ts, 246, 1)) +>B : Symbol(B, Decl(typeGuardAccordingToProperty.ts, 248, 37)) + +function f3(bar: X) { +>f3 : Symbol(f3, Decl(typeGuardAccordingToProperty.ts, 250, 15)) +>bar : Symbol(bar, Decl(typeGuardAccordingToProperty.ts, 252, 12)) +>X : Symbol(X, Decl(typeGuardAccordingToProperty.ts, 249, 37)) + + if (typeof bar.x === 'string') { +>bar.x : Symbol(x, Decl(typeGuardAccordingToProperty.ts, 248, 13), Decl(typeGuardAccordingToProperty.ts, 249, 13)) +>bar : Symbol(bar, Decl(typeGuardAccordingToProperty.ts, 252, 12)) +>x : Symbol(x, Decl(typeGuardAccordingToProperty.ts, 248, 13), Decl(typeGuardAccordingToProperty.ts, 249, 13)) + + let y = bar.y; // string +>y : Symbol(y, Decl(typeGuardAccordingToProperty.ts, 254, 11)) +>bar.y : Symbol(A.y, Decl(typeGuardAccordingToProperty.ts, 248, 24)) +>bar : Symbol(bar, Decl(typeGuardAccordingToProperty.ts, 252, 12)) +>y : Symbol(A.y, Decl(typeGuardAccordingToProperty.ts, 248, 24)) + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToProperty.types b/tests/baselines/reference/typeGuardAccordingToProperty.types new file mode 100644 index 0000000000000..92bc6a209329e --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty.types @@ -0,0 +1,776 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts === +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { + key: boolean; +>key : boolean + + b1: number; +>b1 : number + +}; + +interface Boolean2 { + key: boolean; +>key : boolean + + b2: number; +>b2 : number + +}; + +interface BigInt1 { + key: bigint; +>key : bigint + + bi1: number; +>bi1 : number + +}; + +interface Number1 { + key: number; +>key : number + + n1: number; +>n1 : number + +}; + +interface String1 { + key: string; +>key : string + + st1: number; +>st1 : number +} + +interface Symbol1 { + key: symbol; +>key : symbol + + sy1: number; +>sy1 : number +} + +interface Undefined1 { + key: undefined; +>key : undefined + + u1: number; +>u1 : number +} + +interface Function1 { + key: () => void; +>key : () => void + + f1: number; +>f1 : number +} + +interface Obejct1 { + key: { +>key : { notEmpty: number; } + + notEmpty: number; +>notEmpty : number + + }; + o1: number; +>o1 : number +} + +type Union1 = Boolean1 | Boolean2 | Number1; +>Union1 : Union1 + +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; +>Union2 : Union2 + +function f1_1(u: Union1) { +>f1_1 : (u: Union1) => void +>u : Union1 + + if (typeof u.key !== 'boolean') { +>typeof u.key !== 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : number | boolean +>u : Union1 +>key : number | boolean +>'boolean' : "boolean" + + u; // Number1 +>u : Number1 + + u.n1; // number +>u.n1 : number +>u : Number1 +>n1 : number + } +} +function f1_2(u: Union1) { +>f1_2 : (u: Union1) => void +>u : Union1 + + if (typeof u.key === 'boolean') { +>typeof u.key === 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : number | boolean +>u : Union1 +>key : number | boolean +>'boolean' : "boolean" + + u; // Bolean1 | Bolean2 +>u : Boolean1 | Boolean2 + + u.b1; // Error +>u.b1 : any +>u : Boolean1 | Boolean2 +>b1 : any + + u.b2; // Error +>u.b2 : any +>u : Boolean1 | Boolean2 +>b2 : any + } +} + +function f1ElementAccess_1(u: Union1) { +>f1ElementAccess_1 : (u: Union1) => void +>u : Union1 + + if (typeof u["key"] !== 'boolean') { +>typeof u["key"] !== 'boolean' : boolean +>typeof u["key"] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u["key"] : number | boolean +>u : Union1 +>"key" : "key" +>'boolean' : "boolean" + + u; // Number1 +>u : Number1 + + u.n1; // number +>u.n1 : number +>u : Number1 +>n1 : number + } +} +function f1ElementAccess_2(u: Union1) { +>f1ElementAccess_2 : (u: Union1) => void +>u : Union1 + + if (typeof u["key"] === 'boolean') { +>typeof u["key"] === 'boolean' : boolean +>typeof u["key"] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u["key"] : number | boolean +>u : Union1 +>"key" : "key" +>'boolean' : "boolean" + + u; // Bolean1 | Bolean2 +>u : Boolean1 | Boolean2 + + u.b1; // Error +>u.b1 : any +>u : Boolean1 | Boolean2 +>b1 : any + + u.b2; // Error +>u.b2 : any +>u : Boolean1 | Boolean2 +>b2 : any + } +} + +function f1_Plus(u: Union1) { +>f1_Plus : (u: Union1) => void +>u : Union1 + + if (typeof u.key !== 'boolean') { +>typeof u.key !== 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : number | boolean +>u : Union1 +>key : number | boolean +>'boolean' : "boolean" + + throw new Error(); +>new Error() : Error +>Error : ErrorConstructor + } + u; // Bolean1 | Bolean2 +>u : Boolean1 | Boolean2 + + if (typeof u.key === 'boolean') { +>typeof u.key === 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : boolean +>u : Boolean1 | Boolean2 +>key : boolean +>'boolean' : "boolean" + + throw new Error(); +>new Error() : Error +>Error : ErrorConstructor + } + u; // never +>u : never +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { +>f2_1 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'bigint') { +>typeof u.key === 'bigint' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'bigint' : "bigint" + + u; // BigInt1 +>u : BigInt1 + + u.bi1; +>u.bi1 : number +>u : BigInt1 +>bi1 : number + } + if (typeof u.key == 'bigint') { +>typeof u.key == 'bigint' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'bigint' : "bigint" + + u; // BigInt1 +>u : BigInt1 + + u.bi1; +>u.bi1 : number +>u : BigInt1 +>bi1 : number + } +} +function f2_2(u: Union2) { +>f2_2 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'boolean') { +>typeof u.key === 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'boolean' : "boolean" + + u; // Boolean1 +>u : Boolean1 + + u.b1; +>u.b1 : number +>u : Boolean1 +>b1 : number + } + if (typeof u.key == 'boolean') { +>typeof u.key == 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'boolean' : "boolean" + + u; // Boolean1 +>u : Boolean1 + + u.b1; +>u.b1 : number +>u : Boolean1 +>b1 : number + } +} +function f2_3(u: Union2) { +>f2_3 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'number') { +>typeof u.key === 'number' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'number' : "number" + + u; // Number1 +>u : Number1 + + u.n1; +>u.n1 : number +>u : Number1 +>n1 : number + } + if (typeof u.key == 'number') { +>typeof u.key == 'number' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'number' : "number" + + u; // Number1 +>u : Number1 + + u.n1; +>u.n1 : number +>u : Number1 +>n1 : number + } +} +function f2_4(u: Union2) { +>f2_4 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'string') { +>typeof u.key === 'string' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'string' : "string" + + u; // String1 +>u : String1 + + u.st1; +>u.st1 : number +>u : String1 +>st1 : number + } + if (typeof u.key == 'string') { +>typeof u.key == 'string' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'string' : "string" + + u; // String1 +>u : String1 + + u.st1; +>u.st1 : number +>u : String1 +>st1 : number + } +} +function f2_5(u: Union2) { +>f2_5 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'symbol') { +>typeof u.key === 'symbol' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'symbol' : "symbol" + + u; // Symbol1 +>u : Symbol1 + + u.sy1; +>u.sy1 : number +>u : Symbol1 +>sy1 : number + } + if (typeof u.key == 'symbol') { +>typeof u.key == 'symbol' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'symbol' : "symbol" + + u; // Symbol1 +>u : Symbol1 + + u.sy1; +>u.sy1 : number +>u : Symbol1 +>sy1 : number + } +} +function f2_6(u: Union2) { +>f2_6 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'undefined') { +>typeof u.key === 'undefined' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'undefined' : "undefined" + + u; // Undefined1 +>u : Undefined1 + + u.u1 +>u.u1 : number +>u : Undefined1 +>u1 : number + } + if (typeof u.key == 'undefined') { +>typeof u.key == 'undefined' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'undefined' : "undefined" + + u; // Undefined1 +>u : Undefined1 + + u.u1 +>u.u1 : number +>u : Undefined1 +>u1 : number + } +} +function f2_7(u: Union2) { +>f2_7 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'function') { +>typeof u.key === 'function' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'function' : "function" + + u; // Function1 +>u : Function1 + + u.f1; +>u.f1 : number +>u : Function1 +>f1 : number + } + if (typeof u.key == 'function') { +>typeof u.key == 'function' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'function' : "function" + + u; // Function1 +>u : Function1 + + u.f1; +>u.f1 : number +>u : Function1 +>f1 : number + } +} +function f2_8(u: Union2) { +>f2_8 : (u: Union2) => void +>u : Union2 + + if (typeof u.key === 'object') { +>typeof u.key === 'object' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'object' : "object" + + u; // Object1 +>u : Obejct1 + + u.o1; +>u.o1 : number +>u : Obejct1 +>o1 : number + } + if (typeof u.key == 'object') { +>typeof u.key == 'object' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'object' : "object" + + u; // Object1 +>u : Obejct1 + + u.o1; +>u.o1 : number +>u : Obejct1 +>o1 : number + } +} + +function f2Not_1(u: Union2) { +>f2Not_1 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'bigint') { +>typeof u.key !== 'bigint' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'bigint' : "bigint" + + u; // not BigInt1 +>u : Boolean1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } + if (typeof u.key != 'bigint') { +>typeof u.key != 'bigint' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'bigint' : "bigint" + + u; // not BigInt1 +>u : Boolean1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } +} +function f2Not_2(u: Union2) { +>f2Not_2 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'boolean') { +>typeof u.key !== 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'boolean' : "boolean" + + u; // not Boolean1 +>u : BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } + if (typeof u.key != 'boolean') { +>typeof u.key != 'boolean' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'boolean' : "boolean" + + u; // not Boolean1 +>u : BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } +} + +function f2Not_3(u: Union2) { +>f2Not_3 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'number') { +>typeof u.key !== 'number' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'number' : "number" + + u; // not Number1 +>u : Boolean1 | BigInt1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } + if (typeof u.key != 'number') { +>typeof u.key != 'number' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'number' : "number" + + u; // not Number1 +>u : Boolean1 | BigInt1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } +} + +function f2Not_4(u: Union2) { +>f2Not_4 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'string') { +>typeof u.key !== 'string' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'string' : "string" + + u; // not String1 +>u : Boolean1 | BigInt1 | Number1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } + if (typeof u.key != 'string') { +>typeof u.key != 'string' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'string' : "string" + + u; // not String1 +>u : Boolean1 | BigInt1 | Number1 | Symbol1 | Undefined1 | Function1 | Obejct1 + } +} + +function f2Not_5(u: Union2) { +>f2Not_5 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'symbol') { +>typeof u.key !== 'symbol' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'symbol' : "symbol" + + u; // not Symbol1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Undefined1 | Function1 | Obejct1 + } + if (typeof u.key != 'symbol') { +>typeof u.key != 'symbol' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'symbol' : "symbol" + + u; // not Symbol1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Undefined1 | Function1 | Obejct1 + } +} + +function f2Not_6(u: Union2) { +>f2Not_6 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'undefined') { +>typeof u.key !== 'undefined' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'undefined' : "undefined" + + u; // not Undefined1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Function1 | Obejct1 + } + if (typeof u.key != 'undefined') { +>typeof u.key != 'undefined' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'undefined' : "undefined" + + u; // not Undefined1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Function1 | Obejct1 + } +} + +function f2Not_7(u: Union2) { +>f2Not_7 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'function') { +>typeof u.key !== 'function' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'function' : "function" + + u; // not Function1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Obejct1 + } + if (typeof u.key != 'function') { +>typeof u.key != 'function' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'function' : "function" + + u; // not Function1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Obejct1 + } +} + +function f2Not_8(u: Union2) { +>f2Not_8 : (u: Union2) => void +>u : Union2 + + if (typeof u.key !== 'object') { +>typeof u.key !== 'object' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'object' : "object" + + u; // not Object1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 + } + if (typeof u.key != 'object') { +>typeof u.key != 'object' : boolean +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>'object' : "object" + + u; // not Object1 +>u : Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 + } +} + +interface A { x: string, y: string }; +>x : string +>y : string + +interface B { x: number, y: number }; +>x : number +>y : number + +type X = A | B; +>X : X + +function f3(bar: X) { +>f3 : (bar: X) => void +>bar : X + + if (typeof bar.x === 'string') { +>typeof bar.x === 'string' : boolean +>typeof bar.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>bar.x : string | number +>bar : X +>x : string | number +>'string' : "string" + + let y = bar.y; // string +>y : string +>bar.y : string +>bar : A +>y : string + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToProperty2.js b/tests/baselines/reference/typeGuardAccordingToProperty2.js new file mode 100644 index 0000000000000..b2d69a36d474f --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty2.js @@ -0,0 +1,43 @@ +//// [typeGuardAccordingToProperty2.ts] +interface A { + kind: 'A'; + symbol: object; + fileName: string; +} + +interface B { + kind: 'B'; +} + +declare var s: A | B; + +if (s.kind === 'A') { + if (s.symbol) { // this is a truthy condition, we could narrow it, but it has a property `symbol`, so do nothing. + s; // A + } else { + s.fileName; // A + } + + if (s) { // this is another truthy condition, now it is alone, so narrow it. + s; // A + } else { + s; // never + } +} + +//// [typeGuardAccordingToProperty2.js] +"use strict"; +if (s.kind === 'A') { + if (s.symbol) { // this is a truthy condition, we could narrow it, but it has a property `symbol`, so do nothing. + s; // A + } + else { + s.fileName; // A + } + if (s) { // this is another truthy condition, now it is alone, so narrow it. + s; // A + } + else { + s; // never + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToProperty2.symbols b/tests/baselines/reference/typeGuardAccordingToProperty2.symbols new file mode 100644 index 0000000000000..7330725c2c876 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty2.symbols @@ -0,0 +1,57 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty2.ts === +interface A { +>A : Symbol(A, Decl(typeGuardAccordingToProperty2.ts, 0, 0)) + + kind: 'A'; +>kind : Symbol(A.kind, Decl(typeGuardAccordingToProperty2.ts, 0, 13)) + + symbol: object; +>symbol : Symbol(A.symbol, Decl(typeGuardAccordingToProperty2.ts, 1, 14)) + + fileName: string; +>fileName : Symbol(A.fileName, Decl(typeGuardAccordingToProperty2.ts, 2, 19)) +} + +interface B { +>B : Symbol(B, Decl(typeGuardAccordingToProperty2.ts, 4, 1)) + + kind: 'B'; +>kind : Symbol(B.kind, Decl(typeGuardAccordingToProperty2.ts, 6, 13)) +} + +declare var s: A | B; +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) +>A : Symbol(A, Decl(typeGuardAccordingToProperty2.ts, 0, 0)) +>B : Symbol(B, Decl(typeGuardAccordingToProperty2.ts, 4, 1)) + +if (s.kind === 'A') { +>s.kind : Symbol(kind, Decl(typeGuardAccordingToProperty2.ts, 0, 13), Decl(typeGuardAccordingToProperty2.ts, 6, 13)) +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) +>kind : Symbol(kind, Decl(typeGuardAccordingToProperty2.ts, 0, 13), Decl(typeGuardAccordingToProperty2.ts, 6, 13)) + + if (s.symbol) { // this is a truthy condition, we could narrow it, but it has a property `symbol`, so do nothing. +>s.symbol : Symbol(A.symbol, Decl(typeGuardAccordingToProperty2.ts, 1, 14)) +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) +>symbol : Symbol(A.symbol, Decl(typeGuardAccordingToProperty2.ts, 1, 14)) + + s; // A +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) + + } else { + s.fileName; // A +>s.fileName : Symbol(A.fileName, Decl(typeGuardAccordingToProperty2.ts, 2, 19)) +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) +>fileName : Symbol(A.fileName, Decl(typeGuardAccordingToProperty2.ts, 2, 19)) + } + + if (s) { // this is another truthy condition, now it is alone, so narrow it. +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) + + s; // A +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) + + } else { + s; // never +>s : Symbol(s, Decl(typeGuardAccordingToProperty2.ts, 10, 11)) + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToProperty2.types b/tests/baselines/reference/typeGuardAccordingToProperty2.types new file mode 100644 index 0000000000000..887dc5ea10091 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToProperty2.types @@ -0,0 +1,53 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty2.ts === +interface A { + kind: 'A'; +>kind : "A" + + symbol: object; +>symbol : object + + fileName: string; +>fileName : string +} + +interface B { + kind: 'B'; +>kind : "B" +} + +declare var s: A | B; +>s : A | B + +if (s.kind === 'A') { +>s.kind === 'A' : boolean +>s.kind : "A" | "B" +>s : A | B +>kind : "A" | "B" +>'A' : "A" + + if (s.symbol) { // this is a truthy condition, we could narrow it, but it has a property `symbol`, so do nothing. +>s.symbol : object +>s : A +>symbol : object + + s; // A +>s : A + + } else { + s.fileName; // A +>s.fileName : string +>s : A +>fileName : string + } + + if (s) { // this is another truthy condition, now it is alone, so narrow it. +>s : A + + s; // A +>s : A + + } else { + s; // never +>s : never + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js new file mode 100644 index 0000000000000..4eace09749166 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.js @@ -0,0 +1,301 @@ +//// [typeGuardAccordingToPropertyBySwitch.ts] +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { + key: boolean; + b1: number; +}; + +interface Boolean2 { + key: boolean; + b2: number; +}; + +interface BigInt1 { + key: bigint; + bi1: number; +}; + +interface Number1 { + key: number; + n1: number; +}; + +interface String1 { + key: string; + st1: number; +} + +interface Symbol1 { + key: symbol; + sy1: number; +} + +interface Undefined1 { + key: undefined; + u1: number; +} + +interface Function1 { + key: () => void; + f1: number; +} + +interface Obejct1 { + key: { + notEmpty: number; + }; + o1: number; +} + +type Union1 = Boolean1 | Boolean2 | Number1; +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; + +function f1_1(u: Union1) { + switch (typeof u.key) { + case 'boolean': + u; // Boolean1 | Boolean2 + break; + case 'number': + u; // Number1 + break; + default: + u; // never + break; + } +} + +function f1_2(u: Union1) { + switch (typeof u.key) { + case 'boolean': + u; // Boolean1 | Boolean2 + break; + default: + u; // Number1 + break; + } +} + + +function f1ElementAccess_1(u: Union1) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { + switch (typeof u.key) { + case 'bigint': + u; // Bigint1 + break; + case 'boolean': + u; // Boolean1 + break; + case 'number': + u; // Number1 + break; + case 'string': + u; // String1 + break; + case 'symbol': + u; // Symbol1 + break; + case 'undefined': + u; // Undefined1 + break; + case 'function': + u; // Function1 + break; + case 'object': + u; // Object1 + break; + } +} + +function f2_2(u: Union2) { + switch (typeof u.key) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 + break; + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + } +} + +function f2_3(u: Union2) { + switch (typeof u.key) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 + break; + default: + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + } +} + +function f2_4(u: Union2) { + switch (typeof u.key) { + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + default: + u; // Boolean1 | BigInt1 | Number1 | String1 + break; + } +} + +interface A { x: string, y: string }; +interface B { x: number, y: number }; +type X = A | B; + +function f3(bar: X) { + switch (typeof bar.x) { + case 'string': + let y = bar.y; // string + break; + default: + bar.y; + break; + } +} + + +//// [typeGuardAccordingToPropertyBySwitch.js] +"use strict"; +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection +; +; +; +; +function f1_1(u) { + switch (typeof u.key) { + case 'boolean': + u; // Boolean1 | Boolean2 + break; + case 'number': + u; // Number1 + break; + default: + u; // never + break; + } +} +function f1_2(u) { + switch (typeof u.key) { + case 'boolean': + u; // Boolean1 | Boolean2 + break; + default: + u; // Number1 + break; + } +} +function f1ElementAccess_1(u) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +// boolean bigint number string symbol undefined function object +function f2_1(u) { + switch (typeof u.key) { + case 'bigint': + u; // Bigint1 + break; + case 'boolean': + u; // Boolean1 + break; + case 'number': + u; // Number1 + break; + case 'string': + u; // String1 + break; + case 'symbol': + u; // Symbol1 + break; + case 'undefined': + u; // Undefined1 + break; + case 'function': + u; // Function1 + break; + case 'object': + u; // Object1 + break; + } +} +function f2_2(u) { + switch (typeof u.key) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 + break; + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + } +} +function f2_3(u) { + switch (typeof u.key) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 + break; + default: + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + } +} +function f2_4(u) { + switch (typeof u.key) { + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + default: + u; // Boolean1 | BigInt1 | Number1 | String1 + break; + } +} +; +; +function f3(bar) { + switch (typeof bar.x) { + case 'string': + var y = bar.y; // string + break; + default: + bar.y; + break; + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.symbols b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.symbols new file mode 100644 index 0000000000000..c29805a791210 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.symbols @@ -0,0 +1,371 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts === +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { +>Boolean1 : Symbol(Boolean1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 0, 0)) + + key: boolean; +>key : Symbol(Boolean1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20)) + + b1: number; +>b1 : Symbol(Boolean1.b1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 7, 17)) + +}; + +interface Boolean2 { +>Boolean2 : Symbol(Boolean2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 9, 2)) + + key: boolean; +>key : Symbol(Boolean2.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 11, 20)) + + b2: number; +>b2 : Symbol(Boolean2.b2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 12, 17)) + +}; + +interface BigInt1 { +>BigInt1 : Symbol(BigInt1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 14, 2)) + + key: bigint; +>key : Symbol(BigInt1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19)) + + bi1: number; +>bi1 : Symbol(BigInt1.bi1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 17, 16)) + +}; + +interface Number1 { +>Number1 : Symbol(Number1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 19, 2)) + + key: number; +>key : Symbol(Number1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19)) + + n1: number; +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 22, 16)) + +}; + +interface String1 { +>String1 : Symbol(String1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 24, 2)) + + key: string; +>key : Symbol(String1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19)) + + st1: number; +>st1 : Symbol(String1.st1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 27, 16)) +} + +interface Symbol1 { +>Symbol1 : Symbol(Symbol1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 29, 1)) + + key: symbol; +>key : Symbol(Symbol1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19)) + + sy1: number; +>sy1 : Symbol(Symbol1.sy1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 32, 16)) +} + +interface Undefined1 { +>Undefined1 : Symbol(Undefined1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 34, 1)) + + key: undefined; +>key : Symbol(Undefined1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 36, 22)) + + u1: number; +>u1 : Symbol(Undefined1.u1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 37, 19)) +} + +interface Function1 { +>Function1 : Symbol(Function1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 39, 1)) + + key: () => void; +>key : Symbol(Function1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 41, 21)) + + f1: number; +>f1 : Symbol(Function1.f1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 42, 20)) +} + +interface Obejct1 { +>Obejct1 : Symbol(Obejct1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 44, 1)) + + key: { +>key : Symbol(Obejct1.key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 46, 19)) + + notEmpty: number; +>notEmpty : Symbol(notEmpty, Decl(typeGuardAccordingToPropertyBySwitch.ts, 47, 10)) + + }; + o1: number; +>o1 : Symbol(Obejct1.o1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 49, 6)) +} + +type Union1 = Boolean1 | Boolean2 | Number1; +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 51, 1)) +>Boolean1 : Symbol(Boolean1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 0, 0)) +>Boolean2 : Symbol(Boolean2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 9, 2)) +>Number1 : Symbol(Number1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 19, 2)) + +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 53, 44)) +>Boolean1 : Symbol(Boolean1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 0, 0)) +>BigInt1 : Symbol(BigInt1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 14, 2)) +>Number1 : Symbol(Number1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 19, 2)) +>String1 : Symbol(String1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 24, 2)) +>Symbol1 : Symbol(Symbol1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 29, 1)) +>Undefined1 : Symbol(Undefined1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 34, 1)) +>Function1 : Symbol(Function1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 39, 1)) +>Obejct1 : Symbol(Obejct1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 44, 1)) + +function f1_1(u: Union1) { +>f1_1 : Symbol(f1_1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 54, 98)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 56, 14)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 51, 1)) + + switch (typeof u.key) { +>u.key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 11, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 56, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 11, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19)) + + case 'boolean': + u; // Boolean1 | Boolean2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 56, 14)) + + break; + case 'number': + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 56, 14)) + + break; + default: + u; // never +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 56, 14)) + + break; + } +} + +function f1_2(u: Union1) { +>f1_2 : Symbol(f1_2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 68, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 70, 14)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 51, 1)) + + switch (typeof u.key) { +>u.key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 11, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 70, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 11, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19)) + + case 'boolean': + u; // Boolean1 | Boolean2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 70, 14)) + + break; + default: + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 70, 14)) + + break; + } +} + + +function f1ElementAccess_1(u: Union1) { +>f1ElementAccess_1 : Symbol(f1ElementAccess_1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 79, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 82, 27)) +>Union1 : Symbol(Union1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 51, 1)) + + if (typeof u["key"] !== 'boolean') { +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 82, 27)) +>"key" : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 11, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19)) + + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 82, 27)) + + u.n1; // number +>u.n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 22, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 82, 27)) +>n1 : Symbol(Number1.n1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 22, 16)) + } +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { +>f2_1 : Symbol(f2_1, Decl(typeGuardAccordingToPropertyBySwitch.ts, 87, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 53, 44)) + + switch (typeof u.key) { +>u.key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) + + case 'bigint': + u; // Bigint1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'boolean': + u; // Boolean1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'number': + u; // Number1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'string': + u; // String1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'symbol': + u; // Symbol1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'undefined': + u; // Undefined1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'function': + u; // Function1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + case 'object': + u; // Object1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 90, 14)) + + break; + } +} + +function f2_2(u: Union2) { +>f2_2 : Symbol(f2_2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 117, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 119, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 53, 44)) + + switch (typeof u.key) { +>u.key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 119, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) + + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 119, 14)) + + break; + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 119, 14)) + + break; + } +} + +function f2_3(u: Union2) { +>f2_3 : Symbol(f2_3, Decl(typeGuardAccordingToPropertyBySwitch.ts, 134, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 136, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 53, 44)) + + switch (typeof u.key) { +>u.key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 136, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) + + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 136, 14)) + + break; + default: + u; // Symbol1 | Undefined1 | Function1 | Obejct1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 136, 14)) + + break; + } +} + +function f2_4(u: Union2) { +>f2_4 : Symbol(f2_4, Decl(typeGuardAccordingToPropertyBySwitch.ts, 148, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 150, 14)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyBySwitch.ts, 53, 44)) + + switch (typeof u.key) { +>u.key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 150, 14)) +>key : Symbol(key, Decl(typeGuardAccordingToPropertyBySwitch.ts, 6, 20), Decl(typeGuardAccordingToPropertyBySwitch.ts, 16, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 21, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 26, 19), Decl(typeGuardAccordingToPropertyBySwitch.ts, 31, 19) ... and 3 more) + + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 150, 14)) + + break; + default: + u; // Boolean1 | BigInt1 | Number1 | String1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyBySwitch.ts, 150, 14)) + + break; + } +} + +interface A { x: string, y: string }; +>A : Symbol(A, Decl(typeGuardAccordingToPropertyBySwitch.ts, 162, 1)) +>x : Symbol(A.x, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 13)) +>y : Symbol(A.y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 24)) + +interface B { x: number, y: number }; +>B : Symbol(B, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 37)) +>x : Symbol(B.x, Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 13)) +>y : Symbol(B.y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 24)) + +type X = A | B; +>X : Symbol(X, Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 37)) +>A : Symbol(A, Decl(typeGuardAccordingToPropertyBySwitch.ts, 162, 1)) +>B : Symbol(B, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 37)) + +function f3(bar: X) { +>f3 : Symbol(f3, Decl(typeGuardAccordingToPropertyBySwitch.ts, 166, 15)) +>bar : Symbol(bar, Decl(typeGuardAccordingToPropertyBySwitch.ts, 168, 12)) +>X : Symbol(X, Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 37)) + + switch (typeof bar.x) { +>bar.x : Symbol(x, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 13), Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 13)) +>bar : Symbol(bar, Decl(typeGuardAccordingToPropertyBySwitch.ts, 168, 12)) +>x : Symbol(x, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 13), Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 13)) + + case 'string': + let y = bar.y; // string +>y : Symbol(y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 171, 15)) +>bar.y : Symbol(A.y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 24)) +>bar : Symbol(bar, Decl(typeGuardAccordingToPropertyBySwitch.ts, 168, 12)) +>y : Symbol(A.y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 164, 24)) + + break; + default: + bar.y; +>bar.y : Symbol(B.y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 24)) +>bar : Symbol(bar, Decl(typeGuardAccordingToPropertyBySwitch.ts, 168, 12)) +>y : Symbol(B.y, Decl(typeGuardAccordingToPropertyBySwitch.ts, 165, 24)) + + break; + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.types b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.types new file mode 100644 index 0000000000000..8080cc15b0d89 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyBySwitch.types @@ -0,0 +1,397 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts === +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { + key: boolean; +>key : boolean + + b1: number; +>b1 : number + +}; + +interface Boolean2 { + key: boolean; +>key : boolean + + b2: number; +>b2 : number + +}; + +interface BigInt1 { + key: bigint; +>key : bigint + + bi1: number; +>bi1 : number + +}; + +interface Number1 { + key: number; +>key : number + + n1: number; +>n1 : number + +}; + +interface String1 { + key: string; +>key : string + + st1: number; +>st1 : number +} + +interface Symbol1 { + key: symbol; +>key : symbol + + sy1: number; +>sy1 : number +} + +interface Undefined1 { + key: undefined; +>key : undefined + + u1: number; +>u1 : number +} + +interface Function1 { + key: () => void; +>key : () => void + + f1: number; +>f1 : number +} + +interface Obejct1 { + key: { +>key : { notEmpty: number; } + + notEmpty: number; +>notEmpty : number + + }; + o1: number; +>o1 : number +} + +type Union1 = Boolean1 | Boolean2 | Number1; +>Union1 : Union1 + +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; +>Union2 : Union2 + +function f1_1(u: Union1) { +>f1_1 : (u: Union1) => void +>u : Union1 + + switch (typeof u.key) { +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : number | boolean +>u : Union1 +>key : number | boolean + + case 'boolean': +>'boolean' : "boolean" + + u; // Boolean1 | Boolean2 +>u : Boolean1 | Boolean2 + + break; + case 'number': +>'number' : "number" + + u; // Number1 +>u : Number1 + + break; + default: + u; // never +>u : never + + break; + } +} + +function f1_2(u: Union1) { +>f1_2 : (u: Union1) => void +>u : Union1 + + switch (typeof u.key) { +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : number | boolean +>u : Union1 +>key : number | boolean + + case 'boolean': +>'boolean' : "boolean" + + u; // Boolean1 | Boolean2 +>u : Boolean1 | Boolean2 + + break; + default: + u; // Number1 +>u : Number1 + + break; + } +} + + +function f1ElementAccess_1(u: Union1) { +>f1ElementAccess_1 : (u: Union1) => void +>u : Union1 + + if (typeof u["key"] !== 'boolean') { +>typeof u["key"] !== 'boolean' : boolean +>typeof u["key"] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u["key"] : number | boolean +>u : Union1 +>"key" : "key" +>'boolean' : "boolean" + + u; // Number1 +>u : Number1 + + u.n1; // number +>u.n1 : number +>u : Number1 +>n1 : number + } +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { +>f2_1 : (u: Union2) => void +>u : Union2 + + switch (typeof u.key) { +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined + + case 'bigint': +>'bigint' : "bigint" + + u; // Bigint1 +>u : BigInt1 + + break; + case 'boolean': +>'boolean' : "boolean" + + u; // Boolean1 +>u : Boolean1 + + break; + case 'number': +>'number' : "number" + + u; // Number1 +>u : Number1 + + break; + case 'string': +>'string' : "string" + + u; // String1 +>u : String1 + + break; + case 'symbol': +>'symbol' : "symbol" + + u; // Symbol1 +>u : Symbol1 + + break; + case 'undefined': +>'undefined' : "undefined" + + u; // Undefined1 +>u : Undefined1 + + break; + case 'function': +>'function' : "function" + + u; // Function1 +>u : Function1 + + break; + case 'object': +>'object' : "object" + + u; // Object1 +>u : Obejct1 + + break; + } +} + +function f2_2(u: Union2) { +>f2_2 : (u: Union2) => void +>u : Union2 + + switch (typeof u.key) { +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined + + case 'bigint': +>'bigint' : "bigint" + + case 'boolean': +>'boolean' : "boolean" + + case 'number': +>'number' : "number" + + case 'string': +>'string' : "string" + + u; // Boolean1 | Number1 | BigInt1 | String1 +>u : Boolean1 | BigInt1 | Number1 | String1 + + break; + case 'symbol': +>'symbol' : "symbol" + + case 'undefined': +>'undefined' : "undefined" + + case 'function': +>'function' : "function" + + case 'object': +>'object' : "object" + + u; // Symbol1 | Undefined1 | Function1 | Obejct1 +>u : Symbol1 | Undefined1 | Function1 | Obejct1 + + break; + } +} + +function f2_3(u: Union2) { +>f2_3 : (u: Union2) => void +>u : Union2 + + switch (typeof u.key) { +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined + + case 'bigint': +>'bigint' : "bigint" + + case 'boolean': +>'boolean' : "boolean" + + case 'number': +>'number' : "number" + + case 'string': +>'string' : "string" + + u; // Boolean1 | Number1 | BigInt1 | String1 +>u : Boolean1 | BigInt1 | Number1 | String1 + + break; + default: + u; // Symbol1 | Undefined1 | Function1 | Obejct1 +>u : Symbol1 | Undefined1 | Function1 | Obejct1 + + break; + } +} + +function f2_4(u: Union2) { +>f2_4 : (u: Union2) => void +>u : Union2 + + switch (typeof u.key) { +>typeof u.key : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined +>u : Union2 +>key : string | number | bigint | boolean | symbol | (() => void) | { notEmpty: number; } | undefined + + case 'symbol': +>'symbol' : "symbol" + + case 'undefined': +>'undefined' : "undefined" + + case 'function': +>'function' : "function" + + case 'object': +>'object' : "object" + + u; // Symbol1 | Undefined1 | Function1 | Obejct1 +>u : Symbol1 | Undefined1 | Function1 | Obejct1 + + break; + default: + u; // Boolean1 | BigInt1 | Number1 | String1 +>u : Boolean1 | BigInt1 | Number1 | String1 + + break; + } +} + +interface A { x: string, y: string }; +>x : string +>y : string + +interface B { x: number, y: number }; +>x : number +>y : number + +type X = A | B; +>X : X + +function f3(bar: X) { +>f3 : (bar: X) => void +>bar : X + + switch (typeof bar.x) { +>typeof bar.x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>bar.x : string | number +>bar : X +>x : string | number + + case 'string': +>'string' : "string" + + let y = bar.y; // string +>y : string +>bar.y : string +>bar : A +>y : string + + break; + default: + bar.y; +>bar.y : number +>bar : B +>y : number + + break; + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js new file mode 100644 index 0000000000000..9d87bbf99a053 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.js @@ -0,0 +1,83 @@ +//// [typeGuardAccordingToPropertyDeep.ts] +//// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] +//// mix deep property access ---- a.b["c"]["d"].e + +interface Foo1 { + firstKey: number, + inner: { + secondKey: number, + f1: number + } +} + +interface Foo2 { + firstKey: boolean, + inner: { + secondKey: boolean, + f2: number + } +} + +interface Foo3 { + firstKey: string; +} + +type Union = Foo1 | Foo2 | Foo3; + +function f(u: Union) { + if (typeof u.firstKey === "number" || typeof u.firstKey === "boolean") { + u; // Foo1 | Foo2 + if (typeof u.inner.secondKey === "boolean") { + u; // Foo2 + } + } +} + +type Union2 = Foo1 | Foo2; + +function f2(u: Union2) { + if (typeof u.inner["secondKey"] === "boolean") { + u; // Foo2 + } +} + +function f3(u: Union2) { + if (typeof u["inner"]["secondKey"] === "boolean") { + u; // Foo2 + } +} + +function f4(u: Union2) { + if (typeof u["inner"].secondKey === "boolean") { + u; // Foo2 + } +} + + +//// [typeGuardAccordingToPropertyDeep.js] +"use strict"; +//// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] +//// mix deep property access ---- a.b["c"]["d"].e +function f(u) { + if (typeof u.firstKey === "number" || typeof u.firstKey === "boolean") { + u; // Foo1 | Foo2 + if (typeof u.inner.secondKey === "boolean") { + u; // Foo2 + } + } +} +function f2(u) { + if (typeof u.inner["secondKey"] === "boolean") { + u; // Foo2 + } +} +function f3(u) { + if (typeof u["inner"]["secondKey"] === "boolean") { + u; // Foo2 + } +} +function f4(u) { + if (typeof u["inner"].secondKey === "boolean") { + u; // Foo2 + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeep.symbols b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.symbols new file mode 100644 index 0000000000000..bd73ca61965bb --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.symbols @@ -0,0 +1,132 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts === +//// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] +//// mix deep property access ---- a.b["c"]["d"].e + +interface Foo1 { +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyDeep.ts, 0, 0)) + + firstKey: number, +>firstKey : Symbol(Foo1.firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 3, 16)) + + inner: { +>inner : Symbol(Foo1.inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21)) + + secondKey: number, +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12)) + + f1: number +>f1 : Symbol(f1, Decl(typeGuardAccordingToPropertyDeep.ts, 6, 26)) + } +} + +interface Foo2 { +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyDeep.ts, 9, 1)) + + firstKey: boolean, +>firstKey : Symbol(Foo2.firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 11, 16)) + + inner: { +>inner : Symbol(Foo2.inner, Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) + + secondKey: boolean, +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) + + f2: number +>f2 : Symbol(f2, Decl(typeGuardAccordingToPropertyDeep.ts, 14, 27)) + } +} + +interface Foo3 { +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyDeep.ts, 17, 1)) + + firstKey: string; +>firstKey : Symbol(Foo3.firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 19, 16)) +} + +type Union = Foo1 | Foo2 | Foo3; +>Union : Symbol(Union, Decl(typeGuardAccordingToPropertyDeep.ts, 21, 1)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyDeep.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyDeep.ts, 9, 1)) +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyDeep.ts, 17, 1)) + +function f(u: Union) { +>f : Symbol(f, Decl(typeGuardAccordingToPropertyDeep.ts, 23, 32)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 25, 11)) +>Union : Symbol(Union, Decl(typeGuardAccordingToPropertyDeep.ts, 21, 1)) + + if (typeof u.firstKey === "number" || typeof u.firstKey === "boolean") { +>u.firstKey : Symbol(firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 3, 16), Decl(typeGuardAccordingToPropertyDeep.ts, 11, 16), Decl(typeGuardAccordingToPropertyDeep.ts, 19, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 25, 11)) +>firstKey : Symbol(firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 3, 16), Decl(typeGuardAccordingToPropertyDeep.ts, 11, 16), Decl(typeGuardAccordingToPropertyDeep.ts, 19, 16)) +>u.firstKey : Symbol(firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 11, 16), Decl(typeGuardAccordingToPropertyDeep.ts, 19, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 25, 11)) +>firstKey : Symbol(firstKey, Decl(typeGuardAccordingToPropertyDeep.ts, 11, 16), Decl(typeGuardAccordingToPropertyDeep.ts, 19, 16)) + + u; // Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 25, 11)) + + if (typeof u.inner.secondKey === "boolean") { +>u.inner.secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12), Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) +>u.inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21), Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 25, 11)) +>inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21), Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12), Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) + + u; // Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 25, 11)) + } + } +} + +type Union2 = Foo1 | Foo2; +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyDeep.ts, 32, 1)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyDeep.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyDeep.ts, 9, 1)) + +function f2(u: Union2) { +>f2 : Symbol(f2, Decl(typeGuardAccordingToPropertyDeep.ts, 34, 26)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 36, 12)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyDeep.ts, 32, 1)) + + if (typeof u.inner["secondKey"] === "boolean") { +>u.inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21), Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 36, 12)) +>inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21), Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) +>"secondKey" : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12), Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) + + u; // Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 36, 12)) + } +} + +function f3(u: Union2) { +>f3 : Symbol(f3, Decl(typeGuardAccordingToPropertyDeep.ts, 40, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 42, 12)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyDeep.ts, 32, 1)) + + if (typeof u["inner"]["secondKey"] === "boolean") { +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 42, 12)) +>"inner" : Symbol(inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21), Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) +>"secondKey" : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12), Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) + + u; // Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 42, 12)) + } +} + +function f4(u: Union2) { +>f4 : Symbol(f4, Decl(typeGuardAccordingToPropertyDeep.ts, 46, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 48, 12)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyDeep.ts, 32, 1)) + + if (typeof u["inner"].secondKey === "boolean") { +>u["inner"].secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12), Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 48, 12)) +>"inner" : Symbol(inner, Decl(typeGuardAccordingToPropertyDeep.ts, 4, 21), Decl(typeGuardAccordingToPropertyDeep.ts, 12, 22)) +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeep.ts, 5, 12), Decl(typeGuardAccordingToPropertyDeep.ts, 13, 12)) + + u; // Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeep.ts, 48, 12)) + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeep.types b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.types new file mode 100644 index 0000000000000..264d2576d44f4 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeep.types @@ -0,0 +1,140 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts === +//// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] +//// mix deep property access ---- a.b["c"]["d"].e + +interface Foo1 { + firstKey: number, +>firstKey : number + + inner: { +>inner : { secondKey: number; f1: number; } + + secondKey: number, +>secondKey : number + + f1: number +>f1 : number + } +} + +interface Foo2 { + firstKey: boolean, +>firstKey : boolean + + inner: { +>inner : { secondKey: boolean; f2: number; } + + secondKey: boolean, +>secondKey : boolean + + f2: number +>f2 : number + } +} + +interface Foo3 { + firstKey: string; +>firstKey : string +} + +type Union = Foo1 | Foo2 | Foo3; +>Union : Union + +function f(u: Union) { +>f : (u: Union) => void +>u : Union + + if (typeof u.firstKey === "number" || typeof u.firstKey === "boolean") { +>typeof u.firstKey === "number" || typeof u.firstKey === "boolean" : boolean +>typeof u.firstKey === "number" : boolean +>typeof u.firstKey : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.firstKey : string | number | boolean +>u : Union +>firstKey : string | number | boolean +>"number" : "number" +>typeof u.firstKey === "boolean" : boolean +>typeof u.firstKey : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.firstKey : string | boolean +>u : Foo2 | Foo3 +>firstKey : string | boolean +>"boolean" : "boolean" + + u; // Foo1 | Foo2 +>u : Foo1 | Foo2 + + if (typeof u.inner.secondKey === "boolean") { +>typeof u.inner.secondKey === "boolean" : boolean +>typeof u.inner.secondKey : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.inner.secondKey : number | boolean +>u.inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>u : Foo1 | Foo2 +>inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>secondKey : number | boolean +>"boolean" : "boolean" + + u; // Foo2 +>u : Foo2 + } + } +} + +type Union2 = Foo1 | Foo2; +>Union2 : Union2 + +function f2(u: Union2) { +>f2 : (u: Union2) => void +>u : Union2 + + if (typeof u.inner["secondKey"] === "boolean") { +>typeof u.inner["secondKey"] === "boolean" : boolean +>typeof u.inner["secondKey"] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.inner["secondKey"] : number | boolean +>u.inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>u : Union2 +>inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>"secondKey" : "secondKey" +>"boolean" : "boolean" + + u; // Foo2 +>u : Foo2 + } +} + +function f3(u: Union2) { +>f3 : (u: Union2) => void +>u : Union2 + + if (typeof u["inner"]["secondKey"] === "boolean") { +>typeof u["inner"]["secondKey"] === "boolean" : boolean +>typeof u["inner"]["secondKey"] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u["inner"]["secondKey"] : number | boolean +>u["inner"] : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>u : Union2 +>"inner" : "inner" +>"secondKey" : "secondKey" +>"boolean" : "boolean" + + u; // Foo2 +>u : Foo2 + } +} + +function f4(u: Union2) { +>f4 : (u: Union2) => void +>u : Union2 + + if (typeof u["inner"].secondKey === "boolean") { +>typeof u["inner"].secondKey === "boolean" : boolean +>typeof u["inner"].secondKey : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u["inner"].secondKey : number | boolean +>u["inner"] : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>u : Union2 +>"inner" : "inner" +>secondKey : number | boolean +>"boolean" : "boolean" + + u; // Foo2 +>u : Foo2 + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.js b/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.js new file mode 100644 index 0000000000000..e8c73e827211e --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.js @@ -0,0 +1,74 @@ +//// [typeGuardAccordingToPropertyDeepBySwitch.ts] +interface Foo1 { + firstKey: number, + inner: { + secondKey: number, + f1: number + } +} + +interface Foo2 { + firstKey: boolean, + inner: { + secondKey: boolean, + f2: number + } +} + +interface Foo3 { + firstKey: string; +} + +type Union = Foo1 | Foo2 | Foo3; + +function f(u: Union) { + switch (typeof u.firstKey) { + case 'number': + case 'boolean': + u; + switch (typeof u.inner.secondKey) { + case 'boolean': + u; + } + } +} + +type Union2 = Foo1 | Foo2; + +// fall through +function f2(u: Union2) { + switch (typeof u.inner["secondKey"]) { + case 'boolean': + u; // never + case 'bigint': + u; // Foo2 + default: + u; // Union2 + } +} + + +//// [typeGuardAccordingToPropertyDeepBySwitch.js] +"use strict"; +function f(u) { + switch (typeof u.firstKey) { + case 'number': + case 'boolean': + u; + switch (typeof u.inner.secondKey) { + case 'boolean': + u; + } + } +} +// fall through +function f2(u) { + switch (typeof u.inner["secondKey"]) { + case 'boolean': + u; // never + case 'bigint': + u; // Foo2 + default: + u; // Union2 + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.symbols b/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.symbols new file mode 100644 index 0000000000000..7e6b07084869a --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.symbols @@ -0,0 +1,108 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeepBySwitch.ts === +interface Foo1 { +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 0, 0)) + + firstKey: number, +>firstKey : Symbol(Foo1.firstKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 0, 16)) + + inner: { +>inner : Symbol(Foo1.inner, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 1, 21)) + + secondKey: number, +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 2, 12)) + + f1: number +>f1 : Symbol(f1, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 3, 26)) + } +} + +interface Foo2 { +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 6, 1)) + + firstKey: boolean, +>firstKey : Symbol(Foo2.firstKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 8, 16)) + + inner: { +>inner : Symbol(Foo2.inner, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 9, 22)) + + secondKey: boolean, +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 10, 12)) + + f2: number +>f2 : Symbol(f2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 11, 27)) + } +} + +interface Foo3 { +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 14, 1)) + + firstKey: string; +>firstKey : Symbol(Foo3.firstKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 16, 16)) +} + +type Union = Foo1 | Foo2 | Foo3; +>Union : Symbol(Union, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 18, 1)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 6, 1)) +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 14, 1)) + +function f(u: Union) { +>f : Symbol(f, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 20, 32)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 22, 11)) +>Union : Symbol(Union, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 18, 1)) + + switch (typeof u.firstKey) { +>u.firstKey : Symbol(firstKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 8, 16), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 16, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 22, 11)) +>firstKey : Symbol(firstKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 8, 16), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 16, 16)) + + case 'number': + case 'boolean': + u; +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 22, 11)) + + switch (typeof u.inner.secondKey) { +>u.inner.secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 2, 12), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 10, 12)) +>u.inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 1, 21), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 9, 22)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 22, 11)) +>inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 1, 21), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 9, 22)) +>secondKey : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 2, 12), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 10, 12)) + + case 'boolean': + u; +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 22, 11)) + } + } +} + +type Union2 = Foo1 | Foo2; +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 32, 1)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 6, 1)) + +// fall through +function f2(u: Union2) { +>f2 : Symbol(f2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 34, 26)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 37, 12)) +>Union2 : Symbol(Union2, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 32, 1)) + + switch (typeof u.inner["secondKey"]) { +>u.inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 1, 21), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 9, 22)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 37, 12)) +>inner : Symbol(inner, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 1, 21), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 9, 22)) +>"secondKey" : Symbol(secondKey, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 2, 12), Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 10, 12)) + + case 'boolean': + u; // never +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 37, 12)) + + case 'bigint': + u; // Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 37, 12)) + + default: + u; // Union2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyDeepBySwitch.ts, 37, 12)) + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.types b/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.types new file mode 100644 index 0000000000000..ac3361da3adf0 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyDeepBySwitch.types @@ -0,0 +1,109 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeepBySwitch.ts === +interface Foo1 { + firstKey: number, +>firstKey : number + + inner: { +>inner : { secondKey: number; f1: number; } + + secondKey: number, +>secondKey : number + + f1: number +>f1 : number + } +} + +interface Foo2 { + firstKey: boolean, +>firstKey : boolean + + inner: { +>inner : { secondKey: boolean; f2: number; } + + secondKey: boolean, +>secondKey : boolean + + f2: number +>f2 : number + } +} + +interface Foo3 { + firstKey: string; +>firstKey : string +} + +type Union = Foo1 | Foo2 | Foo3; +>Union : Union + +function f(u: Union) { +>f : (u: Union) => void +>u : Union + + switch (typeof u.firstKey) { +>typeof u.firstKey : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.firstKey : string | number | boolean +>u : Union +>firstKey : string | number | boolean + + case 'number': +>'number' : "number" + + case 'boolean': +>'boolean' : "boolean" + + u; +>u : Foo1 | Foo2 + + switch (typeof u.inner.secondKey) { +>typeof u.inner.secondKey : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.inner.secondKey : number | boolean +>u.inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>u : Foo1 | Foo2 +>inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>secondKey : number | boolean + + case 'boolean': +>'boolean' : "boolean" + + u; +>u : Foo2 + } + } +} + +type Union2 = Foo1 | Foo2; +>Union2 : Union2 + +// fall through +function f2(u: Union2) { +>f2 : (u: Union2) => void +>u : Union2 + + switch (typeof u.inner["secondKey"]) { +>typeof u.inner["secondKey"] : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.inner["secondKey"] : number | boolean +>u.inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>u : Union2 +>inner : { secondKey: number; f1: number; } | { secondKey: boolean; f2: number; } +>"secondKey" : "secondKey" + + case 'boolean': +>'boolean' : "boolean" + + u; // never +>u : Foo2 + + case 'bigint': +>'bigint' : "bigint" + + u; // Foo2 +>u : Foo2 + + default: + u; // Union2 +>u : Union2 + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt new file mode 100644 index 0000000000000..8cbdfaf3779a6 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.errors.txt @@ -0,0 +1,112 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts(58,63): error TS2339: Property 'key2' does not exist on type 'never'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts (1 errors) ==== + interface Foo1 { + key1: { + key2: number; + } | undefined; + f1: number; + } + + interface Foo2 { + key1: { + key2: string + } | undefined; + f2: number; + } + + interface Foo3 { + key1: { + key2: number; + }; + f2: number; + } + type U1 = Foo1 | Foo2 | Foo3; + type U2 = Foo1 | Foo2 | Foo3 | undefined; + + + // unnecessary optional chain + function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // Foo1 | Foo2 + } + } + + // non-root optional chain + function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 + } + } + + function f2Plus(u: U1) { + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + ~~~~ +!!! error TS2339: Property 'key2' does not exist on type 'never'. + u; //should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; //should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + } + + // root optional chain + function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; //U2 + } + if (typeof u?.key1 === 'number') { + u; //never + } + if (typeof u?.key1 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } + } + + // multi optional chain + function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof u?.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js new file mode 100644 index 0000000000000..ee1258450415f --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.js @@ -0,0 +1,190 @@ +//// [typeGuardAccordingToPropertyOptional.ts] +interface Foo1 { + key1: { + key2: number; + } | undefined; + f1: number; +} + +interface Foo2 { + key1: { + key2: string + } | undefined; + f2: number; +} + +interface Foo3 { + key1: { + key2: number; + }; + f2: number; +} +type U1 = Foo1 | Foo2 | Foo3; +type U2 = Foo1 | Foo2 | Foo3 | undefined; + + +// unnecessary optional chain +function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // Foo1 | Foo2 + } +} + +// non-root optional chain +function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 + } +} + +function f2Plus(u: U1) { + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + u; //should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; //should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } +} + +// root optional chain +function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; //U2 + } + if (typeof u?.key1 === 'number') { + u; //never + } + if (typeof u?.key1 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} + +// multi optional chain +function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof u?.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} + + +//// [typeGuardAccordingToPropertyOptional.js] +"use strict"; +// unnecessary optional chain +function f1(u) { + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'number') { + u; // U1 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'number') { + u; // never + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'undefined') { + u; // U1 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'undefined') { + u; // Foo1 | Foo2 + } +} +// non-root optional chain +function f2(u) { + var _a, _b, _c, _d; + if (typeof ((_a = u.key1) === null || _a === void 0 ? void 0 : _a.key2) !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof ((_b = u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { + u; //Foo1 | Foo3 + } + if (typeof ((_c = u.key1) === null || _c === void 0 ? void 0 : _c.key2) !== 'undefined') { + u; //U1 + } + if (typeof ((_d = u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'undefined') { + u; //Foo1 | Foo2 + } +} +function f2Plus(u) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + if (typeof ((_a = u.key1) === null || _a === void 0 ? void 0 : _a.key2) === 'undefined' && typeof ((_b = u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { + u; //should be never, but this should be a design limit? + } + if (typeof ((_c = u.key1) === null || _c === void 0 ? void 0 : _c.key2) === 'undefined' || typeof ((_d = u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'number') { + u; //U1 + } + if (typeof ((_e = u.key1) === null || _e === void 0 ? void 0 : _e.key2) === 'number' && typeof ((_f = u.key1) === null || _f === void 0 ? void 0 : _f.key2) === 'undefined') { + u; //should be never, but this should be a design limit? + } + if (typeof ((_g = u.key1) === null || _g === void 0 ? void 0 : _g.key2) === 'number' || typeof ((_h = u.key1) === null || _h === void 0 ? void 0 : _h.key2) === 'undefined') { + u; //U1 + } + if (typeof ((_j = u.key1) === null || _j === void 0 ? void 0 : _j.key2) === 'number' || typeof ((_k = u.key1) === null || _k === void 0 ? void 0 : _k.key2) !== 'undefined') { + u; //U1 + } +} +// root optional chain +function f3(u) { + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'number') { + u; //U2 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'number') { + u; //never + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} +// multi optional chain +function f4(u) { + var _a, _b, _c, _d; + if (typeof ((_a = u === null || u === void 0 ? void 0 : u.key1) === null || _a === void 0 ? void 0 : _a.key2) !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof ((_b = u === null || u === void 0 ? void 0 : u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { + u; //Foo1 | Foo3 + } + if (typeof ((_c = u === null || u === void 0 ? void 0 : u.key1) === null || _c === void 0 ? void 0 : _c.key2) !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof ((_d = u === null || u === void 0 ? void 0 : u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols new file mode 100644 index 0000000000000..5175c101a0215 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.symbols @@ -0,0 +1,311 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts === +interface Foo1 { +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 0)) + + key1: { +>key1 : Symbol(Foo1.key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16)) + + key2: number; +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11)) + + } | undefined; + f1: number; +>f1 : Symbol(Foo1.f1, Decl(typeGuardAccordingToPropertyOptional.ts, 3, 18)) +} + +interface Foo2 { +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyOptional.ts, 5, 1)) + + key1: { +>key1 : Symbol(Foo2.key1, Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) + + key2: string +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) + + } | undefined; + f2: number; +>f2 : Symbol(Foo2.f2, Decl(typeGuardAccordingToPropertyOptional.ts, 10, 18)) +} + +interface Foo3 { +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyOptional.ts, 12, 1)) + + key1: { +>key1 : Symbol(Foo3.key1, Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + key2: number; +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + }; + f2: number; +>f2 : Symbol(Foo3.f2, Decl(typeGuardAccordingToPropertyOptional.ts, 17, 6)) +} +type U1 = Foo1 | Foo2 | Foo3; +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptional.ts, 19, 1)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyOptional.ts, 5, 1)) +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyOptional.ts, 12, 1)) + +type U2 = Foo1 | Foo2 | Foo3 | undefined; +>U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptional.ts, 20, 29)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyOptional.ts, 5, 1)) +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyOptional.ts, 12, 1)) + + +// unnecessary optional chain +function f1(u: U1) { +>f1 : Symbol(f1, Decl(typeGuardAccordingToPropertyOptional.ts, 21, 41)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptional.ts, 19, 1)) + + if (typeof u?.key1 !== 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; // U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) + } + if (typeof u?.key1 === 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; // never +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) + } + if (typeof u?.key1 !== 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; // U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) + } + if (typeof u?.key1 === 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; // Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 25, 12)) + } +} + +// non-root optional chain +function f2(u: U1) { +>f2 : Symbol(f2, Decl(typeGuardAccordingToPropertyOptional.ts, 38, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptional.ts, 19, 1)) + + if (typeof u.key1?.key2 !== 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) + } + if (typeof u.key1?.key2 === 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) + } + if (typeof u.key1?.key2 !== 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) + } + if (typeof u.key1?.key2 === 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 41, 12)) + } +} + +function f2Plus(u: U1) { +>f2Plus : Symbol(f2Plus, Decl(typeGuardAccordingToPropertyOptional.ts, 54, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptional.ts, 19, 1)) + + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) + + u; //should be never, but this should be a design limit? +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11)) + + u; //should be never, but this should be a design limit? +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 56, 16)) + } +} + +// root optional chain +function f3(u: U2) { +>f3 : Symbol(f3, Decl(typeGuardAccordingToPropertyOptional.ts, 72, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) +>U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptional.ts, 20, 29)) + + if (typeof u?.key1 !== 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; //U2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) + } + if (typeof u?.key1 === 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; //never +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) + } + if (typeof u?.key1 !== 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; //Foo1 | Foo2 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) + } + if (typeof u?.key1 === 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) + + u; //Foo1 | Foo2 | Undefined +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 75, 12)) + } +} + +// multi optional chain +function f4(u: U2) { +>f4 : Symbol(f4, Decl(typeGuardAccordingToPropertyOptional.ts, 88, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) +>U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptional.ts, 20, 29)) + + if (typeof u?.key1?.key2 !== 'number') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo2 | Undefined +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) + } + if (typeof u?.key1?.key2 === 'number') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) + } + if (typeof u?.key1?.key2 !== 'undefined') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo2 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) + } + if (typeof u?.key1?.key2 === 'undefined') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptional.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptional.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptional.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptional.ts, 15, 11)) + + u; //Foo1 | Foo2 | Undefined +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptional.ts, 91, 12)) + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types new file mode 100644 index 0000000000000..7043fceeb70e4 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptional.types @@ -0,0 +1,379 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts === +interface Foo1 { + key1: { +>key1 : { key2: number; } | undefined + + key2: number; +>key2 : number + + } | undefined; + f1: number; +>f1 : number +} + +interface Foo2 { + key1: { +>key1 : { key2: string; } | undefined + + key2: string +>key2 : string + + } | undefined; + f2: number; +>f2 : number +} + +interface Foo3 { + key1: { +>key1 : { key2: number; } + + key2: number; +>key2 : number + + }; + f2: number; +>f2 : number +} +type U1 = Foo1 | Foo2 | Foo3; +>U1 : U1 + +type U2 = Foo1 | Foo2 | Foo3 | undefined; +>U2 : U2 + + +// unnecessary optional chain +function f1(u: U1) { +>f1 : (u: U1) => void +>u : U1 + + if (typeof u?.key1 !== 'number') { +>typeof u?.key1 !== 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; // U1 +>u : U1 + } + if (typeof u?.key1 === 'number') { +>typeof u?.key1 === 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; // never +>u : never + } + if (typeof u?.key1 !== 'undefined') { +>typeof u?.key1 !== 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; // U1 +>u : U1 + } + if (typeof u?.key1 === 'undefined') { +>typeof u?.key1 === 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; // Foo1 | Foo2 +>u : Foo1 | Foo2 + } +} + +// non-root optional chain +function f2(u: U1) { +>f2 : (u: U1) => void +>u : U1 + + if (typeof u.key1?.key2 !== 'number') { +>typeof u.key1?.key2 !== 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo2 +>u : Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo3 +>u : Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { +>typeof u.key1?.key2 !== 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //U1 +>u : U1 + } + if (typeof u.key1?.key2 === 'undefined') { +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 +>u : Foo1 | Foo2 + } +} + +function f2Plus(u: U1) { +>f2Plus : (u: U1) => void +>u : U1 + + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { +>typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : any +>u.key1 : undefined +>u : Foo1 | Foo2 +>key1 : undefined +>key2 : any +>'number' : "number" + + u; //should be never, but this should be a design limit? +>u : Foo1 + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { +>typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key2 : string | number +>'number' : "number" + + u; //U1 +>u : U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { +>typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | undefined +>key2 : string | number | undefined +>'number' : "number" +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : number +>u.key1 : { key2: number; } +>u : Foo1 | Foo3 +>key1 : { key2: number; } +>key2 : number +>'undefined' : "undefined" + + u; //should be never, but this should be a design limit? +>u : Foo1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { +>typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | undefined +>key2 : string | number | undefined +>'number' : "number" +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | undefined +>u.key1 : { key2: string; } | undefined +>u : Foo1 | Foo2 +>key1 : { key2: string; } | undefined +>key2 : string | undefined +>'undefined' : "undefined" + + u; //U1 +>u : U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { +>typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined' : boolean +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | undefined +>key2 : string | number | undefined +>'number' : "number" +>typeof u.key1?.key2 !== 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | undefined +>u.key1 : { key2: string; } | undefined +>u : Foo1 | Foo2 +>key1 : { key2: string; } | undefined +>key2 : string | undefined +>'undefined' : "undefined" + + u; //U1 +>u : U1 + } +} + +// root optional chain +function f3(u: U2) { +>f3 : (u: U2) => void +>u : U2 + + if (typeof u?.key1 !== 'number') { +>typeof u?.key1 !== 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; //U2 +>u : U2 + } + if (typeof u?.key1 === 'number') { +>typeof u?.key1 === 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; //never +>u : never + } + if (typeof u?.key1 !== 'undefined') { +>typeof u?.key1 !== 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Foo3 +>u : Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { +>typeof u?.key1 === 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Undefined +>u : Foo1 | Foo2 | undefined + } +} + +// multi optional chain +function f4(u: U2) { +>f4 : (u: U2) => void +>u : U2 + + if (typeof u?.key1?.key2 !== 'number') { +>typeof u?.key1?.key2 !== 'number' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo2 | Undefined +>u : Foo1 | Foo2 | undefined + } + if (typeof u?.key1?.key2 === 'number') { +>typeof u?.key1?.key2 === 'number' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo3 +>u : Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { +>typeof u?.key1?.key2 !== 'undefined' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Foo3 +>u : Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { +>typeof u?.key1?.key2 === 'undefined' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Undefined +>u : Foo1 | Foo2 | undefined + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.errors.txt b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.errors.txt new file mode 100644 index 0000000000000..eabfa1f27f84b --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.errors.txt @@ -0,0 +1,112 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts(58,63): error TS2339: Property 'key2' does not exist on type 'never'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts (1 errors) ==== + interface Foo1 { + key1: { + key2: number; + } | undefined; + f1: number; + } + + interface Foo2 { + key1: { + key2: string + } | undefined; + f2: number; + } + + interface Foo3 { + key1: { + key2: number; + }; + f2: number; + } + type U1 = Foo1 | Foo2 | Foo3; + type U2 = Foo1 | Foo2 | Foo3 | undefined; + + + // unnecessary optional chain + function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // Foo1 | Foo2 + } + } + + // non-root optional chain + function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 + } + } + + function f2Plus(u: U1) { + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + ~~~~ +!!! error TS2339: Property 'key2' does not exist on type 'never'. + u; // should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; // should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + } + + // root optional chain + function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; //U2 + } + if (typeof u?.key1 === 'number') { + u; //never + } + if (typeof u?.key1 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } + } + + // multi optional chain + function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof u?.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.js b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.js new file mode 100644 index 0000000000000..a625fab9d0d7b --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.js @@ -0,0 +1,190 @@ +//// [typeGuardAccordingToPropertyOptionalBySwitch.ts] +interface Foo1 { + key1: { + key2: number; + } | undefined; + f1: number; +} + +interface Foo2 { + key1: { + key2: string + } | undefined; + f2: number; +} + +interface Foo3 { + key1: { + key2: number; + }; + f2: number; +} +type U1 = Foo1 | Foo2 | Foo3; +type U2 = Foo1 | Foo2 | Foo3 | undefined; + + +// unnecessary optional chain +function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // Foo1 | Foo2 + } +} + +// non-root optional chain +function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 + } +} + +function f2Plus(u: U1) { + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + u; // should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; // should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } +} + +// root optional chain +function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; //U2 + } + if (typeof u?.key1 === 'number') { + u; //never + } + if (typeof u?.key1 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} + +// multi optional chain +function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof u?.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} + + +//// [typeGuardAccordingToPropertyOptionalBySwitch.js] +"use strict"; +// unnecessary optional chain +function f1(u) { + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'number') { + u; // U1 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'number') { + u; // never + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'undefined') { + u; // U1 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'undefined') { + u; // Foo1 | Foo2 + } +} +// non-root optional chain +function f2(u) { + var _a, _b, _c, _d; + if (typeof ((_a = u.key1) === null || _a === void 0 ? void 0 : _a.key2) !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof ((_b = u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { + u; //Foo1 | Foo3 + } + if (typeof ((_c = u.key1) === null || _c === void 0 ? void 0 : _c.key2) !== 'undefined') { + u; //U1 + } + if (typeof ((_d = u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'undefined') { + u; //Foo1 | Foo2 + } +} +function f2Plus(u) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + if (typeof ((_a = u.key1) === null || _a === void 0 ? void 0 : _a.key2) === 'undefined' && typeof ((_b = u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { + u; // should be never, but this should be a design limit? + } + if (typeof ((_c = u.key1) === null || _c === void 0 ? void 0 : _c.key2) === 'undefined' || typeof ((_d = u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'number') { + u; //U1 + } + if (typeof ((_e = u.key1) === null || _e === void 0 ? void 0 : _e.key2) === 'number' && typeof ((_f = u.key1) === null || _f === void 0 ? void 0 : _f.key2) === 'undefined') { + u; // should be never, but this should be a design limit? + } + if (typeof ((_g = u.key1) === null || _g === void 0 ? void 0 : _g.key2) === 'number' || typeof ((_h = u.key1) === null || _h === void 0 ? void 0 : _h.key2) === 'undefined') { + u; //U1 + } + if (typeof ((_j = u.key1) === null || _j === void 0 ? void 0 : _j.key2) === 'number' || typeof ((_k = u.key1) === null || _k === void 0 ? void 0 : _k.key2) !== 'undefined') { + u; //U1 + } +} +// root optional chain +function f3(u) { + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'number') { + u; //U2 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'number') { + u; //never + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof (u === null || u === void 0 ? void 0 : u.key1) === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} +// multi optional chain +function f4(u) { + var _a, _b, _c, _d; + if (typeof ((_a = u === null || u === void 0 ? void 0 : u.key1) === null || _a === void 0 ? void 0 : _a.key2) !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof ((_b = u === null || u === void 0 ? void 0 : u.key1) === null || _b === void 0 ? void 0 : _b.key2) === 'number') { + u; //Foo1 | Foo3 + } + if (typeof ((_c = u === null || u === void 0 ? void 0 : u.key1) === null || _c === void 0 ? void 0 : _c.key2) !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof ((_d = u === null || u === void 0 ? void 0 : u.key1) === null || _d === void 0 ? void 0 : _d.key2) === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.symbols b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.symbols new file mode 100644 index 0000000000000..7381ba8a7da86 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.symbols @@ -0,0 +1,311 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts === +interface Foo1 { +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 0)) + + key1: { +>key1 : Symbol(Foo1.key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16)) + + key2: number; +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11)) + + } | undefined; + f1: number; +>f1 : Symbol(Foo1.f1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 3, 18)) +} + +interface Foo2 { +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 5, 1)) + + key1: { +>key1 : Symbol(Foo2.key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) + + key2: string +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) + + } | undefined; + f2: number; +>f2 : Symbol(Foo2.f2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 10, 18)) +} + +interface Foo3 { +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 12, 1)) + + key1: { +>key1 : Symbol(Foo3.key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + key2: number; +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + }; + f2: number; +>f2 : Symbol(Foo3.f2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 17, 6)) +} +type U1 = Foo1 | Foo2 | Foo3; +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 19, 1)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 5, 1)) +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 12, 1)) + +type U2 = Foo1 | Foo2 | Foo3 | undefined; +>U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 20, 29)) +>Foo1 : Symbol(Foo1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 0)) +>Foo2 : Symbol(Foo2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 5, 1)) +>Foo3 : Symbol(Foo3, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 12, 1)) + + +// unnecessary optional chain +function f1(u: U1) { +>f1 : Symbol(f1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 21, 41)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 19, 1)) + + if (typeof u?.key1 !== 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; // U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) + } + if (typeof u?.key1 === 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; // never +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) + } + if (typeof u?.key1 !== 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; // U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) + } + if (typeof u?.key1 === 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; // Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 25, 12)) + } +} + +// non-root optional chain +function f2(u: U1) { +>f2 : Symbol(f2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 38, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 19, 1)) + + if (typeof u.key1?.key2 !== 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) + } + if (typeof u.key1?.key2 === 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) + } + if (typeof u.key1?.key2 !== 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) + } + if (typeof u.key1?.key2 === 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 41, 12)) + } +} + +function f2Plus(u: U1) { +>f2Plus : Symbol(f2Plus, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 54, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>U1 : Symbol(U1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 19, 1)) + + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) + + u; // should be never, but this should be a design limit? +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11)) + + u; // should be never, but this should be a design limit? +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) +>u.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11)) + + u; //U1 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 56, 16)) + } +} + +// root optional chain +function f3(u: U2) { +>f3 : Symbol(f3, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 72, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) +>U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 20, 29)) + + if (typeof u?.key1 !== 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; //U2 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) + } + if (typeof u?.key1 === 'number') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; //never +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) + } + if (typeof u?.key1 !== 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; //Foo1 | Foo2 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) + } + if (typeof u?.key1 === 'undefined') { +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) + + u; //Foo1 | Foo2 | Undefined +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 75, 12)) + } +} + +// multi optional chain +function f4(u: U2) { +>f4 : Symbol(f4, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 88, 1)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) +>U2 : Symbol(U2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 20, 29)) + + if (typeof u?.key1?.key2 !== 'number') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo2 | Undefined +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) + } + if (typeof u?.key1?.key2 === 'number') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) + } + if (typeof u?.key1?.key2 !== 'undefined') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo2 | Foo3 +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) + } + if (typeof u?.key1?.key2 === 'undefined') { +>u?.key1?.key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) +>u?.key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) +>key1 : Symbol(key1, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 0, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 7, 16), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 14, 16)) +>key2 : Symbol(key2, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 1, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 8, 11), Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 15, 11)) + + u; //Foo1 | Foo2 | Undefined +>u : Symbol(u, Decl(typeGuardAccordingToPropertyOptionalBySwitch.ts, 91, 12)) + } +} + diff --git a/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.types b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.types new file mode 100644 index 0000000000000..99739475d9d44 --- /dev/null +++ b/tests/baselines/reference/typeGuardAccordingToPropertyOptionalBySwitch.types @@ -0,0 +1,379 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts === +interface Foo1 { + key1: { +>key1 : { key2: number; } | undefined + + key2: number; +>key2 : number + + } | undefined; + f1: number; +>f1 : number +} + +interface Foo2 { + key1: { +>key1 : { key2: string; } | undefined + + key2: string +>key2 : string + + } | undefined; + f2: number; +>f2 : number +} + +interface Foo3 { + key1: { +>key1 : { key2: number; } + + key2: number; +>key2 : number + + }; + f2: number; +>f2 : number +} +type U1 = Foo1 | Foo2 | Foo3; +>U1 : U1 + +type U2 = Foo1 | Foo2 | Foo3 | undefined; +>U2 : U2 + + +// unnecessary optional chain +function f1(u: U1) { +>f1 : (u: U1) => void +>u : U1 + + if (typeof u?.key1 !== 'number') { +>typeof u?.key1 !== 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; // U1 +>u : U1 + } + if (typeof u?.key1 === 'number') { +>typeof u?.key1 === 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; // never +>u : never + } + if (typeof u?.key1 !== 'undefined') { +>typeof u?.key1 !== 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; // U1 +>u : U1 + } + if (typeof u?.key1 === 'undefined') { +>typeof u?.key1 === 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; // Foo1 | Foo2 +>u : Foo1 | Foo2 + } +} + +// non-root optional chain +function f2(u: U1) { +>f2 : (u: U1) => void +>u : U1 + + if (typeof u.key1?.key2 !== 'number') { +>typeof u.key1?.key2 !== 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo2 +>u : Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo3 +>u : Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { +>typeof u.key1?.key2 !== 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //U1 +>u : U1 + } + if (typeof u.key1?.key2 === 'undefined') { +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 +>u : Foo1 | Foo2 + } +} + +function f2Plus(u: U1) { +>f2Plus : (u: U1) => void +>u : U1 + + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { +>typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : any +>u.key1 : undefined +>u : Foo1 | Foo2 +>key1 : undefined +>key2 : any +>'number' : "number" + + u; // should be never, but this should be a design limit? +>u : Foo1 + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { +>typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number +>u.key1 : { key2: number; } | { key2: string; } | { key2: number; } +>u : U1 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } +>key2 : string | number +>'number' : "number" + + u; //U1 +>u : U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { +>typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | undefined +>key2 : string | number | undefined +>'number' : "number" +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : number +>u.key1 : { key2: number; } +>u : Foo1 | Foo3 +>key1 : { key2: number; } +>key2 : number +>'undefined' : "undefined" + + u; // should be never, but this should be a design limit? +>u : Foo1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { +>typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | undefined +>key2 : string | number | undefined +>'number' : "number" +>typeof u.key1?.key2 === 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | undefined +>u.key1 : { key2: string; } | undefined +>u : Foo1 | Foo2 +>key1 : { key2: string; } | undefined +>key2 : string | undefined +>'undefined' : "undefined" + + u; //U1 +>u : U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { +>typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined' : boolean +>typeof u.key1?.key2 === 'number' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | number | undefined +>u.key1 : { key2: number; } | { key2: string; } | undefined +>u : U1 +>key1 : { key2: number; } | { key2: string; } | undefined +>key2 : string | number | undefined +>'number' : "number" +>typeof u.key1?.key2 !== 'undefined' : boolean +>typeof u.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u.key1?.key2 : string | undefined +>u.key1 : { key2: string; } | undefined +>u : Foo1 | Foo2 +>key1 : { key2: string; } | undefined +>key2 : string | undefined +>'undefined' : "undefined" + + u; //U1 +>u : U1 + } +} + +// root optional chain +function f3(u: U2) { +>f3 : (u: U2) => void +>u : U2 + + if (typeof u?.key1 !== 'number') { +>typeof u?.key1 !== 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; //U2 +>u : U2 + } + if (typeof u?.key1 === 'number') { +>typeof u?.key1 === 'number' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'number' : "number" + + u; //never +>u : never + } + if (typeof u?.key1 !== 'undefined') { +>typeof u?.key1 !== 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Foo3 +>u : Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { +>typeof u?.key1 === 'undefined' : boolean +>typeof u?.key1 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Undefined +>u : Foo1 | Foo2 | undefined + } +} + +// multi optional chain +function f4(u: U2) { +>f4 : (u: U2) => void +>u : U2 + + if (typeof u?.key1?.key2 !== 'number') { +>typeof u?.key1?.key2 !== 'number' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo2 | Undefined +>u : Foo1 | Foo2 | undefined + } + if (typeof u?.key1?.key2 === 'number') { +>typeof u?.key1?.key2 === 'number' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'number' : "number" + + u; //Foo1 | Foo3 +>u : Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { +>typeof u?.key1?.key2 !== 'undefined' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Foo3 +>u : Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { +>typeof u?.key1?.key2 === 'undefined' : boolean +>typeof u?.key1?.key2 : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>u?.key1?.key2 : string | number | undefined +>u?.key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>u : U2 +>key1 : { key2: number; } | { key2: string; } | { key2: number; } | undefined +>key2 : string | number | undefined +>'undefined' : "undefined" + + u; //Foo1 | Foo2 | Undefined +>u : Foo1 | Foo2 | undefined + } +} + diff --git a/tests/cases/compiler/nonNullReferenceMatching.ts b/tests/cases/compiler/nonNullReferenceMatching.ts index 1295c3ce9a7f7..eb7762b0c1d13 100644 --- a/tests/cases/compiler/nonNullReferenceMatching.ts +++ b/tests/cases/compiler/nonNullReferenceMatching.ts @@ -10,6 +10,14 @@ type ComponentProps = { thumbXProps: ThumbProps; } +type ThumbProps2 = { + elementRef: ElementRef | null; +} + +type ComponentProps2 = { + thumbYProps: ThumbProps2 | null; +} + class Component { props!: ComponentProps; public thumbYElementRef = (ref: HTMLElement | null) => { @@ -31,4 +39,15 @@ class Component { typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); }; +} + +class Component2 { + props!: ComponentProps2; + public thumbYElementRef = (ref: HTMLElement | null) => { + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); + } } \ No newline at end of file diff --git a/tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts b/tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts index e5495a313aa0d..b6d7a04800d2b 100644 --- a/tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts +++ b/tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts @@ -518,7 +518,7 @@ function f41(o: Thing | undefined) { o.foo; // Error break; default: - o.foo; // Error + o.foo; break; } } diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts new file mode 100644 index 0000000000000..d5b78fc3306c6 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty.ts @@ -0,0 +1,259 @@ +// @strict: true + +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { + key: boolean; + b1: number; +}; + +interface Boolean2 { + key: boolean; + b2: number; +}; + +interface BigInt1 { + key: bigint; + bi1: number; +}; + +interface Number1 { + key: number; + n1: number; +}; + +interface String1 { + key: string; + st1: number; +} + +interface Symbol1 { + key: symbol; + sy1: number; +} + +interface Undefined1 { + key: undefined; + u1: number; +} + +interface Function1 { + key: () => void; + f1: number; +} + +interface Obejct1 { + key: { + notEmpty: number; + }; + o1: number; +} + +type Union1 = Boolean1 | Boolean2 | Number1; +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; + +function f1_1(u: Union1) { + if (typeof u.key !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +function f1_2(u: Union1) { + if (typeof u.key === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + u.b2; // Error + } +} + +function f1ElementAccess_1(u: Union1) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } +} +function f1ElementAccess_2(u: Union1) { + if (typeof u["key"] === 'boolean') { + u; // Bolean1 | Bolean2 + u.b1; // Error + u.b2; // Error + } +} + +function f1_Plus(u: Union1) { + if (typeof u.key !== 'boolean') { + throw new Error(); + } + u; // Bolean1 | Bolean2 + if (typeof u.key === 'boolean') { + throw new Error(); + } + u; // never +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { + if (typeof u.key === 'bigint') { + u; // BigInt1 + u.bi1; + } + if (typeof u.key == 'bigint') { + u; // BigInt1 + u.bi1; + } +} +function f2_2(u: Union2) { + if (typeof u.key === 'boolean') { + u; // Boolean1 + u.b1; + } + if (typeof u.key == 'boolean') { + u; // Boolean1 + u.b1; + } +} +function f2_3(u: Union2) { + if (typeof u.key === 'number') { + u; // Number1 + u.n1; + } + if (typeof u.key == 'number') { + u; // Number1 + u.n1; + } +} +function f2_4(u: Union2) { + if (typeof u.key === 'string') { + u; // String1 + u.st1; + } + if (typeof u.key == 'string') { + u; // String1 + u.st1; + } +} +function f2_5(u: Union2) { + if (typeof u.key === 'symbol') { + u; // Symbol1 + u.sy1; + } + if (typeof u.key == 'symbol') { + u; // Symbol1 + u.sy1; + } +} +function f2_6(u: Union2) { + if (typeof u.key === 'undefined') { + u; // Undefined1 + u.u1 + } + if (typeof u.key == 'undefined') { + u; // Undefined1 + u.u1 + } +} +function f2_7(u: Union2) { + if (typeof u.key === 'function') { + u; // Function1 + u.f1; + } + if (typeof u.key == 'function') { + u; // Function1 + u.f1; + } +} +function f2_8(u: Union2) { + if (typeof u.key === 'object') { + u; // Object1 + u.o1; + } + if (typeof u.key == 'object') { + u; // Object1 + u.o1; + } +} + +function f2Not_1(u: Union2) { + if (typeof u.key !== 'bigint') { + u; // not BigInt1 + } + if (typeof u.key != 'bigint') { + u; // not BigInt1 + } +} +function f2Not_2(u: Union2) { + if (typeof u.key !== 'boolean') { + u; // not Boolean1 + } + if (typeof u.key != 'boolean') { + u; // not Boolean1 + } +} + +function f2Not_3(u: Union2) { + if (typeof u.key !== 'number') { + u; // not Number1 + } + if (typeof u.key != 'number') { + u; // not Number1 + } +} + +function f2Not_4(u: Union2) { + if (typeof u.key !== 'string') { + u; // not String1 + } + if (typeof u.key != 'string') { + u; // not String1 + } +} + +function f2Not_5(u: Union2) { + if (typeof u.key !== 'symbol') { + u; // not Symbol1 + } + if (typeof u.key != 'symbol') { + u; // not Symbol1 + } +} + +function f2Not_6(u: Union2) { + if (typeof u.key !== 'undefined') { + u; // not Undefined1 + } + if (typeof u.key != 'undefined') { + u; // not Undefined1 + } +} + +function f2Not_7(u: Union2) { + if (typeof u.key !== 'function') { + u; // not Function1 + } + if (typeof u.key != 'function') { + u; // not Function1 + } +} + +function f2Not_8(u: Union2) { + if (typeof u.key !== 'object') { + u; // not Object1 + } + if (typeof u.key != 'object') { + u; // not Object1 + } +} + +interface A { x: string, y: string }; +interface B { x: number, y: number }; +type X = A | B; + +function f3(bar: X) { + if (typeof bar.x === 'string') { + let y = bar.y; // string + } +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty2.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty2.ts new file mode 100644 index 0000000000000..276c89b4c580c --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToProperty2.ts @@ -0,0 +1,27 @@ +// @strict: true + +interface A { + kind: 'A'; + symbol: object; + fileName: string; +} + +interface B { + kind: 'B'; +} + +declare var s: A | B; + +if (s.kind === 'A') { + if (s.symbol) { // this is a truthy condition, we could narrow it, but it has a property `symbol`, so do nothing. + s; // A + } else { + s.fileName; // A + } + + if (s) { // this is another truthy condition, now it is alone, so narrow it. + s; // A + } else { + s; // never + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts new file mode 100644 index 0000000000000..d18eaeb54a6b6 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyBySwitch.ts @@ -0,0 +1,180 @@ +// @strict: true + +// Primitive value ---- boolean bigint number string symbol undefined function object +// ts special type ---- any, void, unknown, union, intersection + +//// Property Access ---- a.b +//// Element Access ---- a["b"] + +interface Boolean1 { + key: boolean; + b1: number; +}; + +interface Boolean2 { + key: boolean; + b2: number; +}; + +interface BigInt1 { + key: bigint; + bi1: number; +}; + +interface Number1 { + key: number; + n1: number; +}; + +interface String1 { + key: string; + st1: number; +} + +interface Symbol1 { + key: symbol; + sy1: number; +} + +interface Undefined1 { + key: undefined; + u1: number; +} + +interface Function1 { + key: () => void; + f1: number; +} + +interface Obejct1 { + key: { + notEmpty: number; + }; + o1: number; +} + +type Union1 = Boolean1 | Boolean2 | Number1; +type Union2 = Boolean1 | BigInt1 | Number1 | String1 | Symbol1 | Undefined1 | Function1 | Obejct1; + +function f1_1(u: Union1) { + switch (typeof u.key) { + case 'boolean': + u; // Boolean1 | Boolean2 + break; + case 'number': + u; // Number1 + break; + default: + u; // never + break; + } +} + +function f1_2(u: Union1) { + switch (typeof u.key) { + case 'boolean': + u; // Boolean1 | Boolean2 + break; + default: + u; // Number1 + break; + } +} + + +function f1ElementAccess_1(u: Union1) { + if (typeof u["key"] !== 'boolean') { + u; // Number1 + u.n1; // number + } +} + +// boolean bigint number string symbol undefined function object +function f2_1(u: Union2) { + switch (typeof u.key) { + case 'bigint': + u; // Bigint1 + break; + case 'boolean': + u; // Boolean1 + break; + case 'number': + u; // Number1 + break; + case 'string': + u; // String1 + break; + case 'symbol': + u; // Symbol1 + break; + case 'undefined': + u; // Undefined1 + break; + case 'function': + u; // Function1 + break; + case 'object': + u; // Object1 + break; + } +} + +function f2_2(u: Union2) { + switch (typeof u.key) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 + break; + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + } +} + +function f2_3(u: Union2) { + switch (typeof u.key) { + case 'bigint': + case 'boolean': + case 'number': + case 'string': + u; // Boolean1 | Number1 | BigInt1 | String1 + break; + default: + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + } +} + +function f2_4(u: Union2) { + switch (typeof u.key) { + case 'symbol': + case 'undefined': + case 'function': + case 'object': + u; // Symbol1 | Undefined1 | Function1 | Obejct1 + break; + default: + u; // Boolean1 | BigInt1 | Number1 | String1 + break; + } +} + +interface A { x: string, y: string }; +interface B { x: number, y: number }; +type X = A | B; + +function f3(bar: X) { + switch (typeof bar.x) { + case 'string': + let y = bar.y; // string + break; + default: + bar.y; + break; + } +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts new file mode 100644 index 0000000000000..2ce4135da4a78 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeep.ts @@ -0,0 +1,55 @@ +// @strict: true + +//// deep property access ---- a.b.c.d.e.f, a["b"]["c"]["d"] +//// mix deep property access ---- a.b["c"]["d"].e + +interface Foo1 { + firstKey: number, + inner: { + secondKey: number, + f1: number + } +} + +interface Foo2 { + firstKey: boolean, + inner: { + secondKey: boolean, + f2: number + } +} + +interface Foo3 { + firstKey: string; +} + +type Union = Foo1 | Foo2 | Foo3; + +function f(u: Union) { + if (typeof u.firstKey === "number" || typeof u.firstKey === "boolean") { + u; // Foo1 | Foo2 + if (typeof u.inner.secondKey === "boolean") { + u; // Foo2 + } + } +} + +type Union2 = Foo1 | Foo2; + +function f2(u: Union2) { + if (typeof u.inner["secondKey"] === "boolean") { + u; // Foo2 + } +} + +function f3(u: Union2) { + if (typeof u["inner"]["secondKey"] === "boolean") { + u; // Foo2 + } +} + +function f4(u: Union2) { + if (typeof u["inner"].secondKey === "boolean") { + u; // Foo2 + } +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeepBySwitch.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeepBySwitch.ts new file mode 100644 index 0000000000000..80ef4372c177a --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyDeepBySwitch.ts @@ -0,0 +1,49 @@ +// @strict: true + +interface Foo1 { + firstKey: number, + inner: { + secondKey: number, + f1: number + } +} + +interface Foo2 { + firstKey: boolean, + inner: { + secondKey: boolean, + f2: number + } +} + +interface Foo3 { + firstKey: string; +} + +type Union = Foo1 | Foo2 | Foo3; + +function f(u: Union) { + switch (typeof u.firstKey) { + case 'number': + case 'boolean': + u; + switch (typeof u.inner.secondKey) { + case 'boolean': + u; + } + } +} + +type Union2 = Foo1 | Foo2; + +// fall through +function f2(u: Union2) { + switch (typeof u.inner["secondKey"]) { + case 'boolean': + u; // never + case 'bigint': + u; // Foo2 + default: + u; // Union2 + } +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts new file mode 100644 index 0000000000000..80807e9498e41 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptional.ts @@ -0,0 +1,109 @@ +// @strict: true + + + +interface Foo1 { + key1: { + key2: number; + } | undefined; + f1: number; +} + +interface Foo2 { + key1: { + key2: string + } | undefined; + f2: number; +} + +interface Foo3 { + key1: { + key2: number; + }; + f2: number; +} +type U1 = Foo1 | Foo2 | Foo3; +type U2 = Foo1 | Foo2 | Foo3 | undefined; + + +// unnecessary optional chain +function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // Foo1 | Foo2 + } +} + +// non-root optional chain +function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 + } +} + +function f2Plus(u: U1) { + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + u; //should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; //should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } +} + +// root optional chain +function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; //U2 + } + if (typeof u?.key1 === 'number') { + u; //never + } + if (typeof u?.key1 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} + +// multi optional chain +function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof u?.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts new file mode 100644 index 0000000000000..42439ae11dfba --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardAccordingToPropertyOptionalBySwitch.ts @@ -0,0 +1,109 @@ +// @strict: true + + + +interface Foo1 { + key1: { + key2: number; + } | undefined; + f1: number; +} + +interface Foo2 { + key1: { + key2: string + } | undefined; + f2: number; +} + +interface Foo3 { + key1: { + key2: number; + }; + f2: number; +} +type U1 = Foo1 | Foo2 | Foo3; +type U2 = Foo1 | Foo2 | Foo3 | undefined; + + +// unnecessary optional chain +function f1(u: U1) { + if (typeof u?.key1 !== 'number') { + u; // U1 + } + if (typeof u?.key1 === 'number') { + u; // never + } + if (typeof u?.key1 !== 'undefined') { + u; // U1 + } + if (typeof u?.key1 === 'undefined') { + u; // Foo1 | Foo2 + } +} + +// non-root optional chain +function f2(u: U1) { + if (typeof u.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 + } + if (typeof u.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 + } +} + +function f2Plus(u: U1) { + if (typeof u.key1?.key2 === 'undefined' && typeof u.key1?.key2 === 'number') { + u; // should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'undefined' || typeof u.key1?.key2 === 'number') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' && typeof u.key1?.key2 === 'undefined') { + u; // should be never, but this should be a design limit? + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 === 'undefined') { + u; //U1 + } + if (typeof u.key1?.key2 === 'number' || typeof u.key1?.key2 !== 'undefined') { + u; //U1 + } +} + +// root optional chain +function f3(u: U2) { + if (typeof u?.key1 !== 'number') { + u; //U2 + } + if (typeof u?.key1 === 'number') { + u; //never + } + if (typeof u?.key1 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} + +// multi optional chain +function f4(u: U2) { + if (typeof u?.key1?.key2 !== 'number') { + u; //Foo1 | Foo2 | Undefined + } + if (typeof u?.key1?.key2 === 'number') { + u; //Foo1 | Foo3 + } + if (typeof u?.key1?.key2 !== 'undefined') { + u; //Foo1 | Foo2 | Foo3 + } + if (typeof u?.key1?.key2 === 'undefined') { + u; //Foo1 | Foo2 | Undefined + } +} diff --git a/tests/cases/conformance/types/union/discriminatedUnionTypes2.ts b/tests/cases/conformance/types/union/discriminatedUnionTypes2.ts index 6ef85b2406a51..b73fdb8f0ab83 100644 --- a/tests/cases/conformance/types/union/discriminatedUnionTypes2.ts +++ b/tests/cases/conformance/types/union/discriminatedUnionTypes2.ts @@ -131,7 +131,7 @@ function foo1(x: RuntimeValue & { type: 'number' }) { x.value; // number } else { - x.value; // number + x.value; // Error, x is never } } diff --git a/tests/cases/conformance/types/union/discriminatedUnionTypes3.ts b/tests/cases/conformance/types/union/discriminatedUnionTypes3.ts index a5e51271bc586..27cb072b605d7 100644 --- a/tests/cases/conformance/types/union/discriminatedUnionTypes3.ts +++ b/tests/cases/conformance/types/union/discriminatedUnionTypes3.ts @@ -1,5 +1,67 @@ // @strict: true +type A = { type2: "a", a: number } +type B = { type2: "b", b: number } +type C = { type2: "c", b: number | string } + +type X = { type1: A, x: string } +type Y = { type1: B, y: string } +type Z = { type1: C, z: string } +type W = { type1: undefined } + +function f32(x: X | Y) { + switch (x.type1.type2) { + case "a": + x.x // typeof x is X + break; + case "b": + x.y // typeof x is Y + break; + } +} + +function f33(x: A | B) { + switch (x.type2) { + case "a": + x // typeof x is X + break; + case "b": + x // typeof x is Y + break; + } +} + +function f34(x: X | Y) { + if (x.type1.type2 === "a") { + x.x // typeof x is X + } else if (x.type1.type2 === "b") { + x.y // typeof x is Y + } +} + +function f35(x: X | W) { + if (x.type1?.type2 === "a") { + x.x + } +} + +function f36(x: X | W) { + x.type1?.type2 ?? x; +} + +type S = { sub: { type0: X }, s: string } +type T = { sub: { type0: Y }, t: string } + +function f37(s: S | T) { + if (s.sub.type0.type1.type2 === "a") { + s.s // typeof s is S + s.sub.type0.x // type of s.sub.type is X + s.sub.type0.type1.a // type of s.sub.type.type is A + } else { + s.s // type error! + } +} + // Repro from #44435 type Correct = { @@ -16,4 +78,4 @@ const example: SomeReturnType = {} as SomeReturnType; if (example.err === undefined) { example.property; // true -} \ No newline at end of file +}