docs/libs/typescript.js
function objectTypeRelatedTo(source, originalSource, 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 (reportErrors && related === 2 /* Failed */) {
                        // We are elaborating errors and the cached result is an unreported failure. Record the result as a reported
                        // failure and continue computing the relation such that errors get reported.
                        relation[id] = 3 /* FailedAndReported */;
                    }
                    else {
                        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] = ts.createMap();
                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 &= indexTypesRelatedTo(source, originalSource, target, 0 /* String */, reportErrors);
                                if (result) {
                                    result &= indexTypesRelatedTo(source, originalSource, target, 1 /* Number */, 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.copyProperties(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 objectTypeRelatedTo(source, originalSource, 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 (reportErrors && related === 2 /* Failed */) {
                        // We are elaborating errors and the cached result is an unreported failure. Record the result as a reported
                        // failure and continue computing the relation such that errors get reported.
                        relation[id] = 3 /* FailedAndReported */;
                    }
                    else {
                        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] = ts.createMap();
                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 &= indexTypesRelatedTo(source, originalSource, target, 0 /* String */, reportErrors);
                                if (result) {
                                    result &= indexTypesRelatedTo(source, originalSource, target, 1 /* Number */, 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.copyProperties(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 objectTypeRelatedTo ( source , originalSource , 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 ( reportErrors && related === 2 /* Failed */ ) { // We are elaborating errors and the cached result is an unreported failure. Record the result as a reported // failure and continue computing the relation such that errors get reported. relation [ id ] = 3 /* FailedAndReported */ ; } else { 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 ] = ts . createMap ( ) ; 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 &= indexTypesRelatedTo ( source , originalSource , target , 0 /* String */ , reportErrors ) ; if ( result ) { result &= indexTypesRelatedTo ( source , originalSource , target , 1 /* Number */ , 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 . copyProperties ( 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 ; }
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.
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 .