Input: Checks if source is related to target ( e . g . : is a assignable to ) . [CODESPLIT] function checkTypeRelatedTo ( source , target , relation , errorNode , headMessage , containingMessageChain ) { var errorInfo ; var sourceStack ; var targetStack ; var maybeStack ; var expandingFlags ; var depth = 0 ; var overflow = false ; var elaborateErrors = false ; ts . Debug . assert ( relation !== identityRelation || ! errorNode , "no error reporting in identity checking" ) ; var result = isRelatedTo ( source , target , errorNode !== undefined , headMessage ) ; if ( overflow ) { error ( errorNode , ts . Diagnostics . Excessive_stack_depth_comparing_types_0_and_1 , typeToString ( source ) , typeToString ( target ) ) ; } else if ( errorInfo ) { // If we already computed this relation, but in a context where we didn't want to report errors (e.g. overload resolution), // then we'll only have a top-level error (e.g. 'Class X does not implement interface Y') without any details. If this happened, // request a recompuation to get a complete error message. This will be skipped if we've already done this computation in a context // where errors were being reported. if ( errorInfo . next === undefined ) { errorInfo = undefined ; elaborateErrors = true ; isRelatedTo ( source , target , errorNode !== undefined , headMessage ) ; } if ( containingMessageChain ) { errorInfo = ts . concatenateDiagnosticMessageChains ( containingMessageChain , errorInfo ) ; } diagnostics . add ( ts . createDiagnosticForNodeFromMessageChain ( errorNode , errorInfo ) ) ; } return result !== 0 /* False */ ; function reportError ( message , arg0 , arg1 , arg2 ) { errorInfo = ts . chainDiagnosticMessages ( errorInfo , message , arg0 , arg1 , arg2 ) ; } function reportRelationError ( message , source , target ) { var sourceType = typeToString ( source ) ; var targetType = typeToString ( target ) ; if ( sourceType === targetType ) { sourceType = typeToString ( source , /*enclosingDeclaration*/ undefined , 128 /* UseFullyQualifiedType */ ) ; targetType = typeToString ( target , /*enclosingDeclaration*/ undefined , 128 /* UseFullyQualifiedType */ ) ; } reportError ( message || ts . Diagnostics . Type_0_is_not_assignable_to_type_1 , sourceType , targetType ) ; } // Compare two types and return // Ternary.True if they are related with no assumptions, // Ternary.Maybe if they are related with assumptions of other relationships, or // Ternary.False if they are not related. function isRelatedTo ( source , target , reportErrors , headMessage ) { var result ; // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if ( source === target ) return - 1 /* True */ ; if ( relation === identityRelation ) { return isIdenticalTo ( source , target ) ; } if ( isTypeAny ( target ) ) return - 1 /* True */ ; if ( source === undefinedType ) return - 1 /* True */ ; if ( source === nullType && target !== undefinedType ) return - 1 /* True */ ; if ( source . flags & 128 /* Enum */ && target === numberType ) return - 1 /* True */ ; if ( source . flags & 256 /* StringLiteral */ && target === stringType ) return - 1 /* True */ ; if ( relation === assignableRelation ) { if ( isTypeAny ( source ) ) return - 1 /* True */ ; if ( source === numberType && target . flags & 128 /* Enum */ ) return - 1 /* True */ ; } if ( source . flags & 1048576 /* FreshObjectLiteral */ ) { if ( hasExcessProperties ( source , target , reportErrors ) ) { if ( reportErrors ) { reportRelationError ( headMessage , source , target ) ; } return 0 /* False */ ; } // Above we check for excess properties with respect to the entire target type. When union // and intersection types are further deconstructed on the target side, we don't want to // make the check again (as it might fail for a partial target type). Therefore we obtain // the regular source type and proceed with that. if ( target . flags & 49152 /* UnionOrIntersection */ ) { source = getRegularTypeOfObjectLiteral ( source ) ; } } var saveErrorInfo = errorInfo ; // Note that the "each" checks must precede the "some" checks to produce the correct results if ( source . flags & 16384 /* Union */ ) { if ( result = eachTypeRelatedToType ( source , target , reportErrors ) ) { return result ; } } else if ( target . flags & 32768 /* Intersection */ ) { if ( result = typeRelatedToEachType ( source , target , reportErrors ) ) { return result ; } } else { // It is necessary to try "some" checks on both sides because there may be nested "each" checks // on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or // A & B = (A & B) | (C & D). if ( source . flags & 32768 /* Intersection */ ) { // If target is a union type the following check will report errors so we suppress them here if ( result = someTypeRelatedToType ( source , target , reportErrors && ! ( target . flags & 16384 /* Union */ ) ) ) { return result ; } } if ( target . flags & 16384 /* Union */ ) { if ( result = typeRelatedToSomeType ( source , target , reportErrors ) ) { return result ; } } } if ( source . flags & 512 /* TypeParameter */ ) { var constraint = getConstraintOfTypeParameter ( source ) ; if ( ! constraint || constraint . flags & 1 /* Any */ ) { constraint = emptyObjectType ; } // Report constraint errors only if the constraint is not the empty object type var reportConstraintErrors = reportErrors && constraint !== emptyObjectType ; if ( result = isRelatedTo ( constraint , target , reportConstraintErrors ) ) { errorInfo = saveErrorInfo ; return result ; } } else { if ( source . flags & 4096 /* Reference */ && target . flags & 4096 /* Reference */ && source . target === target . target ) { // We have type references to same target type, see if relationship holds for all type arguments if ( result = typeArgumentsRelatedTo ( source , target , reportErrors ) ) { return result ; } } // Even if relationship doesn't hold for unions, intersections, or generic type references, // it may hold in a structural comparison. var apparentType = getApparentType ( source ) ; // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates // to X. Failing both of those we want to check if the aggregation of A and B's members structurally // relates to X. Thus, we include intersection types on the source side here. if ( apparentType . flags & ( 80896 /* ObjectType */ | 32768 /* Intersection */ ) && target . flags & 80896 /* ObjectType */ ) { // Report structural errors only if we haven't reported any errors yet var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo ; if ( result = objectTypeRelatedTo ( apparentType , target , reportStructuralErrors ) ) { errorInfo = saveErrorInfo ; return result ; } } } if ( reportErrors ) { reportRelationError ( headMessage , source , target ) ; } return 0 /* False */ ; } function isIdenticalTo ( source , target ) { var result ; if ( source . flags & 80896 /* ObjectType */ && target . flags & 80896 /* ObjectType */ ) { if ( source . flags & 4096 /* Reference */ && target . flags & 4096 /* Reference */ && source . target === target . target ) { // We have type references to same target type, see if all type arguments are identical if ( result = typeArgumentsRelatedTo ( source , target , /*reportErrors*/ false ) ) { return result ; } } return objectTypeRelatedTo ( source , target , /*reportErrors*/ false ) ; } if ( source . flags & 512 /* TypeParameter */ && target . flags & 512 /* TypeParameter */ ) { return typeParameterIdenticalTo ( source , target ) ; } if ( source . flags & 16384 /* Union */ && target . flags & 16384 /* Union */ || source . flags & 32768 /* Intersection */ && target . flags & 32768 /* Intersection */ ) { if ( result = eachTypeRelatedToSomeType ( source , target ) ) { if ( result &= eachTypeRelatedToSomeType ( target , source ) ) { return result ; } } } return 0 /* False */ ; } // Check if a property with the given name is known anywhere in the given type. In an object type, a property // is considered known if the object type is empty and the check is for assignability, if the object type has // index signatures, or if the property is actually declared in the object type. In a union or intersection // type, a property is considered known if it is known in any constituent type. function isKnownProperty ( type , name ) { if ( type . flags & 80896 /* ObjectType */ ) { var resolved = resolveStructuredTypeMembers ( type ) ; if ( relation === assignableRelation && ( type === globalObjectType || resolved . properties . length === 0 ) || resolved . stringIndexType || resolved . numberIndexType || getPropertyOfType ( type , name ) ) { return true ; } return false ; } if ( type . flags & 49152 /* UnionOrIntersection */ ) { for ( var _i = 0 , _a = type . types ; _i < _a . length ; _i ++ ) { var t = _a [ _i ] ; if ( isKnownProperty ( t , name ) ) { return true ; } } return false ; } return true ; } function hasExcessProperties ( source , target , reportErrors ) { for ( var _i = 0 , _a = getPropertiesOfObjectType ( source ) ; _i < _a . length ; _i ++ ) { var prop = _a [ _i ] ; if ( ! isKnownProperty ( target , prop . name ) ) { if ( reportErrors ) { // We know *exactly* where things went wrong when comparing the types. // Use this property as the error node as this will be more helpful in // reasoning about what went wrong. errorNode = prop . valueDeclaration ; reportError ( ts . Diagnostics . Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1 , symbolToString ( prop ) , typeToString ( target ) ) ; } return true ; } } } function eachTypeRelatedToSomeType ( source , target ) { var result = - 1 /* True */ ; var sourceTypes = source . types ; for ( var _i = 0 ; _i < sourceTypes . length ; _i ++ ) { var sourceType = sourceTypes [ _i ] ; var related = typeRelatedToSomeType ( sourceType , target , false ) ; if ( ! related ) { return 0 /* False */ ; } result &= related ; } return result ; } function typeRelatedToSomeType ( source , target , reportErrors ) { var targetTypes = target . types ; for ( var i = 0 , len = targetTypes . length ; i < len ; i ++ ) { var related = isRelatedTo ( source , targetTypes [ i ] , reportErrors && i === len - 1 ) ; if ( related ) { return related ; } } return 0 /* False */ ; } function typeRelatedToEachType ( source , target , reportErrors ) { var result = - 1 /* True */ ; var targetTypes = target . types ; for ( var _i = 0 ; _i < targetTypes . length ; _i ++ ) { var targetType = targetTypes [ _i ] ; var related = isRelatedTo ( source , targetType , reportErrors ) ; if ( ! related ) { return 0 /* False */ ; } result &= related ; } return result ; } function someTypeRelatedToType ( source , target , reportErrors ) { var sourceTypes = source . types ; for ( var i = 0 , len = sourceTypes . length ; i < len ; i ++ ) { var related = isRelatedTo ( sourceTypes [ i ] , target , reportErrors && i === len - 1 ) ; if ( related ) { return related ; } } return 0 /* False */ ; } function eachTypeRelatedToType ( source , target , reportErrors ) { var result = - 1 /* True */ ; var sourceTypes = source . types ; for ( var _i = 0 ; _i < sourceTypes . length ; _i ++ ) { var sourceType = sourceTypes [ _i ] ; var related = isRelatedTo ( sourceType , target , reportErrors ) ; if ( ! related ) { return 0 /* False */ ; } result &= related ; } return result ; } function typeArgumentsRelatedTo ( source , target , reportErrors ) { var sources = source . typeArguments || emptyArray ; var targets = target . typeArguments || emptyArray ; if ( sources . length !== targets . length && relation === identityRelation ) { return 0 /* False */ ; } var result = - 1 /* True */ ; for ( var i = 0 ; i < targets . length ; i ++ ) { var related = isRelatedTo ( sources [ i ] , targets [ i ] , reportErrors ) ; if ( ! related ) { return 0 /* False */ ; } result &= related ; } return result ; } function typeParameterIdenticalTo ( source , target ) { if ( source . symbol . name !== target . symbol . name ) { return 0 /* False */ ; } // covers case when both type parameters does not have constraint (both equal to noConstraintType) if ( source . constraint === target . constraint ) { return - 1 /* True */ ; } if ( source . constraint === noConstraintType || target . constraint === noConstraintType ) { return 0 /* False */ ; } return isIdenticalTo ( source . constraint , target . constraint ) ; } // Determine if two object types are related by structure. First, check if the result is already available in the global cache. // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true. // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion // and issue an error. Otherwise, actually compare the structure of the two types. function objectTypeRelatedTo ( source , target , reportErrors ) { if ( overflow ) { return 0 /* False */ ; } var id = relation !== identityRelation || source . id < target . id ? source . id + "," + target . id : target . id + "," + source . id ; var related = relation [ id ] ; if ( related !== undefined ) { // If we computed this relation already and it was failed and reported, or if we're not being asked to elaborate // errors, we can use the cached value. Otherwise, recompute the relation if ( ! elaborateErrors || ( related === 3 /* FailedAndReported */ ) ) { return related === 1 /* Succeeded */ ? - 1 /* True */ : 0 /* False */ ; } } if ( depth > 0 ) { for ( var i = 0 ; i < depth ; i ++ ) { // If source and target are already being compared, consider them related with assumptions if ( maybeStack [ i ] [ id ] ) { return 1 /* Maybe */ ; } } if ( depth === 100 ) { overflow = true ; return 0 /* False */ ; } } else { sourceStack = [ ] ; targetStack = [ ] ; maybeStack = [ ] ; expandingFlags = 0 ; } sourceStack [ depth ] = source ; targetStack [ depth ] = target ; maybeStack [ depth ] = { } ; maybeStack [ depth ] [ id ] = 1 /* Succeeded */ ; depth ++ ; var saveExpandingFlags = expandingFlags ; if ( ! ( expandingFlags & 1 ) && isDeeplyNestedGeneric ( source , sourceStack , depth ) ) expandingFlags |= 1 ; if ( ! ( expandingFlags & 2 ) && isDeeplyNestedGeneric ( target , targetStack , depth ) ) expandingFlags |= 2 ; var result ; if ( expandingFlags === 3 ) { result = 1 /* Maybe */ ; } else { result = propertiesRelatedTo ( source , target , reportErrors ) ; if ( result ) { result &= signaturesRelatedTo ( source , target , 0 /* Call */ , reportErrors ) ; if ( result ) { result &= signaturesRelatedTo ( source , target , 1 /* Construct */ , reportErrors ) ; if ( result ) { result &= stringIndexTypesRelatedTo ( source , target , reportErrors ) ; if ( result ) { result &= numberIndexTypesRelatedTo ( source , target , reportErrors ) ; } } } } } expandingFlags = saveExpandingFlags ; depth -- ; if ( result ) { var maybeCache = maybeStack [ depth ] ; // If result is definitely true, copy assumptions to global cache, else copy to next level up var destinationCache = ( result === - 1 /* True */ || depth === 0 ) ? relation : maybeStack [ depth - 1 ] ; ts . copyMap ( maybeCache , destinationCache ) ; } else { // A false result goes straight into global cache (when something is false under assumptions it // will also be false without assumptions) relation [ id ] = reportErrors ? 3 /* FailedAndReported */ : 2 /* Failed */ ; } return result ; } function propertiesRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { return propertiesIdenticalTo ( source , target ) ; } var result = - 1 /* True */ ; var properties = getPropertiesOfObjectType ( target ) ; var requireOptionalProperties = relation === subtypeRelation && ! ( source . flags & 524288 /* ObjectLiteral */ ) ; for ( var _i = 0 ; _i < properties . length ; _i ++ ) { var targetProp = properties [ _i ] ; var sourceProp = getPropertyOfType ( source , targetProp . name ) ; if ( sourceProp !== targetProp ) { if ( ! sourceProp ) { if ( ! ( targetProp . flags & 536870912 /* Optional */ ) || requireOptionalProperties ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Property_0_is_missing_in_type_1 , symbolToString ( targetProp ) , typeToString ( source ) ) ; } return 0 /* False */ ; } } else if ( ! ( targetProp . flags & 134217728 /* Prototype */ ) ) { var sourcePropFlags = getDeclarationFlagsFromSymbol ( sourceProp ) ; var targetPropFlags = getDeclarationFlagsFromSymbol ( targetProp ) ; if ( sourcePropFlags & 32 /* Private */ || targetPropFlags & 32 /* Private */ ) { if ( sourceProp . valueDeclaration !== targetProp . valueDeclaration ) { if ( reportErrors ) { if ( sourcePropFlags & 32 /* Private */ && targetPropFlags & 32 /* Private */ ) { reportError ( ts . Diagnostics . Types_have_separate_declarations_of_a_private_property_0 , symbolToString ( targetProp ) ) ; } else { reportError ( ts . Diagnostics . Property_0_is_private_in_type_1_but_not_in_type_2 , symbolToString ( targetProp ) , typeToString ( sourcePropFlags & 32 /* Private */ ? source : target ) , typeToString ( sourcePropFlags & 32 /* Private */ ? target : source ) ) ; } } return 0 /* False */ ; } } else if ( targetPropFlags & 64 /* Protected */ ) { var sourceDeclaredInClass = sourceProp . parent && sourceProp . parent . flags & 32 /* Class */ ; var sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol ( sourceProp . parent ) : undefined ; var targetClass = getDeclaredTypeOfSymbol ( targetProp . parent ) ; if ( ! sourceClass || ! hasBaseType ( sourceClass , targetClass ) ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2 , symbolToString ( targetProp ) , typeToString ( sourceClass || source ) , typeToString ( targetClass ) ) ; } return 0 /* False */ ; } } else if ( sourcePropFlags & 64 /* Protected */ ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Property_0_is_protected_in_type_1_but_public_in_type_2 , symbolToString ( targetProp ) , typeToString ( source ) , typeToString ( target ) ) ; } return 0 /* False */ ; } var related = isRelatedTo ( getTypeOfSymbol ( sourceProp ) , getTypeOfSymbol ( targetProp ) , reportErrors ) ; if ( ! related ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Types_of_property_0_are_incompatible , symbolToString ( targetProp ) ) ; } return 0 /* False */ ; } result &= related ; if ( sourceProp . flags & 536870912 /* Optional */ && ! ( targetProp . flags & 536870912 /* Optional */ ) ) { // TypeScript 1.0 spec (April 2014): 3.8.3 // S is a subtype of a type T, and T is a supertype of S if ... // S' and T are object types and, for each member M in T.. // M is a property and S' contains a property N where // if M is a required property, N is also a required property // (M - property in T) // (N - property in S) if ( reportErrors ) { reportError ( ts . Diagnostics . Property_0_is_optional_in_type_1_but_required_in_type_2 , symbolToString ( targetProp ) , typeToString ( source ) , typeToString ( target ) ) ; } return 0 /* False */ ; } } } } return result ; } function propertiesIdenticalTo ( source , target ) { if ( ! ( source . flags & 80896 /* ObjectType */ && target . flags & 80896 /* ObjectType */ ) ) { return 0 /* False */ ; } var sourceProperties = getPropertiesOfObjectType ( source ) ; var targetProperties = getPropertiesOfObjectType ( target ) ; if ( sourceProperties . length !== targetProperties . length ) { return 0 /* False */ ; } var result = - 1 /* True */ ; for ( var _i = 0 ; _i < sourceProperties . length ; _i ++ ) { var sourceProp = sourceProperties [ _i ] ; var targetProp = getPropertyOfObjectType ( target , sourceProp . name ) ; if ( ! targetProp ) { return 0 /* False */ ; } var related = compareProperties ( sourceProp , targetProp , isRelatedTo ) ; if ( ! related ) { return 0 /* False */ ; } result &= related ; } return result ; } function signaturesRelatedTo ( source , target , kind , reportErrors ) { if ( relation === identityRelation ) { return signaturesIdenticalTo ( source , target , kind ) ; } if ( target === anyFunctionType || source === anyFunctionType ) { return - 1 /* True */ ; } var sourceSignatures = getSignaturesOfType ( source , kind ) ; var targetSignatures = getSignaturesOfType ( target , kind ) ; var result = - 1 /* True */ ; var saveErrorInfo = errorInfo ; if ( kind === 1 /* Construct */ ) { // Only want to compare the construct signatures for abstractness guarantees. // Because the "abstractness" of a class is the same across all construct signatures // (internally we are checking the corresponding declaration), it is enough to perform // the check and report an error once over all pairs of source and target construct signatures. // // sourceSig and targetSig are (possibly) undefined. // // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. var sourceSig = sourceSignatures [ 0 ] ; var targetSig = targetSignatures [ 0 ] ; result &= abstractSignatureRelatedTo ( source , sourceSig , target , targetSig ) ; if ( result !== - 1 /* True */ ) { return result ; } } outer : for ( var _i = 0 ; _i < targetSignatures . length ; _i ++ ) { var t = targetSignatures [ _i ] ; if ( ! t . hasStringLiterals || target . flags & 262144 /* FromSignature */ ) { var localErrors = reportErrors ; var checkedAbstractAssignability = false ; for ( var _a = 0 ; _a < sourceSignatures . length ; _a ++ ) { var s = sourceSignatures [ _a ] ; if ( ! s . hasStringLiterals || source . flags & 262144 /* FromSignature */ ) { var related = signatureRelatedTo ( s , t , localErrors ) ; if ( related ) { result &= related ; errorInfo = saveErrorInfo ; continue outer ; } // Only report errors from the first failure localErrors = false ; } } return 0 /* False */ ; } } return result ; function abstractSignatureRelatedTo ( source , sourceSig , target , targetSig ) { if ( sourceSig && targetSig ) { var sourceDecl = source . symbol && getClassLikeDeclarationOfSymbol ( source . symbol ) ; var targetDecl = target . symbol && getClassLikeDeclarationOfSymbol ( target . symbol ) ; if ( ! sourceDecl ) { // If the source object isn't itself a class declaration, it can be freely assigned, regardless // of whether the constructed object is abstract or not. return - 1 /* True */ ; } var sourceErasedSignature = getErasedSignature ( sourceSig ) ; var targetErasedSignature = getErasedSignature ( targetSig ) ; var sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature ( sourceErasedSignature ) ; var targetReturnType = targetErasedSignature && getReturnTypeOfSignature ( targetErasedSignature ) ; var sourceReturnDecl = sourceReturnType && sourceReturnType . symbol && getClassLikeDeclarationOfSymbol ( sourceReturnType . symbol ) ; var targetReturnDecl = targetReturnType && targetReturnType . symbol && getClassLikeDeclarationOfSymbol ( targetReturnType . symbol ) ; var sourceIsAbstract = sourceReturnDecl && sourceReturnDecl . flags & 256 /* Abstract */ ; var targetIsAbstract = targetReturnDecl && targetReturnDecl . flags & 256 /* Abstract */ ; if ( sourceIsAbstract && ! ( targetIsAbstract && targetDecl ) ) { // if target isn't a class-declaration type, then it can be new'd, so we forbid the assignment. if ( reportErrors ) { reportError ( ts . Diagnostics . Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type ) ; } return 0 /* False */ ; } } return - 1 /* True */ ; } } function signatureRelatedTo ( source , target , reportErrors ) { if ( source === target ) { return - 1 /* True */ ; } if ( ! target . hasRestParameter && source . minArgumentCount > target . parameters . length ) { return 0 /* False */ ; } var sourceMax = source . parameters . length ; var targetMax = target . parameters . length ; var checkCount ; if ( source . hasRestParameter && target . hasRestParameter ) { checkCount = sourceMax > targetMax ? sourceMax : targetMax ; sourceMax -- ; targetMax -- ; } else if ( source . hasRestParameter ) { sourceMax -- ; checkCount = targetMax ; } else if ( target . hasRestParameter ) { targetMax -- ; checkCount = sourceMax ; } else { checkCount = sourceMax < targetMax ? sourceMax : targetMax ; } // Spec 1.0 Section 3.8.3 & 3.8.4: // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N source = getErasedSignature ( source ) ; target = getErasedSignature ( target ) ; var result = - 1 /* True */ ; for ( var i = 0 ; i < checkCount ; i ++ ) { var s = i < sourceMax ? getTypeOfSymbol ( source . parameters [ i ] ) : getRestTypeOfSignature ( source ) ; var t = i < targetMax ? getTypeOfSymbol ( target . parameters [ i ] ) : getRestTypeOfSignature ( target ) ; var saveErrorInfo = errorInfo ; var related = isRelatedTo ( s , t , reportErrors ) ; if ( ! related ) { related = isRelatedTo ( t , s , false ) ; if ( ! related ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Types_of_parameters_0_and_1_are_incompatible , source . parameters [ i < sourceMax ? i : sourceMax ] . name , target . parameters [ i < targetMax ? i : targetMax ] . name ) ; } return 0 /* False */ ; } errorInfo = saveErrorInfo ; } result &= related ; } if ( source . typePredicate && target . typePredicate ) { var hasDifferentParameterIndex = source . typePredicate . parameterIndex !== target . typePredicate . parameterIndex ; var hasDifferentTypes ; if ( hasDifferentParameterIndex || ( hasDifferentTypes = ! isTypeIdenticalTo ( source . typePredicate . type , target . typePredicate . type ) ) ) { if ( reportErrors ) { var sourceParamText = source . typePredicate . parameterName ; var targetParamText = target . typePredicate . parameterName ; var sourceTypeText = typeToString ( source . typePredicate . type ) ; var targetTypeText = typeToString ( target . typePredicate . type ) ; if ( hasDifferentParameterIndex ) { reportError ( ts . Diagnostics . Parameter_0_is_not_in_the_same_position_as_parameter_1 , sourceParamText , targetParamText ) ; } else if ( hasDifferentTypes ) { reportError ( ts . Diagnostics . Type_0_is_not_assignable_to_type_1 , sourceTypeText , targetTypeText ) ; } reportError ( ts . Diagnostics . Type_predicate_0_is_not_assignable_to_1 , sourceParamText + " is " + sourceTypeText , targetParamText + " is " + targetTypeText ) ; } return 0 /* False */ ; } } else if ( ! source . typePredicate && target . typePredicate ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Signature_0_must_have_a_type_predicate , signatureToString ( source ) ) ; } return 0 /* False */ ; } var targetReturnType = getReturnTypeOfSignature ( target ) ; if ( targetReturnType === voidType ) return result ; var sourceReturnType = getReturnTypeOfSignature ( source ) ; return result & isRelatedTo ( sourceReturnType , targetReturnType , reportErrors ) ; } function signaturesIdenticalTo ( source , target , kind ) { var sourceSignatures = getSignaturesOfType ( source , kind ) ; var targetSignatures = getSignaturesOfType ( target , kind ) ; if ( sourceSignatures . length !== targetSignatures . length ) { return 0 /* False */ ; } var result = - 1 /* True */ ; for ( var i = 0 , len = sourceSignatures . length ; i < len ; ++ i ) { var related = compareSignatures ( sourceSignatures [ i ] , targetSignatures [ i ] , /*partialMatch*/ false , /*ignoreReturnTypes*/ false , isRelatedTo ) ; if ( ! related ) { return 0 /* False */ ; } result &= related ; } return result ; } function stringIndexTypesRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { return indexTypesIdenticalTo ( 0 /* String */ , source , target ) ; } var targetType = getIndexTypeOfType ( target , 0 /* String */ ) ; if ( targetType && ! ( targetType . flags & 1 /* Any */ ) ) { var sourceType = getIndexTypeOfType ( source , 0 /* String */ ) ; if ( ! sourceType ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Index_signature_is_missing_in_type_0 , typeToString ( source ) ) ; } return 0 /* False */ ; } var related = isRelatedTo ( sourceType , targetType , reportErrors ) ; if ( ! related ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Index_signatures_are_incompatible ) ; } return 0 /* False */ ; } return related ; } return - 1 /* True */ ; } function numberIndexTypesRelatedTo ( source , target , reportErrors ) { if ( relation === identityRelation ) { return indexTypesIdenticalTo ( 1 /* Number */ , source , target ) ; } var targetType = getIndexTypeOfType ( target , 1 /* Number */ ) ; if ( targetType && ! ( targetType . flags & 1 /* Any */ ) ) { var sourceStringType = getIndexTypeOfType ( source , 0 /* String */ ) ; var sourceNumberType = getIndexTypeOfType ( source , 1 /* Number */ ) ; if ( ! ( sourceStringType || sourceNumberType ) ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Index_signature_is_missing_in_type_0 , typeToString ( source ) ) ; } return 0 /* False */ ; } var related ; if ( sourceStringType && sourceNumberType ) { // If we know for sure we're testing both string and numeric index types then only report errors from the second one related = isRelatedTo ( sourceStringType , targetType , false ) || isRelatedTo ( sourceNumberType , targetType , reportErrors ) ; } else { related = isRelatedTo ( sourceStringType || sourceNumberType , targetType , reportErrors ) ; } if ( ! related ) { if ( reportErrors ) { reportError ( ts . Diagnostics . Index_signatures_are_incompatible ) ; } return 0 /* False */ ; } return related ; } return - 1 /* True */ ; } function indexTypesIdenticalTo ( indexKind , source , target ) { var targetType = getIndexTypeOfType ( target , indexKind ) ; var sourceType = getIndexTypeOfType ( source , indexKind ) ; if ( ! sourceType && ! targetType ) { return - 1 /* True */ ; } if ( sourceType && targetType ) { return isRelatedTo ( sourceType , targetType ) ; } return 0 /* False */ ; } }


Input: Compare two types and return Ternary . True if they are related with no assumptions Ternary . Maybe if they are related with assumptions of other relationships or Ternary . False if they are not related . [CODESPLIT] function isRelatedTo ( source , target , reportErrors , headMessage ) { var result ; // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if ( source === target ) return - 1 /* True */ ; if ( relation === identityRelation ) { return isIdenticalTo ( source , target ) ; } if ( isTypeAny ( target ) ) return - 1 /* True */ ; if ( source === undefinedType ) return - 1 /* True */ ; if ( source === nullType && target !== undefinedType ) return - 1 /* True */ ; if ( source . flags & 128 /* Enum */ && target === numberType ) return - 1 /* True */ ; if ( source . flags & 256 /* StringLiteral */ && target === stringType ) return - 1 /* True */ ; if ( relation === assignableRelation ) { if ( isTypeAny ( source ) ) return - 1 /* True */ ; if ( source === numberType && target . flags & 128 /* Enum */ ) return - 1 /* True */ ; } if ( source . flags & 1048576 /* FreshObjectLiteral */ ) { if ( hasExcessProperties ( source , target , reportErrors ) ) { if ( reportErrors ) { reportRelationError ( headMessage , source , target ) ; } return 0 /* False */ ; } // Above we check for excess properties with respect to the entire target type. When union // and intersection types are further deconstructed on the target side, we don't want to // make the check again (as it might fail for a partial target type). Therefore we obtain // the regular source type and proceed with that. if ( target . flags & 49152 /* UnionOrIntersection */ ) { source = getRegularTypeOfObjectLiteral ( source ) ; } } var saveErrorInfo = errorInfo ; // Note that the "each" checks must precede the "some" checks to produce the correct results if ( source . flags & 16384 /* Union */ ) { if ( result = eachTypeRelatedToType ( source , target , reportErrors ) ) { return result ; } } else if ( target . flags & 32768 /* Intersection */ ) { if ( result = typeRelatedToEachType ( source , target , reportErrors ) ) { return result ; } } else { // It is necessary to try "some" checks on both sides because there may be nested "each" checks // on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or // A & B = (A & B) | (C & D). if ( source . flags & 32768 /* Intersection */ ) { // If target is a union type the following check will report errors so we suppress them here if ( result = someTypeRelatedToType ( source , target , reportErrors && ! ( target . flags & 16384 /* Union */ ) ) ) { return result ; } } if ( target . flags & 16384 /* Union */ ) { if ( result = typeRelatedToSomeType ( source , target , reportErrors ) ) { return result ; } } } if ( source . flags & 512 /* TypeParameter */ ) { var constraint = getConstraintOfTypeParameter ( source ) ; if ( ! constraint || constraint . flags & 1 /* Any */ ) { constraint = emptyObjectType ; } // Report constraint errors only if the constraint is not the empty object type var reportConstraintErrors = reportErrors && constraint !== emptyObjectType ; if ( result = isRelatedTo ( constraint , target , reportConstraintErrors ) ) { errorInfo = saveErrorInfo ; return result ; } } else { if ( source . flags & 4096 /* Reference */ && target . flags & 4096 /* Reference */ && source . target === target . target ) { // We have type references to same target type, see if relationship holds for all type arguments if ( result = typeArgumentsRelatedTo ( source , target , reportErrors ) ) { return result ; } } // Even if relationship doesn't hold for unions, intersections, or generic type references, // it may hold in a structural comparison. var apparentType = getApparentType ( source ) ; // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates // to X. Failing both of those we want to check if the aggregation of A and B's members structurally // relates to X. Thus, we include intersection types on the source side here. if ( apparentType . flags & ( 80896 /* ObjectType */ | 32768 /* Intersection */ ) && target . flags & 80896 /* ObjectType */ ) { // Report structural errors only if we haven't reported any errors yet var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo ; if ( result = objectTypeRelatedTo ( apparentType , target , reportStructuralErrors ) ) { errorInfo = saveErrorInfo ; return result ; } } } if ( reportErrors ) { reportRelationError ( headMessage , source , target ) ; } return 0 /* False */ ; }


Input: Check if a property with the given name is known anywhere in the given type . In an object type a property is considered known if the object type is empty and the check is for assignability if the object type has index signatures or if the property is actually declared in the object type . In a union or intersection type a property is considered known if it is known in any constituent type . [CODESPLIT] function isKnownProperty ( type , name ) { if ( type . flags & 80896 /* ObjectType */ ) { var resolved = resolveStructuredTypeMembers ( type ) ; if ( relation === assignableRelation && ( type === globalObjectType || resolved . properties . length === 0 ) || resolved . stringIndexType || resolved . numberIndexType || getPropertyOfType ( type , name ) ) { return true ; } return false ; } if ( type . flags & 49152 /* UnionOrIntersection */ ) { for ( var _i = 0 , _a = type . types ; _i < _a . length ; _i ++ ) { var t = _a [ _i ] ; if ( isKnownProperty ( t , name ) ) { return true ; } } return false ; } return true ; }


Input: Determine if two object types are related by structure . First check if the result is already available in the global cache . Second check if we have already started a comparison of the given two types in which case we assume the result to be true . Third check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are equal and infinitely expanding . Fourth if we have reached a depth of 100 nested comparisons assume we have runaway recursion and issue an error . Otherwise actually compare the structure of the two types . [CODESPLIT] function objectTypeRelatedTo ( source , target , reportErrors ) { if ( overflow ) { return 0 /* False */ ; } var id = relation !== identityRelation || source . id < target . id ? source . id + "," + target . id : target . id + "," + source . id ; var related = relation [ id ] ; if ( related !== undefined ) { // If we computed this relation already and it was failed and reported, or if we're not being asked to elaborate // errors, we can use the cached value. Otherwise, recompute the relation if ( ! elaborateErrors || ( related === 3 /* FailedAndReported */ ) ) { return related === 1 /* Succeeded */ ? - 1 /* True */ : 0 /* False */ ; } } if ( depth > 0 ) { for ( var i = 0 ; i < depth ; i ++ ) { // If source and target are already being compared, consider them related with assumptions if ( maybeStack [ i ] [ id ] ) { return 1 /* Maybe */ ; } } if ( depth === 100 ) { overflow = true ; return 0 /* False */ ; } } else { sourceStack = [ ] ; targetStack = [ ] ; maybeStack = [ ] ; expandingFlags = 0 ; } sourceStack [ depth ] = source ; targetStack [ depth ] = target ; maybeStack [ depth ] = { } ; maybeStack [ depth ] [ id ] = 1 /* Succeeded */ ; depth ++ ; var saveExpandingFlags = expandingFlags ; if ( ! ( expandingFlags & 1 ) && isDeeplyNestedGeneric ( source , sourceStack , depth ) ) expandingFlags |= 1 ; if ( ! ( expandingFlags & 2 ) && isDeeplyNestedGeneric ( target , targetStack , depth ) ) expandingFlags |= 2 ; var result ; if ( expandingFlags === 3 ) { result = 1 /* Maybe */ ; } else { result = propertiesRelatedTo ( source , target , reportErrors ) ; if ( result ) { result &= signaturesRelatedTo ( source , target , 0 /* Call */ , reportErrors ) ; if ( result ) { result &= signaturesRelatedTo ( source , target , 1 /* Construct */ , reportErrors ) ; if ( result ) { result &= stringIndexTypesRelatedTo ( source , target , reportErrors ) ; if ( result ) { result &= numberIndexTypesRelatedTo ( source , target , reportErrors ) ; } } } } } expandingFlags = saveExpandingFlags ; depth -- ; if ( result ) { var maybeCache = maybeStack [ depth ] ; // If result is definitely true, copy assumptions to global cache, else copy to next level up var destinationCache = ( result === - 1 /* True */ || depth === 0 ) ? relation : maybeStack [ depth - 1 ] ; ts . copyMap ( maybeCache , destinationCache ) ; } else { // A false result goes straight into global cache (when something is false under assumptions it // will also be false without assumptions) relation [ id ] = reportErrors ? 3 /* FailedAndReported */ : 2 /* Failed */ ; } return result ; }


Input: Return true if the given type is part of a deeply nested chain of generic instantiations . We consider this to be the case when structural type comparisons have been started for 10 or more instantiations of the same generic type . It is possible though highly unlikely for this test to be true in a situation where a chain of instantiations is not infinitely expanding . Effectively we will generate a false positive when two types are structurally equal to at least 10 levels but unequal at some level beyond that . [CODESPLIT] function isDeeplyNestedGeneric ( type , stack , depth ) { // We track type references (created by createTypeReference) and instantiated types (created by instantiateType) if ( type . flags & ( 4096 /* Reference */ | 131072 /* Instantiated */ ) && depth >= 5 ) { var symbol = type . symbol ; var count = 0 ; for ( var i = 0 ; i < depth ; i ++ ) { var t = stack [ i ] ; if ( t . flags & ( 4096 /* Reference */ | 131072 /* Instantiated */ ) && t . symbol === symbol ) { count ++ ; if ( count >= 5 ) return true ; } } } return false ; }


Input: For a union type remove all constituent types that are of the given type kind ( when isOfTypeKind is true ) or not of the given type kind ( when isOfTypeKind is false ) [CODESPLIT] function removeTypesFromUnionType ( type , typeKind , isOfTypeKind , allowEmptyUnionResult ) { if ( type . flags & 16384 /* Union */ ) { var types = type . types ; if ( ts . forEach ( types , function ( t ) { return ! ! ( t . flags & typeKind ) === isOfTypeKind ; } ) ) { // Above we checked if we have anything to remove, now use the opposite test to do the removal var narrowedType = getUnionType ( ts . filter ( types , function ( t ) { return ! ( t . flags & typeKind ) === isOfTypeKind ; } ) ) ; if ( allowEmptyUnionResult || narrowedType !== emptyObjectType ) { return narrowedType ; } } } else if ( allowEmptyUnionResult && ! ! ( type . flags & typeKind ) === isOfTypeKind ) { // Use getUnionType(emptyArray) instead of emptyObjectType in case the way empty union types // are represented ever changes. return getUnionType ( emptyArray ) ; } return type ; }


Input: Check if a given variable is assigned within a given syntax node [CODESPLIT] function isVariableAssignedWithin ( symbol , node ) { var links = getNodeLinks ( node ) ; if ( links . assignmentChecks ) { var cachedResult = links . assignmentChecks [ symbol . id ] ; if ( cachedResult !== undefined ) { return cachedResult ; } } else { links . assignmentChecks = { } ; } return links . assignmentChecks [ symbol . id ] = isAssignedIn ( node ) ; function isAssignedInBinaryExpression ( node ) { if ( node . operatorToken . kind >= 56 /* FirstAssignment */ && node . operatorToken . kind <= 68 /* LastAssignment */ ) { var n = node . left ; while ( n . kind === 172 /* ParenthesizedExpression */ ) { n = n . expression ; } if ( n . kind === 69 /* Identifier */ && getResolvedSymbol ( n ) === symbol ) { return true ; } } return ts . forEachChild ( node , isAssignedIn ) ; } function isAssignedInVariableDeclaration ( node ) { if ( ! ts . isBindingPattern ( node . name ) && getSymbolOfNode ( node ) === symbol && hasInitializer ( node ) ) { return true ; } return ts . forEachChild ( node , isAssignedIn ) ; } function isAssignedIn ( node ) { switch ( node . kind ) { case 181 /* BinaryExpression */ : return isAssignedInBinaryExpression ( node ) ; case 211 /* VariableDeclaration */ : case 163 /* BindingElement */ : return isAssignedInVariableDeclaration ( node ) ; case 161 /* ObjectBindingPattern */ : case 162 /* ArrayBindingPattern */ : case 164 /* ArrayLiteralExpression */ : case 165 /* ObjectLiteralExpression */ : case 166 /* PropertyAccessExpression */ : case 167 /* ElementAccessExpression */ : case 168 /* CallExpression */ : case 169 /* NewExpression */ : case 171 /* TypeAssertionExpression */ : case 189 /* AsExpression */ : case 172 /* ParenthesizedExpression */ : case 179 /* PrefixUnaryExpression */ : case 175 /* DeleteExpression */ : case 178 /* AwaitExpression */ : case 176 /* TypeOfExpression */ : case 177 /* VoidExpression */ : case 180 /* PostfixUnaryExpression */ : case 184 /* YieldExpression */ : case 182 /* ConditionalExpression */ : case 185 /* SpreadElementExpression */ : case 192 /* Block */ : case 193 /* VariableStatement */ : case 195 /* ExpressionStatement */ : case 196 /* IfStatement */ : case 197 /* DoStatement */ : case 198 /* WhileStatement */ : case 199 /* ForStatement */ : case 200 /* ForInStatement */ : case 201 /* ForOfStatement */ : case 204 /* ReturnStatement */ : case 205 /* WithStatement */ : case 206 /* SwitchStatement */ : case 241 /* CaseClause */ : case 242 /* DefaultClause */ : case 207 /* LabeledStatement */ : case 208 /* ThrowStatement */ : case 209 /* TryStatement */ : case 244 /* CatchClause */ : case 233 /* JsxElement */ : case 234 /* JsxSelfClosingElement */ : case 238 /* JsxAttribute */ : case 239 /* JsxSpreadAttribute */ : case 235 /* JsxOpeningElement */ : case 240 /* JsxExpression */ : return ts . forEachChild ( node , isAssignedIn ) ; } return false ; } }


Input: Get the narrowed type of a given symbol at a given location [CODESPLIT] function getNarrowedTypeOfSymbol ( symbol , node ) { var type = getTypeOfSymbol ( symbol ) ; // Only narrow when symbol is variable of type any or an object, union, or type parameter type if ( node && symbol . flags & 3 /* Variable */ ) { if ( isTypeAny ( type ) || type . flags & ( 80896 /* ObjectType */ | 16384 /* Union */ | 512 /* TypeParameter */ ) ) { loop : while ( node . parent ) { var child = node ; node = node . parent ; var narrowedType = type ; switch ( node . kind ) { case 196 /* IfStatement */ : // In a branch of an if statement, narrow based on controlling expression if ( child !== node . expression ) { narrowedType = narrowType ( type , node . expression , /*assumeTrue*/ child === node . thenStatement ) ; } break ; case 182 /* ConditionalExpression */ : // In a branch of a conditional expression, narrow based on controlling condition if ( child !== node . condition ) { narrowedType = narrowType ( type , node . condition , /*assumeTrue*/ child === node . whenTrue ) ; } break ; case 181 /* BinaryExpression */ : // In the right operand of an && or ||, narrow based on left operand if ( child === node . right ) { if ( node . operatorToken . kind === 51 /* AmpersandAmpersandToken */ ) { narrowedType = narrowType ( type , node . left , /*assumeTrue*/ true ) ; } else if ( node . operatorToken . kind === 52 /* BarBarToken */ ) { narrowedType = narrowType ( type , node . left , /*assumeTrue*/ false ) ; } } break ; case 248 /* SourceFile */ : case 218 /* ModuleDeclaration */ : case 213 /* FunctionDeclaration */ : case 143 /* MethodDeclaration */ : case 142 /* MethodSignature */ : case 145 /* GetAccessor */ : case 146 /* SetAccessor */ : case 144 /* Constructor */ : // Stop at the first containing function or module declaration break loop ; } // Use narrowed type if construct contains no assignments to variable if ( narrowedType !== type ) { if ( isVariableAssignedWithin ( symbol , node ) ) { break ; } type = narrowedType ; } } } } return type ; function narrowTypeByEquality ( type , expr , assumeTrue ) { // Check that we have 'typeof <symbol>' on the left and string literal on the right if ( expr . left . kind !== 176 /* TypeOfExpression */ || expr . right . kind !== 9 /* StringLiteral */ ) { return type ; } var left = expr . left ; var right = expr . right ; if ( left . expression . kind !== 69 /* Identifier */ || getResolvedSymbol ( left . expression ) !== symbol ) { return type ; } var typeInfo = primitiveTypeInfo [ right . text ] ; if ( expr . operatorToken . kind === 33 /* ExclamationEqualsEqualsToken */ ) { assumeTrue = ! assumeTrue ; } if ( assumeTrue ) { // Assumed result is true. If check was not for a primitive type, remove all primitive types if ( ! typeInfo ) { return removeTypesFromUnionType ( type , /*typeKind*/ 258 /* StringLike */ | 132 /* NumberLike */ | 8 /* Boolean */ | 16777216 /* ESSymbol */ , /*isOfTypeKind*/ true , /*allowEmptyUnionResult*/ false ) ; } // Check was for a primitive type, return that primitive type if it is a subtype if ( isTypeSubtypeOf ( typeInfo . type , type ) ) { return typeInfo . type ; } // Otherwise, remove all types that aren't of the primitive type kind. This can happen when the type is // union of enum types and other types. return removeTypesFromUnionType ( type , /*typeKind*/ typeInfo . flags , /*isOfTypeKind*/ false , /*allowEmptyUnionResult*/ false ) ; } else { // Assumed result is false. If check was for a primitive type, remove that primitive type if ( typeInfo ) { return removeTypesFromUnionType ( type , /*typeKind*/ typeInfo . flags , /*isOfTypeKind*/ true , /*allowEmptyUnionResult*/ false ) ; } // Otherwise we don't have enough information to do anything. return type ; } } function narrowTypeByAnd ( type , expr , assumeTrue ) { if ( assumeTrue ) { // The assumed result is true, therefore we narrow assuming each operand to be true. return narrowType ( narrowType ( type , expr . left , /*assumeTrue*/ true ) , expr . right , /*assumeTrue*/ true ) ; } else { // The assumed result is false. This means either the first operand was false, or the first operand was true // and the second operand was false. We narrow with those assumptions and union the two resulting types. return getUnionType ( [ narrowType ( type , expr . left , /*assumeTrue*/ false ) , narrowType ( narrowType ( type , expr . left , /*assumeTrue*/ true ) , expr . right , /*assumeTrue*/ false ) ] ) ; } } function narrowTypeByOr ( type , expr , assumeTrue ) { if ( assumeTrue ) { // The assumed result is true. This means either the first operand was true, or the first operand was false // and the second operand was true. We narrow with those assumptions and union the two resulting types. return getUnionType ( [ narrowType ( type , expr . left , /*assumeTrue*/ true ) , narrowType ( narrowType ( type , expr . left , /*assumeTrue*/ false ) , expr . right , /*assumeTrue*/ true ) ] ) ; } else { // The assumed result is false, therefore we narrow assuming each operand to be false. return narrowType ( narrowType ( type , expr . left , /*assumeTrue*/ false ) , expr . right , /*assumeTrue*/ false ) ; } } function narrowTypeByInstanceof ( type , expr , assumeTrue ) { // Check that type is not any, assumed result is true, and we have variable symbol on the left if ( isTypeAny ( type ) || ! assumeTrue || expr . left . kind !== 69 /* Identifier */ || getResolvedSymbol ( expr . left ) !== symbol ) { return type ; } // Check that right operand is a function type with a prototype property var rightType = checkExpression ( expr . right ) ; if ( ! isTypeSubtypeOf ( rightType , globalFunctionType ) ) { return type ; } var targetType ; var prototypeProperty = getPropertyOfType ( rightType , "prototype" ) ; if ( prototypeProperty ) { // Target type is type of the prototype property var prototypePropertyType = getTypeOfSymbol ( prototypeProperty ) ; if ( ! isTypeAny ( prototypePropertyType ) ) { targetType = prototypePropertyType ; } } if ( ! targetType ) { // Target type is type of construct signature var constructSignatures ; if ( rightType . flags & 2048 /* Interface */ ) { constructSignatures = resolveDeclaredMembers ( rightType ) . declaredConstructSignatures ; } else if ( rightType . flags & 65536 /* Anonymous */ ) { constructSignatures = getSignaturesOfType ( rightType , 1 /* Construct */ ) ; } if ( constructSignatures && constructSignatures . length ) { targetType = getUnionType ( ts . map ( constructSignatures , function ( signature ) { return getReturnTypeOfSignature ( getErasedSignature ( signature ) ) ; } ) ) ; } } if ( targetType ) { return getNarrowedType ( type , targetType ) ; } return type ; } function getNarrowedType ( originalType , narrowedTypeCandidate ) { // If the current type is a union type, remove all constituents that aren't assignable to target. If that produces // 0 candidates, fall back to the assignability check if ( originalType . flags & 16384 /* Union */ ) { var assignableConstituents = ts . filter ( originalType . types , function ( t ) { return isTypeAssignableTo ( t , narrowedTypeCandidate ) ; } ) ; if ( assignableConstituents . length ) { return getUnionType ( assignableConstituents ) ; } } if ( isTypeAssignableTo ( narrowedTypeCandidate , originalType ) ) { // Narrow to the target type if it's assignable to the current type return narrowedTypeCandidate ; } return originalType ; } function narrowTypeByTypePredicate ( type , expr , assumeTrue ) { if ( type . flags & 1 /* Any */ ) { return type ; } var signature = getResolvedSignature ( expr ) ; if ( signature . typePredicate && expr . arguments [ signature . typePredicate . parameterIndex ] && getSymbolAtLocation ( expr . arguments [ signature . typePredicate . parameterIndex ] ) === symbol ) { if ( ! assumeTrue ) { if ( type . flags & 16384 /* Union */ ) { return getUnionType ( ts . filter ( type . types , function ( t ) { return ! isTypeSubtypeOf ( t , signature . typePredicate . type ) ; } ) ) ; } return type ; } return getNarrowedType ( type , signature . typePredicate . type ) ; } return type ; } // Narrow the given type based on the given expression having the assumed boolean value. The returned type // will be a subtype or the same type as the argument. function narrowType ( type , expr , assumeTrue ) { switch ( expr . kind ) { case 168 /* CallExpression */ : return narrowTypeByTypePredicate ( type , expr , assumeTrue ) ; case 172 /* ParenthesizedExpression */ : return narrowType ( type , expr . expression , assumeTrue ) ; case 181 /* BinaryExpression */ : var operator = expr . operatorToken . kind ; if ( operator === 32 /* EqualsEqualsEqualsToken */ || operator === 33 /* ExclamationEqualsEqualsToken */ ) { return narrowTypeByEquality ( type , expr , assumeTrue ) ; } else if ( operator === 51 /* AmpersandAmpersandToken */ ) { return narrowTypeByAnd ( type , expr , assumeTrue ) ; } else if ( operator === 52 /* BarBarToken */ ) { return narrowTypeByOr ( type , expr , assumeTrue ) ; } else if ( operator === 91 /* InstanceOfKeyword */ ) { return narrowTypeByInstanceof ( type , expr , assumeTrue ) ; } break ; case 179 /* PrefixUnaryExpression */ : if ( expr . operator === 49 /* ExclamationToken */ ) { return narrowType ( type , expr . operand , ! assumeTrue ) ; } break ; } return type ; } }


Input: Narrow the given type based on the given expression having the assumed boolean value . The returned type will be a subtype or the same type as the argument . [CODESPLIT] function narrowType ( type , expr , assumeTrue ) { switch ( expr . kind ) { case 168 /* CallExpression */ : return narrowTypeByTypePredicate ( type , expr , assumeTrue ) ; case 172 /* ParenthesizedExpression */ : return narrowType ( type , expr . expression , assumeTrue ) ; case 181 /* BinaryExpression */ : var operator = expr . operatorToken . kind ; if ( operator === 32 /* EqualsEqualsEqualsToken */ || operator === 33 /* ExclamationEqualsEqualsToken */ ) { return narrowTypeByEquality ( type , expr , assumeTrue ) ; } else if ( operator === 51 /* AmpersandAmpersandToken */ ) { return narrowTypeByAnd ( type , expr , assumeTrue ) ; } else if ( operator === 52 /* BarBarToken */ ) { return narrowTypeByOr ( type , expr , assumeTrue ) ; } else if ( operator === 91 /* InstanceOfKeyword */ ) { return narrowTypeByInstanceof ( type , expr , assumeTrue ) ; } break ; case 179 /* PrefixUnaryExpression */ : if ( expr . operator === 49 /* ExclamationToken */ ) { return narrowType ( type , expr . operand , ! assumeTrue ) ; } break ; } return type ; }


Input: Return contextual type of parameter or undefined if no contextual type is available [CODESPLIT] function getContextuallyTypedParameterType ( parameter ) { var func = parameter . parent ; if ( isFunctionExpressionOrArrowFunction ( func ) || ts . isObjectLiteralMethod ( func ) ) { if ( isContextSensitive ( func ) ) { var contextualSignature = getContextualSignature ( func ) ; if ( contextualSignature ) { var funcHasRestParameters = ts . hasRestParameter ( func ) ; var len = func . parameters . length - ( funcHasRestParameters ? 1 : 0 ) ; var indexOfParameter = ts . indexOf ( func . parameters , parameter ) ; if ( indexOfParameter < len ) { return getTypeAtPosition ( contextualSignature , indexOfParameter ) ; } // If last parameter is contextually rest parameter get its type if ( funcHasRestParameters && indexOfParameter === ( func . parameters . length - 1 ) && isRestParameterIndex ( contextualSignature , func . parameters . length - 1 ) ) { return getTypeOfSymbol ( ts . lastOrUndefined ( contextualSignature . parameters ) ) ; } } } } return undefined ; }


Input: In a variable parameter or property declaration with a type annotation the contextual type of an initializer expression is the type of the variable parameter or property . Otherwise in a parameter declaration of a contextually typed function expression the contextual type of an initializer expression is the contextual type of the parameter . Otherwise in a variable or parameter declaration with a binding pattern name the contextual type of an initializer expression is the type implied by the binding pattern . [CODESPLIT] function getContextualTypeForInitializerExpression ( node ) { var declaration = node . parent ; if ( node === declaration . initializer ) { if ( declaration . type ) { return getTypeFromTypeNode ( declaration . type ) ; } if ( declaration . kind === 138 /* Parameter */ ) { var type = getContextuallyTypedParameterType ( declaration ) ; if ( type ) { return type ; } } if ( ts . isBindingPattern ( declaration . name ) ) { return getTypeFromBindingPattern ( declaration . name , /*includePatternInType*/ true ) ; } } return undefined ; }


Input: Apply a mapping function to a contextual type and return the resulting type . If the contextual type is a union type the mapping function is applied to each constituent type and a union of the resulting types is returned . [CODESPLIT] function applyToContextualType ( type , mapper ) { if ( ! ( type . flags & 16384 /* Union */ ) ) { return mapper ( type ) ; } var types = type . types ; var mappedType ; var mappedTypes ; for ( var _i = 0 ; _i < types . length ; _i ++ ) { var current = types [ _i ] ; var t = mapper ( current ) ; if ( t ) { if ( ! mappedType ) { mappedType = t ; } else if ( ! mappedTypes ) { mappedTypes = [ mappedType , t ] ; } else { mappedTypes . push ( t ) ; } } } return mappedTypes ? getUnionType ( mappedTypes ) : mappedType ; }


Input: Return true if the given contextual type provides an index signature of the given kind [CODESPLIT] function contextualTypeHasIndexSignature ( type , kind ) { return ! ! ( type . flags & 16384 /* Union */ ? ts . forEach ( type . types , function ( t ) { return getIndexTypeOfStructuredType ( t , kind ) ; } ) : getIndexTypeOfStructuredType ( type , kind ) ) ; }


Input: In an object literal contextually typed by a type T the contextual type of a property assignment is the type of the matching property in T if one exists . Otherwise it is the type of the numeric index signature in T if one exists . Otherwise it is the type of the string index signature in T if one exists . [CODESPLIT] function getContextualTypeForObjectLiteralMethod ( node ) { ts . Debug . assert ( ts . isObjectLiteralMethod ( node ) ) ; if ( isInsideWithStatementBody ( node ) ) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined ; } return getContextualTypeForObjectLiteralElement ( node ) ; }


Input: In an array literal contextually typed by a type T the contextual type of an element expression at index N is the type of the property with the numeric name N in T if one exists . Otherwise if T has a numeric index signature it is the type of the numeric index signature in T . Otherwise in ES6 and higher the contextual type is the iterated type of T . [CODESPLIT] function getContextualTypeForElementExpression ( node ) { var arrayLiteral = node . parent ; var type = getContextualType ( arrayLiteral ) ; if ( type ) { var index = ts . indexOf ( arrayLiteral . elements , node ) ; return getTypeOfPropertyOfContextualType ( type , "" + index ) || getIndexTypeOfContextualType ( type , 1 /* Number */ ) || ( languageVersion >= 2 /* ES6 */ ? getElementTypeOfIterable ( type , /*errorNode*/ undefined ) : undefined ) ; } return undefined ; }


Input: In a contextually typed conditional expression the true / false expressions are contextually typed by the same type . [CODESPLIT] function getContextualTypeForConditionalOperand ( node ) { var conditional = node . parent ; return node === conditional . whenTrue || node === conditional . whenFalse ? getContextualType ( conditional ) : undefined ; }


Input: If the given type is an object or union type if that type has a single signature and if that signature is non - generic return the signature . Otherwise return undefined . [CODESPLIT] function getNonGenericSignature ( type ) { var signatures = getSignaturesOfStructuredType ( type , 0 /* Call */ ) ; if ( signatures . length === 1 ) { var signature = signatures [ 0 ] ; if ( ! signature . typeParameters ) { return signature ; } } }


Input: Return the contextual signature for a given expression node . A contextual type provides a contextual signature if it has a single call signature and if that call signature is non - generic . If the contextual type is a union type get the signature from each type possible and if they are all identical ignoring their return type the result is same signature but with return type as union type of return types from these signatures [CODESPLIT] function getContextualSignature ( node ) { ts . Debug . assert ( node . kind !== 143 /* MethodDeclaration */ || ts . isObjectLiteralMethod ( node ) ) ; var type = ts . isObjectLiteralMethod ( node ) ? getContextualTypeForObjectLiteralMethod ( node ) : getContextualType ( node ) ; if ( ! type ) { return undefined ; } if ( ! ( type . flags & 16384 /* Union */ ) ) { return getNonGenericSignature ( type ) ; } var signatureList ; var types = type . types ; for ( var _i = 0 ; _i < types . length ; _i ++ ) { var current = types [ _i ] ; var signature = getNonGenericSignature ( current ) ; if ( signature ) { if ( ! signatureList ) { // This signature will contribute to contextual union signature signatureList = [ signature ] ; } else if ( ! compareSignatures ( signatureList [ 0 ] , signature , /*partialMatch*/ false , /*ignoreReturnTypes*/ true , compareTypes ) ) { // Signatures aren't identical, do not use return undefined ; } else { // Use this signature for contextual union signature signatureList . push ( signature ) ; } } } // Result is union of signatures collected (return type is union of return types of this signature set) var result ; if ( signatureList ) { result = cloneSignature ( signatureList [ 0 ] ) ; // Clear resolved return type we possibly got from cloneSignature result . resolvedReturnType = undefined ; result . unionSignatures = signatureList ; } return result ; }


Input: A node is an assignment target if it is on the left hand side of an = token if it is parented by a property assignment in an object literal that is an assignment target or if it is parented by an array literal that is an assignment target . Examples include a = xxx { p : a } = xxx [ { p : a } ] = xxx . [CODESPLIT] function isAssignmentTarget ( node ) { var parent = node . parent ; if ( parent . kind === 181 /* BinaryExpression */ && parent . operatorToken . kind === 56 /* EqualsToken */ && parent . left === node ) { return true ; } if ( parent . kind === 245 /* PropertyAssignment */ ) { return isAssignmentTarget ( parent . parent ) ; } if ( parent . kind === 164 /* ArrayLiteralExpression */ ) { return isAssignmentTarget ( parent ) ; } return false ; }


Input: / Returns the type JSX . IntrinsicElements . May return unknownType if that type is not present . [CODESPLIT] function getJsxIntrinsicElementsType ( ) { if ( ! jsxIntrinsicElementsType ) { jsxIntrinsicElementsType = getExportedTypeFromNamespace ( JsxNames . JSX , JsxNames . IntrinsicElements ) || unknownType ; } return jsxIntrinsicElementsType ; }


Input: / Given a JSX opening element or self - closing element return the symbol of the property that the tag name points to if / this is an intrinsic tag . This might be a named / property of the IntrinsicElements interface or its string indexer . / If this is a class - based tag ( otherwise returns undefined ) returns the symbol of the class / type or factory function . / Otherwise returns unknownSymbol . [CODESPLIT] function getJsxElementTagSymbol ( node ) { var flags = 8 /* UnknownElement */ ; var links = getNodeLinks ( node ) ; if ( ! links . resolvedSymbol ) { if ( isJsxIntrinsicIdentifier ( node . tagName ) ) { links . resolvedSymbol = lookupIntrinsicTag ( node ) ; } else { links . resolvedSymbol = lookupClassTag ( node ) ; } } return links . resolvedSymbol ; function lookupIntrinsicTag ( node ) { var intrinsicElementsType = getJsxIntrinsicElementsType ( ) ; if ( intrinsicElementsType !== unknownType ) { // Property case var intrinsicProp = getPropertyOfType ( intrinsicElementsType , node . tagName . text ) ; if ( intrinsicProp ) { links . jsxFlags |= 1 /* IntrinsicNamedElement */ ; return intrinsicProp ; } // Intrinsic string indexer case var indexSignatureType = getIndexTypeOfType ( intrinsicElementsType , 0 /* String */ ) ; if ( indexSignatureType ) { links . jsxFlags |= 2 /* IntrinsicIndexedElement */ ; return intrinsicElementsType . symbol ; } // Wasn't found error ( node , ts . Diagnostics . Property_0_does_not_exist_on_type_1 , node . tagName . text , "JSX." + JsxNames . IntrinsicElements ) ; return unknownSymbol ; } else { if ( compilerOptions . noImplicitAny ) { error ( node , ts . Diagnostics . JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists , JsxNames . IntrinsicElements ) ; } } } function lookupClassTag ( node ) { var valueSymbol = resolveJsxTagName ( node ) ; // Look up the value in the current scope if ( valueSymbol && valueSymbol !== unknownSymbol ) { links . jsxFlags |= 4 /* ClassElement */ ; if ( valueSymbol . flags & 8388608 /* Alias */ ) { markAliasSymbolAsReferenced ( valueSymbol ) ; } } return valueSymbol || unknownSymbol ; } function resolveJsxTagName ( node ) { if ( node . tagName . kind === 69 /* Identifier */ ) { var tag = node . tagName ; var sym = getResolvedSymbol ( tag ) ; return sym . exportSymbol || sym ; } else { return checkQualifiedName ( node . tagName ) . symbol ; } } }


Input: Given a JSX element that is a class element finds the Element Instance Type . If the element is not a class element or the class element type cannot be determined returns undefined . For example in the element <MyClass > the element instance type is MyClass ( not typeof MyClass ) . [CODESPLIT] function getJsxElementInstanceType ( node ) { // There is no such thing as an instance type for a non-class element. This // line shouldn't be hit. ts . Debug . assert ( ! ! ( getNodeLinks ( node ) . jsxFlags & 4 /* ClassElement */ ) , "Should not call getJsxElementInstanceType on non-class Element" ) ; var classSymbol = getJsxElementTagSymbol ( node ) ; if ( classSymbol === unknownSymbol ) { // Couldn't find the class instance type. Error has already been issued return anyType ; } var valueType = getTypeOfSymbol ( classSymbol ) ; if ( isTypeAny ( valueType ) ) { // Short-circuit if the class tag is using an element type 'any' return anyType ; } // Resolve the signatures, preferring constructors var signatures = getSignaturesOfType ( valueType , 1 /* Construct */ ) ; if ( signatures . length === 0 ) { // No construct signatures, try call signatures signatures = getSignaturesOfType ( valueType , 0 /* Call */ ) ; if ( signatures . length === 0 ) { // We found no signatures at all, which is an error error ( node . tagName , ts . Diagnostics . JSX_element_type_0_does_not_have_any_construct_or_call_signatures , ts . getTextOfNode ( node . tagName ) ) ; return unknownType ; } } var returnType = getUnionType ( signatures . map ( getReturnTypeOfSignature ) ) ; // Issue an error if this return type isn't assignable to JSX.ElementClass var elemClassType = getJsxGlobalElementClassType ( ) ; if ( elemClassType ) { checkTypeRelatedTo ( returnType , elemClassType , assignableRelation , node , ts . Diagnostics . JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements ) ; } return returnType ; }


Input: Given an opening / self - closing element get the element attributes type i . e . the type that tells us which attributes are valid on a given element . [CODESPLIT] function getJsxElementAttributesType ( node ) { var links = getNodeLinks ( node ) ; if ( ! links . resolvedJsxType ) { var sym = getJsxElementTagSymbol ( node ) ; if ( links . jsxFlags & 4 /* ClassElement */ ) { var elemInstanceType = getJsxElementInstanceType ( node ) ; if ( isTypeAny ( elemInstanceType ) ) { return links . resolvedJsxType = elemInstanceType ; } var propsName = getJsxElementPropertiesName ( ) ; if ( propsName === undefined ) { // There is no type ElementAttributesProperty, return 'any' return links . resolvedJsxType = anyType ; } else if ( propsName === "" ) { // If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead return links . resolvedJsxType = elemInstanceType ; } else { var attributesType = getTypeOfPropertyOfType ( elemInstanceType , propsName ) ; if ( ! attributesType ) { // There is no property named 'props' on this instance type return links . resolvedJsxType = emptyObjectType ; } else if ( isTypeAny ( attributesType ) || ( attributesType === unknownType ) ) { return links . resolvedJsxType = attributesType ; } else if ( ! ( attributesType . flags & 80896 /* ObjectType */ ) ) { error ( node . tagName , ts . Diagnostics . JSX_element_attributes_type_0_must_be_an_object_type , typeToString ( attributesType ) ) ; return links . resolvedJsxType = anyType ; } else { return links . resolvedJsxType = attributesType ; } } } else if ( links . jsxFlags & 1 /* IntrinsicNamedElement */ ) { return links . resolvedJsxType = getTypeOfSymbol ( sym ) ; } else if ( links . jsxFlags & 2 /* IntrinsicIndexedElement */ ) { return links . resolvedJsxType = getIndexTypeOfSymbol ( sym , 0 /* String */ ) ; } else { // Resolution failed, so we don't know return links . resolvedJsxType = anyType ; } } return links . resolvedJsxType ; }


Input: Given a JSX attribute returns the symbol for the corresponds property of the element attributes type . Will return unknownSymbol for attributes that have no matching element attributes type property . [CODESPLIT] function getJsxAttributePropertySymbol ( attrib ) { var attributesType = getJsxElementAttributesType ( attrib . parent ) ; var prop = getPropertyOfType ( attributesType , attrib . name . text ) ; return prop || unknownSymbol ; }


Input: Check whether the requested property access is valid . Returns true if node is a valid property access and false otherwise . [CODESPLIT] function checkClassPropertyAccess ( node , left , type , prop ) { var flags = getDeclarationFlagsFromSymbol ( prop ) ; var declaringClass = getDeclaredTypeOfSymbol ( prop . parent ) ; if ( left . kind === 95 /* SuperKeyword */ ) { var errorNode = node . kind === 166 /* PropertyAccessExpression */ ? node . name : node . right ; // TS 1.0 spec (April 2014): 4.8.2 // - In a constructor, instance member function, instance member accessor, or //   instance member variable initializer where this references a derived class instance, //   a super property access is permitted and must specify a public instance member function of the base class. // - In a static member function or static member accessor //   where this references the constructor function object of a derived class, //   a super property access is permitted and must specify a public static member function of the base class. if ( getDeclarationKindFromSymbol ( prop ) !== 143 /* MethodDeclaration */ ) { // `prop` refers to a *property* declared in the super class // rather than a *method*, so it does not satisfy the above criteria. error ( errorNode , ts . Diagnostics . Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword ) ; return false ; } if ( flags & 256 /* Abstract */ ) { // A method cannot be accessed in a super property access if the method is abstract. // This error could mask a private property access error. But, a member // cannot simultaneously be private and abstract, so this will trigger an // additional error elsewhere. error ( errorNode , ts . Diagnostics . Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression , symbolToString ( prop ) , typeToString ( declaringClass ) ) ; return false ; } } // Public properties are otherwise accessible. if ( ! ( flags & ( 32 /* Private */ | 64 /* Protected */ ) ) ) { return true ; } // Property is known to be private or protected at this point // Get the declaring and enclosing class instance types var enclosingClassDeclaration = ts . getContainingClass ( node ) ; var enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol ( getSymbolOfNode ( enclosingClassDeclaration ) ) : undefined ; // Private property is accessible if declaring and enclosing class are the same if ( flags & 32 /* Private */ ) { if ( declaringClass !== enclosingClass ) { error ( node , ts . Diagnostics . Property_0_is_private_and_only_accessible_within_class_1 , symbolToString ( prop ) , typeToString ( declaringClass ) ) ; return false ; } return true ; } // Property is known to be protected at this point // All protected properties of a supertype are accessible in a super access if ( left . kind === 95 /* SuperKeyword */ ) { return true ; } // A protected property is accessible in the declaring class and classes derived from it if ( ! enclosingClass || ! hasBaseType ( enclosingClass , declaringClass ) ) { error ( node , ts . Diagnostics . Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses , symbolToString ( prop ) , typeToString ( declaringClass ) ) ; return false ; } // No further restrictions for static properties if ( flags & 128 /* Static */ ) { return true ; } // An instance property must be accessed through an instance of the enclosing class if ( type . flags & 33554432 /* ThisType */ ) { // get the original type -- represented as the type constraint of the 'this' type type = getConstraintOfTypeParameter ( type ) ; } // TODO: why is the first part of this check here? if ( ! ( getTargetType ( type ) . flags & ( 1024 /* Class */ | 2048 /* Interface */ ) && hasBaseType ( type , enclosingClass ) ) ) { error ( node , ts . Diagnostics . Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1 , symbolToString ( prop ) , typeToString ( enclosingClass ) ) ; return false ; } return true ; }


Input: If indexArgumentExpression is a string literal or number literal returns its text . If indexArgumentExpression is a constant value returns its string value . If indexArgumentExpression is a well known symbol returns the property name corresponding to this symbol as long as it is a proper symbol reference . Otherwise returns undefined . [CODESPLIT] function getPropertyNameForIndexedAccess ( indexArgumentExpression , indexArgumentType ) { if ( indexArgumentExpression . kind === 9 /* StringLiteral */ || indexArgumentExpression . kind === 8 /* NumericLiteral */ ) { return indexArgumentExpression . text ; } if ( indexArgumentExpression . kind === 167 /* ElementAccessExpression */ || indexArgumentExpression . kind === 166 /* PropertyAccessExpression */ ) { var value = getConstantValue ( indexArgumentExpression ) ; if ( value !== undefined ) { return value . toString ( ) ; } } if ( checkThatExpressionIsProperSymbolReference ( indexArgumentExpression , indexArgumentType , /*reportError*/ false ) ) { var rightHandSideName = indexArgumentExpression . name . text ; return ts . getPropertyNameForKnownSymbolName ( rightHandSideName ) ; } return undefined ; }


Input: Re - order candidate signatures into the result array . Assumes the result array to be empty . The candidate list orders groups in reverse but within a group signatures are kept in declaration order A nit here is that we reorder only signatures that belong to the same symbol so order how inherited signatures are processed is still preserved . interface A { ( x : string ) : void } interface B extends A { ( x : foo ) : string } let b : B ; b ( foo ) // < - here overloads should be processed as [ ( x : foo ) : string ( x : string ) : void ] [CODESPLIT] function reorderCandidates ( signatures , result ) { var lastParent ; var lastSymbol ; var cutoffIndex = 0 ; var index ; var specializedIndex = - 1 ; var spliceIndex ; ts . Debug . assert ( ! result . length ) ; for ( var _i = 0 ; _i < signatures . length ; _i ++ ) { var signature = signatures [ _i ] ; var symbol = signature . declaration && getSymbolOfNode ( signature . declaration ) ; var parent_5 = signature . declaration && signature . declaration . parent ; if ( ! lastSymbol || symbol === lastSymbol ) { if ( lastParent && parent_5 === lastParent ) { index ++ ; } else { lastParent = parent_5 ; index = cutoffIndex ; } } else { // current declaration belongs to a different symbol // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex index = cutoffIndex = result . length ; lastParent = parent_5 ; } lastSymbol = symbol ; // specialized signatures always need to be placed before non-specialized signatures regardless // of the cutoff position; see GH#1133 if ( signature . hasStringLiterals ) { specializedIndex ++ ; spliceIndex = specializedIndex ; // The cutoff index always needs to be greater than or equal to the specialized signature index // in order to prevent non-specialized signatures from being added before a specialized // signature. cutoffIndex ++ ; } else { spliceIndex = index ; } result . splice ( spliceIndex , 0 , signature ) ; } }


Input: If type has a single call signature and no other members return that signature . Otherwise return undefined . [CODESPLIT] function getSingleCallSignature ( type ) { if ( type . flags & 80896 /* ObjectType */ ) { var resolved = resolveStructuredTypeMembers ( type ) ; if ( resolved . callSignatures . length === 1 && resolved . constructSignatures . length === 0 && resolved . properties . length === 0 && ! resolved . stringIndexType && ! resolved . numberIndexType ) { return resolved . callSignatures [ 0 ] ; } } return undefined ; }


Input: Instantiate a generic signature in the context of a non - generic signature ( section 3 . 8 . 5 in TypeScript spec ) [CODESPLIT] function instantiateSignatureInContextOf ( signature , contextualSignature , contextualMapper ) { var context = createInferenceContext ( signature . typeParameters , /*inferUnionTypes*/ true ) ; forEachMatchingParameterType ( contextualSignature , signature , function ( source , target ) { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes ( context , instantiateType ( source , contextualMapper ) , target ) ; } ) ; return getSignatureInstantiation ( signature , getInferredTypes ( context ) ) ; }


Input: Returns the effective arguments for an expression that works like a function invocation . [CODESPLIT] function getEffectiveCallArguments ( node ) { var args ; if ( node . kind === 170 /* TaggedTemplateExpression */ ) { var template = node . template ; args = [ undefined ] ; if ( template . kind === 183 /* TemplateExpression */ ) { ts . forEach ( template . templateSpans , function ( span ) { args . push ( span . expression ) ; } ) ; } } else if ( node . kind === 139 /* Decorator */ ) { // For a decorator, we return undefined as we will determine // the number and types of arguments for a decorator using // `getEffectiveArgumentCount` and `getEffectiveArgumentType` below. return undefined ; } else { args = node . arguments || emptyArray ; } return args ; }


Input: Returns the effective argument count for a node that works like a function invocation . If node is a Decorator the number of arguments is derived from the decoration target and the signature : If node . target is a class declaration or class expression the effective argument count is 1 . If node . target is a parameter declaration the effective argument count is 3 . If node . target is a property declaration the effective argument count is 2 . If node . target is a method or accessor declaration the effective argument count is 3 although it can be 2 if the signature only accepts two arguments allowing us to match a property decorator . Otherwise the argument count is the length of the args array . [CODESPLIT] function getEffectiveArgumentCount ( node , args , signature ) { if ( node . kind === 139 /* Decorator */ ) { switch ( node . parent . kind ) { case 214 /* ClassDeclaration */ : case 186 /* ClassExpression */ : // A class decorator will have one argument (see `ClassDecorator` in core.d.ts) return 1 ; case 141 /* PropertyDeclaration */ : // A property declaration decorator will have two arguments (see // `PropertyDecorator` in core.d.ts) return 2 ; case 143 /* MethodDeclaration */ : case 145 /* GetAccessor */ : case 146 /* SetAccessor */ : // A method or accessor declaration decorator will have two or three arguments (see // `PropertyDecorator` and `MethodDecorator` in core.d.ts) // If we are emitting decorators for ES3, we will only pass two arguments. if ( languageVersion === 0 /* ES3 */ ) { return 2 ; } // If the method decorator signature only accepts a target and a key, we will only // type check those arguments. return signature . parameters . length >= 3 ? 3 : 2 ; case 138 /* Parameter */ : // A parameter declaration decorator will have three arguments (see // `ParameterDecorator` in core.d.ts) return 3 ; } } else { return args . length ; } }


Input: Returns the effective type for the second argument to a decorator . If node is a parameter its effective argument type is one of the following : If node . parent is a constructor the effective argument type is any as we will emit undefined . If node . parent is a member with an identifier numeric or string literal name the effective argument type will be a string literal type for the member name . If node . parent is a computed property name the effective argument type will either be a symbol type or the string type . If node is a member with an identifier numeric or string literal name the effective argument type will be a string literal type for the member name . If node is a computed property name the effective argument type will either be a symbol type or the string type . A class decorator does not have a second argument type . [CODESPLIT] function getEffectiveDecoratorSecondArgumentType ( node ) { // The second argument to a decorator is its `propertyKey` if ( node . kind === 214 /* ClassDeclaration */ ) { ts . Debug . fail ( "Class decorators should not have a second synthetic argument." ) ; return unknownType ; } if ( node . kind === 138 /* Parameter */ ) { node = node . parent ; if ( node . kind === 144 /* Constructor */ ) { // For a constructor parameter decorator, the `propertyKey` will be `undefined`. return anyType ; } } if ( node . kind === 141 /* PropertyDeclaration */ || node . kind === 143 /* MethodDeclaration */ || node . kind === 145 /* GetAccessor */ || node . kind === 146 /* SetAccessor */ ) { // The `propertyKey` for a property or method decorator will be a // string literal type if the member name is an identifier, number, or string; // otherwise, if the member name is a computed property name it will // be either string or symbol. var element = node ; switch ( element . name . kind ) { case 69 /* Identifier */ : case 8 /* NumericLiteral */ : case 9 /* StringLiteral */ : return getStringLiteralType ( element . name ) ; case 136 /* ComputedPropertyName */ : var nameType = checkComputedPropertyName ( element . name ) ; if ( allConstituentTypesHaveKind ( nameType , 16777216 /* ESSymbol */ ) ) { return nameType ; } else { return stringType ; } default : ts . Debug . fail ( "Unsupported property name." ) ; return unknownType ; } } ts . Debug . fail ( "Unsupported decorator target." ) ; return unknownType ; }


Input: Returns the effective argument type for the provided argument to a decorator . [CODESPLIT] function getEffectiveDecoratorArgumentType ( node , argIndex ) { if ( argIndex === 0 ) { return getEffectiveDecoratorFirstArgumentType ( node . parent ) ; } else if ( argIndex === 1 ) { return getEffectiveDecoratorSecondArgumentType ( node . parent ) ; } else if ( argIndex === 2 ) { return getEffectiveDecoratorThirdArgumentType ( node . parent ) ; } ts . Debug . fail ( "Decorators should not have a fourth synthetic argument." ) ; return unknownType ; }


Input: Gets the effective argument type for an argument in a call expression . [CODESPLIT] function getEffectiveArgumentType ( node , argIndex , arg ) { // Decorators provide special arguments, a tagged template expression provides // a special first argument, and string literals get string literal types // unless we're reporting errors if ( node . kind === 139 /* Decorator */ ) { return getEffectiveDecoratorArgumentType ( node , argIndex ) ; } else if ( argIndex === 0 && node . kind === 170 /* TaggedTemplateExpression */ ) { return globalTemplateStringsArrayType ; } // This is not a synthetic argument, so we return 'undefined' // to signal that the caller needs to check the argument. return undefined ; }


Input: Gets the effective argument expression for an argument in a call expression . [CODESPLIT] function getEffectiveArgument ( node , args , argIndex ) { // For a decorator or the first argument of a tagged template expression we return undefined. if ( node . kind === 139 /* Decorator */ || ( argIndex === 0 && node . kind === 170 /* TaggedTemplateExpression */ ) ) { return undefined ; } return args [ argIndex ] ; }


Input: Gets the error node to use when reporting errors for an effective argument . [CODESPLIT] function getEffectiveArgumentErrorNode ( node , argIndex , arg ) { if ( node . kind === 139 /* Decorator */ ) { // For a decorator, we use the expression of the decorator for error reporting. return node . expression ; } else if ( argIndex === 0 && node . kind === 170 /* TaggedTemplateExpression */ ) { // For a the first argument of a tagged template expression, we use the template of the tag for error reporting. return node . template ; } else { return arg ; } }


Input: Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression . [CODESPLIT] function getDiagnosticHeadMessageForDecoratorResolution ( node ) { switch ( node . parent . kind ) { case 214 /* ClassDeclaration */ : case 186 /* ClassExpression */ : return ts . Diagnostics . Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression ; case 138 /* Parameter */ : return ts . Diagnostics . Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression ; case 141 /* PropertyDeclaration */ : return ts . Diagnostics . Unable_to_resolve_signature_of_property_decorator_when_called_as_an_expression ; case 143 /* MethodDeclaration */ : case 145 /* GetAccessor */ : case 146 /* SetAccessor */ : return ts . Diagnostics . Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression ; } }


Input: Resolves a decorator as if it were a call expression . [CODESPLIT] function resolveDecorator ( node , candidatesOutArray ) { var funcType = checkExpression ( node . expression ) ; var apparentType = getApparentType ( funcType ) ; if ( apparentType === unknownType ) { return resolveErrorCall ( node ) ; } var callSignatures = getSignaturesOfType ( apparentType , 0 /* Call */ ) ; if ( funcType === anyType || ( ! callSignatures . length && ! ( funcType . flags & 16384 /* Union */ ) && isTypeAssignableTo ( funcType , globalFunctionType ) ) ) { return resolveUntypedCall ( node ) ; } var headMessage = getDiagnosticHeadMessageForDecoratorResolution ( node ) ; if ( ! callSignatures . length ) { var errorInfo ; errorInfo = ts . chainDiagnosticMessages ( errorInfo , ts . Diagnostics . Cannot_invoke_an_expression_whose_type_lacks_a_call_signature ) ; errorInfo = ts . chainDiagnosticMessages ( errorInfo , headMessage ) ; diagnostics . add ( ts . createDiagnosticForNodeFromMessageChain ( node , errorInfo ) ) ; return resolveErrorCall ( node ) ; } return resolveCall ( node , callSignatures , candidatesOutArray , headMessage ) ; }


Input: candidatesOutArray is passed by signature help in the language service and collectCandidates must fill it up with the appropriate candidate signatures [CODESPLIT] function getResolvedSignature ( node , candidatesOutArray ) { var links = getNodeLinks ( node ) ; // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, // or that a different candidatesOutArray was passed in. Therefore, we need to redo the work // to correctly fill the candidatesOutArray. if ( ! links . resolvedSignature || candidatesOutArray ) { links . resolvedSignature = anySignature ; if ( node . kind === 168 /* CallExpression */ ) { links . resolvedSignature = resolveCallExpression ( node , candidatesOutArray ) ; } else if ( node . kind === 169 /* NewExpression */ ) { links . resolvedSignature = resolveNewExpression ( node , candidatesOutArray ) ; } else if ( node . kind === 170 /* TaggedTemplateExpression */ ) { links . resolvedSignature = resolveTaggedTemplateExpression ( node , candidatesOutArray ) ; } else if ( node . kind === 139 /* Decorator */ ) { links . resolvedSignature = resolveDecorator ( node , candidatesOutArray ) ; } else { ts . Debug . fail ( "Branch in 'getResolvedSignature' should be unreachable." ) ; } } return links . resolvedSignature ; }


Input: Syntactically and semantically checks a call or new expression . [CODESPLIT] function checkCallExpression ( node ) { // Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true checkGrammarTypeArguments ( node , node . typeArguments ) || checkGrammarArguments ( node , node . arguments ) ; var signature = getResolvedSignature ( node ) ; if ( node . expression . kind === 95 /* SuperKeyword */ ) { return voidType ; } if ( node . kind === 169 /* NewExpression */ ) { var declaration = signature . declaration ; if ( declaration && declaration . kind !== 144 /* Constructor */ && declaration . kind !== 148 /* ConstructSignature */ && declaration . kind !== 153 /* ConstructorType */ ) { // When resolved signature is a call signature (and not a construct signature) the result type is any if ( compilerOptions . noImplicitAny ) { error ( node , ts . Diagnostics . new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type ) ; } return anyType ; } } return getReturnTypeOfSignature ( signature ) ; }


Input: When contextual typing assigns a type to a parameter that contains a binding pattern we also need to push the destructured type into the contained binding elements . [CODESPLIT] function assignBindingElementTypes ( node ) { if ( ts . isBindingPattern ( node . name ) ) { for ( var _i = 0 , _a = node . name . elements ; _i < _a . length ; _i ++ ) { var element = _a [ _i ] ; if ( element . kind !== 187 /* OmittedExpression */ ) { if ( element . name . kind === 69 /* Identifier */ ) { getSymbolLinks ( getSymbolOfNode ( element ) ) . type = getTypeForBindingElement ( element ) ; } assignBindingElementTypes ( element ) ; } } } }


Input: TypeScript Specification 1 . 0 ( 6 . 3 ) - July 2014 An explicitly typed function whose return type isn t the Void or the Any type must have at least one return statement somewhere in its body . An exception to this rule is if the function implementation consists of a single throw statement . [CODESPLIT] function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment ( func , returnType ) { if ( ! produceDiagnostics ) { return ; } // Functions that return 'void' or 'any' don't need any return expressions. if ( returnType === voidType || isTypeAny ( returnType ) ) { return ; } // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. if ( ts . nodeIsMissing ( func . body ) || func . body . kind !== 192 /* Block */ ) { return ; } var bodyBlock = func . body ; // Ensure the body has at least one return expression. if ( bodyContainsAReturnStatement ( bodyBlock ) ) { return ; } // If there are no return expressions, then we need to check if // the function body consists solely of a throw statement; // this is to make an exception for unimplemented functions. if ( bodyContainsSingleThrowStatement ( bodyBlock ) ) { return ; } // This function does not conform to the specification. error ( func . type , ts . Diagnostics . A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement ) ; }


Input: Just like isTypeOfKind below except that it returns true if * any * constituent has this kind . [CODESPLIT] function someConstituentTypeHasKind ( type , kind ) { if ( type . flags & kind ) { return true ; } if ( type . flags & 49152 /* UnionOrIntersection */ ) { var types = type . types ; for ( var _i = 0 ; _i < types . length ; _i ++ ) { var current = types [ _i ] ; if ( current . flags & kind ) { return true ; } } return false ; } return false ; }


Input: DECLARATION AND STATEMENT TYPE CHECKING [CODESPLIT] function checkTypeParameter ( node ) { // Grammar Checking if ( node . expression ) { grammarErrorOnFirstToken ( node . expression , ts . Diagnostics . Type_expected ) ; } checkSourceElement ( node . constraint ) ; if ( produceDiagnostics ) { checkTypeParameterHasIllegalReferencesInConstraint ( node ) ; checkTypeNameIsReserved ( node . name , ts . Diagnostics . Type_parameter_name_cannot_be_0 ) ; } // TODO: Check multiple declarations are identical }


Input: Gets the promised type of a promise . [CODESPLIT] function getPromisedType ( promise ) { // //  { // promise //      then( // thenFunction //          onfulfilled: ( // onfulfilledParameterType //              value: T // valueParameterType //          ) => any //      ): any; //  } // if ( promise . flags & 1 /* Any */ ) { return undefined ; } if ( ( promise . flags & 4096 /* Reference */ ) && promise . target === tryGetGlobalPromiseType ( ) ) { return promise . typeArguments [ 0 ] ; } var globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType ( ) ; if ( globalPromiseLikeType === emptyObjectType || ! isTypeAssignableTo ( promise , globalPromiseLikeType ) ) { return undefined ; } var thenFunction = getTypeOfPropertyOfType ( promise , "then" ) ; if ( thenFunction && ( thenFunction . flags & 1 /* Any */ ) ) { return undefined ; } var thenSignatures = thenFunction ? getSignaturesOfType ( thenFunction , 0 /* Call */ ) : emptyArray ; if ( thenSignatures . length === 0 ) { return undefined ; } var onfulfilledParameterType = getUnionType ( ts . map ( thenSignatures , getTypeOfFirstParameterOfSignature ) ) ; if ( onfulfilledParameterType . flags & 1 /* Any */ ) { return undefined ; } var onfulfilledParameterSignatures = getSignaturesOfType ( onfulfilledParameterType , 0 /* Call */ ) ; if ( onfulfilledParameterSignatures . length === 0 ) { return undefined ; } var valueParameterType = getUnionType ( ts . map ( onfulfilledParameterSignatures , getTypeOfFirstParameterOfSignature ) ) ; return valueParameterType ; }


Input: Check a decorator [CODESPLIT] function checkDecorator ( node ) { var signature = getResolvedSignature ( node ) ; var returnType = getReturnTypeOfSignature ( signature ) ; if ( returnType . flags & 1 /* Any */ ) { return ; } var expectedReturnType ; var headMessage = getDiagnosticHeadMessageForDecoratorResolution ( node ) ; var errorInfo ; switch ( node . parent . kind ) { case 214 /* ClassDeclaration */ : var classSymbol = getSymbolOfNode ( node . parent ) ; var classConstructorType = getTypeOfSymbol ( classSymbol ) ; expectedReturnType = getUnionType ( [ classConstructorType , voidType ] ) ; break ; case 138 /* Parameter */ : expectedReturnType = voidType ; errorInfo = ts . chainDiagnosticMessages ( errorInfo , ts . Diagnostics . The_return_type_of_a_parameter_decorator_function_must_be_either_void_or_any ) ; break ; case 141 /* PropertyDeclaration */ : expectedReturnType = voidType ; errorInfo = ts . chainDiagnosticMessages ( errorInfo , ts . Diagnostics . The_return_type_of_a_property_decorator_function_must_be_either_void_or_any ) ; break ; case 143 /* MethodDeclaration */ : case 145 /* GetAccessor */ : case 146 /* SetAccessor */ : var methodType = getTypeOfNode ( node . parent ) ; var descriptorType = createTypedPropertyDescriptorType ( methodType ) ; expectedReturnType = getUnionType ( [ descriptorType , voidType ] ) ; break ; } checkTypeAssignableTo ( returnType , expectedReturnType , node , headMessage , errorInfo ) ; }


Input: Checks a type reference node as an expression . [CODESPLIT] function checkTypeNodeAsExpression ( node ) { // When we are emitting type metadata for decorators, we need to try to check the type // as if it were an expression so that we can emit the type in a value position when we // serialize the type metadata. if ( node && node . kind === 151 /* TypeReference */ ) { var root = getFirstIdentifier ( node . typeName ) ; var meaning = root . parent . kind === 151 /* TypeReference */ ? 793056 /* Type */ : 1536 /* Namespace */ ; // Resolve type so we know which symbol is referenced var rootSymbol = resolveName ( root , root . text , meaning | 8388608 /* Alias */ , /*nameNotFoundMessage*/ undefined , /*nameArg*/ undefined ) ; // Resolved symbol is alias if ( rootSymbol && rootSymbol . flags & 8388608 /* Alias */ ) { var aliasTarget = resolveAlias ( rootSymbol ) ; // If alias has value symbol - mark alias as referenced if ( aliasTarget . flags & 107455 /* Value */ && ! isConstEnumOrConstEnumOnlyModule ( resolveAlias ( rootSymbol ) ) ) { markAliasSymbolAsReferenced ( rootSymbol ) ; } } } }


Input: Checks the type annotation of an accessor declaration or property declaration as an expression if it is a type reference to a type with a value declaration . [CODESPLIT] function checkTypeAnnotationAsExpression ( node ) { switch ( node . kind ) { case 141 /* PropertyDeclaration */ : checkTypeNodeAsExpression ( node . type ) ; break ; case 138 /* Parameter */ : checkTypeNodeAsExpression ( node . type ) ; break ; case 143 /* MethodDeclaration */ : checkTypeNodeAsExpression ( node . type ) ; break ; case 145 /* GetAccessor */ : checkTypeNodeAsExpression ( node . type ) ; break ; case 146 /* SetAccessor */ : checkTypeNodeAsExpression ( ts . getSetAccessorTypeAnnotationNode ( node ) ) ; break ; } }


Input: Checks the type annotation of the parameters of a function / method or the constructor of a class as expressions [CODESPLIT] function checkParameterTypeAnnotationsAsExpressions ( node ) { // ensure all type annotations with a value declaration are checked as an expression for ( var _i = 0 , _a = node . parameters ; _i < _a . length ; _i ++ ) { var parameter = _a [ _i ] ; checkTypeAnnotationAsExpression ( parameter ) ; } }


Input: Check the decorators of a node [CODESPLIT] function checkDecorators ( node ) { if ( ! node . decorators ) { return ; } // skip this check for nodes that cannot have decorators. These should have already had an error reported by // checkGrammarDecorators. if ( ! ts . nodeCanBeDecorated ( node ) ) { return ; } if ( ! compilerOptions . experimentalDecorators ) { error ( node , ts . Diagnostics . Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalDecorators_to_remove_this_warning ) ; } if ( compilerOptions . emitDecoratorMetadata ) { // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator. switch ( node . kind ) { case 214 /* ClassDeclaration */ : var constructor = ts . getFirstConstructorWithBody ( node ) ; if ( constructor ) { checkParameterTypeAnnotationsAsExpressions ( constructor ) ; } break ; case 143 /* MethodDeclaration */ : checkParameterTypeAnnotationsAsExpressions ( node ) ; // fall-through case 146 /* SetAccessor */ : case 145 /* GetAccessor */ : case 141 /* PropertyDeclaration */ : case 138 /* Parameter */ : checkTypeAnnotationAsExpression ( node ) ; break ; } } emitDecorate = true ; if ( node . kind === 138 /* Parameter */ ) { emitParam = true ; } ts . forEach ( node . decorators , checkDecorator ) ; }