• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts {
3    const ambientModuleSymbolRegex = /^".+"$/;
4    const anon = "(anonymous)" as __String & string;
5
6    let nextSymbolId = 1;
7    let nextNodeId = 1;
8    let nextMergeId = 1;
9    let nextFlowId = 1;
10
11    const enum IterationUse {
12        AllowsSyncIterablesFlag = 1 << 0,
13        AllowsAsyncIterablesFlag = 1 << 1,
14        AllowsStringInputFlag = 1 << 2,
15        ForOfFlag = 1 << 3,
16        YieldStarFlag = 1 << 4,
17        SpreadFlag = 1 << 5,
18        DestructuringFlag = 1 << 6,
19        PossiblyOutOfBounds = 1 << 7,
20
21        // Spread, Destructuring, Array element assignment
22        Element = AllowsSyncIterablesFlag,
23        Spread = AllowsSyncIterablesFlag | SpreadFlag,
24        Destructuring = AllowsSyncIterablesFlag | DestructuringFlag,
25
26        ForOf = AllowsSyncIterablesFlag | AllowsStringInputFlag | ForOfFlag,
27        ForAwaitOf = AllowsSyncIterablesFlag | AllowsAsyncIterablesFlag | AllowsStringInputFlag | ForOfFlag,
28
29        YieldStar = AllowsSyncIterablesFlag | YieldStarFlag,
30        AsyncYieldStar = AllowsSyncIterablesFlag | AllowsAsyncIterablesFlag | YieldStarFlag,
31
32        GeneratorReturnType = AllowsSyncIterablesFlag,
33        AsyncGeneratorReturnType = AllowsAsyncIterablesFlag,
34
35    }
36
37    const enum IterationTypeKind {
38        Yield,
39        Return,
40        Next,
41    }
42
43    interface IterationTypesResolver {
44        iterableCacheKey: "iterationTypesOfAsyncIterable" | "iterationTypesOfIterable";
45        iteratorCacheKey: "iterationTypesOfAsyncIterator" | "iterationTypesOfIterator";
46        iteratorSymbolName: "asyncIterator" | "iterator";
47        getGlobalIteratorType: (reportErrors: boolean) => GenericType;
48        getGlobalIterableType: (reportErrors: boolean) => GenericType;
49        getGlobalIterableIteratorType: (reportErrors: boolean) => GenericType;
50        getGlobalGeneratorType: (reportErrors: boolean) => GenericType;
51        resolveIterationType: (type: Type, errorNode: Node | undefined) => Type | undefined;
52        mustHaveANextMethodDiagnostic: DiagnosticMessage;
53        mustBeAMethodDiagnostic: DiagnosticMessage;
54        mustHaveAValueDiagnostic: DiagnosticMessage;
55    }
56
57    const enum WideningKind {
58        Normal,
59        FunctionReturn,
60        GeneratorNext,
61        GeneratorYield,
62    }
63
64    export const enum TypeFacts {
65        None = 0,
66        TypeofEQString = 1 << 0,      // typeof x === "string"
67        TypeofEQNumber = 1 << 1,      // typeof x === "number"
68        TypeofEQBigInt = 1 << 2,      // typeof x === "bigint"
69        TypeofEQBoolean = 1 << 3,     // typeof x === "boolean"
70        TypeofEQSymbol = 1 << 4,      // typeof x === "symbol"
71        TypeofEQObject = 1 << 5,      // typeof x === "object"
72        TypeofEQFunction = 1 << 6,    // typeof x === "function"
73        TypeofEQHostObject = 1 << 7,  // typeof x === "xxx"
74        TypeofNEString = 1 << 8,      // typeof x !== "string"
75        TypeofNENumber = 1 << 9,      // typeof x !== "number"
76        TypeofNEBigInt = 1 << 10,     // typeof x !== "bigint"
77        TypeofNEBoolean = 1 << 11,    // typeof x !== "boolean"
78        TypeofNESymbol = 1 << 12,     // typeof x !== "symbol"
79        TypeofNEObject = 1 << 13,     // typeof x !== "object"
80        TypeofNEFunction = 1 << 14,   // typeof x !== "function"
81        TypeofNEHostObject = 1 << 15, // typeof x !== "xxx"
82        EQUndefined = 1 << 16,        // x === undefined
83        EQNull = 1 << 17,             // x === null
84        EQUndefinedOrNull = 1 << 18,  // x === undefined / x === null
85        NEUndefined = 1 << 19,        // x !== undefined
86        NENull = 1 << 20,             // x !== null
87        NEUndefinedOrNull = 1 << 21,  // x != undefined / x != null
88        Truthy = 1 << 22,             // x
89        Falsy = 1 << 23,              // !x
90        IsUndefined = 1 << 24,        // Contains undefined or intersection with undefined
91        IsNull = 1 << 25,             // Contains null or intersection with null
92        IsUndefinedOrNull = IsUndefined | IsNull,
93        All = (1 << 27) - 1,
94        // The following members encode facts about particular kinds of types for use in the getTypeFacts function.
95        // The presence of a particular fact means that the given test is true for some (and possibly all) values
96        // of that kind of type.
97        BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull,
98        BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
99        StringStrictFacts = BaseStringStrictFacts | Truthy | Falsy,
100        StringFacts = BaseStringFacts | Truthy,
101        EmptyStringStrictFacts = BaseStringStrictFacts | Falsy,
102        EmptyStringFacts = BaseStringFacts,
103        NonEmptyStringStrictFacts = BaseStringStrictFacts | Truthy,
104        NonEmptyStringFacts = BaseStringFacts | Truthy,
105        BaseNumberStrictFacts = TypeofEQNumber | TypeofNEString | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull,
106        BaseNumberFacts = BaseNumberStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
107        NumberStrictFacts = BaseNumberStrictFacts | Truthy | Falsy,
108        NumberFacts = BaseNumberFacts | Truthy,
109        ZeroNumberStrictFacts = BaseNumberStrictFacts | Falsy,
110        ZeroNumberFacts = BaseNumberFacts,
111        NonZeroNumberStrictFacts = BaseNumberStrictFacts | Truthy,
112        NonZeroNumberFacts = BaseNumberFacts | Truthy,
113        BaseBigIntStrictFacts = TypeofEQBigInt | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull,
114        BaseBigIntFacts = BaseBigIntStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
115        BigIntStrictFacts = BaseBigIntStrictFacts | Truthy | Falsy,
116        BigIntFacts = BaseBigIntFacts | Truthy,
117        ZeroBigIntStrictFacts = BaseBigIntStrictFacts | Falsy,
118        ZeroBigIntFacts = BaseBigIntFacts,
119        NonZeroBigIntStrictFacts = BaseBigIntStrictFacts | Truthy,
120        NonZeroBigIntFacts = BaseBigIntFacts | Truthy,
121        BaseBooleanStrictFacts = TypeofEQBoolean | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull,
122        BaseBooleanFacts = BaseBooleanStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
123        BooleanStrictFacts = BaseBooleanStrictFacts | Truthy | Falsy,
124        BooleanFacts = BaseBooleanFacts | Truthy,
125        FalseStrictFacts = BaseBooleanStrictFacts | Falsy,
126        FalseFacts = BaseBooleanFacts,
127        TrueStrictFacts = BaseBooleanStrictFacts | Truthy,
128        TrueFacts = BaseBooleanFacts | Truthy,
129        SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy,
130        SymbolFacts = SymbolStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
131        ObjectStrictFacts = TypeofEQObject | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | NEUndefined | NENull | NEUndefinedOrNull | Truthy,
132        ObjectFacts = ObjectStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
133        FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy,
134        FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy,
135        VoidFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy,
136        UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined,
137        NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull,
138        EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull),
139        EmptyObjectFacts = All & ~IsUndefinedOrNull,
140        UnknownFacts = All & ~IsUndefinedOrNull,
141        AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined,
142        // Masks
143        OrFactsMask = TypeofEQFunction | TypeofNEObject,
144        AndFactsMask = All & ~OrFactsMask,
145    }
146
147    const typeofNEFacts: ReadonlyESMap<string, TypeFacts> = new Map(getEntries({
148        string: TypeFacts.TypeofNEString,
149        number: TypeFacts.TypeofNENumber,
150        bigint: TypeFacts.TypeofNEBigInt,
151        boolean: TypeFacts.TypeofNEBoolean,
152        symbol: TypeFacts.TypeofNESymbol,
153        undefined: TypeFacts.NEUndefined,
154        object: TypeFacts.TypeofNEObject,
155        function: TypeFacts.TypeofNEFunction
156    }));
157
158    type TypeSystemEntity = Node | Symbol | Type | Signature;
159
160    const enum TypeSystemPropertyName {
161        Type,
162        ResolvedBaseConstructorType,
163        DeclaredType,
164        ResolvedReturnType,
165        ImmediateBaseConstraint,
166        EnumTagType,
167        ResolvedTypeArguments,
168        ResolvedBaseTypes,
169        WriteType,
170    }
171
172    type AnnotationConstantExpressionType = number | string | boolean | AnnotationConstantExpressionType[];
173
174    export const enum CheckMode {
175        Normal = 0,                                     // Normal type checking
176        Contextual = 1 << 0,                            // Explicitly assigned contextual type, therefore not cacheable
177        Inferential = 1 << 1,                           // Inferential typing
178        SkipContextSensitive = 1 << 2,                  // Skip context sensitive function expressions
179        SkipGenericFunctions = 1 << 3,                  // Skip single signature generic functions
180        IsForSignatureHelp = 1 << 4,                    // Call resolution for purposes of signature help
181        IsForStringLiteralArgumentCompletions = 1 << 5, // Do not infer from the argument currently being typed
182        RestBindingElement = 1 << 6,                    // Checking a type that is going to be used to determine the type of a rest binding element
183                                                        //   e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`,
184                                                        //   we need to preserve generic types instead of substituting them for constraints
185        SkipEtsComponentBody = 1 << 7,                  // Not check body for Completion
186    }
187
188    export const enum SignatureCheckMode {
189        BivariantCallback = 1 << 0,
190        StrictCallback    = 1 << 1,
191        IgnoreReturnTypes = 1 << 2,
192        StrictArity       = 1 << 3,
193        Callback          = BivariantCallback | StrictCallback,
194    }
195
196    const enum IntersectionState {
197        None = 0,
198        Source = 1 << 0,
199        Target = 1 << 1,
200    }
201
202    const enum RecursionFlags {
203        None = 0,
204        Source = 1 << 0,
205        Target = 1 << 1,
206        Both = Source | Target,
207    }
208
209    const enum MappedTypeModifiers {
210        IncludeReadonly = 1 << 0,
211        ExcludeReadonly = 1 << 1,
212        IncludeOptional = 1 << 2,
213        ExcludeOptional = 1 << 3,
214    }
215
216    const enum ExpandingFlags {
217        None = 0,
218        Source = 1,
219        Target = 1 << 1,
220        Both = Source | Target,
221    }
222
223    const enum MembersOrExportsResolutionKind {
224        resolvedExports = "resolvedExports",
225        resolvedMembers = "resolvedMembers"
226    }
227
228    const enum UnusedKind {
229        Local,
230        Parameter,
231    }
232
233    /** @param containingNode Node to check for parse error */
234    type AddUnusedDiagnostic = (containingNode: Node, type: UnusedKind, diagnostic: DiagnosticWithLocation) => void;
235
236    const isNotOverloadAndNotAccessor = and(isNotOverload, isNotAccessor);
237
238    const enum DeclarationMeaning {
239        GetAccessor = 1,
240        SetAccessor = 2,
241        PropertyAssignment = 4,
242        Method = 8,
243        PrivateStatic = 16,
244        GetOrSetAccessor = GetAccessor | SetAccessor,
245        PropertyAssignmentOrMethod = PropertyAssignment | Method,
246    }
247
248    const enum DeclarationSpaces {
249        None = 0,
250        ExportValue = 1 << 0,
251        ExportType = 1 << 1,
252        ExportNamespace = 1 << 2,
253    }
254
255    const enum MinArgumentCountFlags {
256        None = 0,
257        StrongArityForUntypedJS = 1 << 0,
258        VoidIsNonOptional = 1 << 1,
259    }
260
261    const enum IntrinsicTypeKind {
262        Uppercase,
263        Lowercase,
264        Capitalize,
265        Uncapitalize
266    }
267
268    const intrinsicTypeKinds: ReadonlyESMap<string, IntrinsicTypeKind> = new Map(getEntries({
269        Uppercase: IntrinsicTypeKind.Uppercase,
270        Lowercase: IntrinsicTypeKind.Lowercase,
271        Capitalize: IntrinsicTypeKind.Capitalize,
272        Uncapitalize: IntrinsicTypeKind.Uncapitalize
273    }));
274
275    function SymbolLinks(this: SymbolLinks) {
276    }
277
278    function NodeLinks(this: NodeLinks) {
279        this.flags = 0;
280    }
281
282    export function getNodeId(node: Node): number {
283        if (!node.id) {
284            node.id = nextNodeId;
285            nextNodeId++;
286        }
287        return node.id;
288    }
289
290    export function getSymbolId(symbol: Symbol): SymbolId {
291        if (!symbol.id) {
292            symbol.id = nextSymbolId;
293            nextSymbolId++;
294        }
295
296        return symbol.id;
297    }
298
299    export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) {
300        const moduleState = getModuleInstanceState(node);
301        return moduleState === ModuleInstanceState.Instantiated ||
302            (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly);
303    }
304
305    export function createTypeChecker(host: TypeCheckerHost, isTypeCheckerForLinter: boolean = false): TypeChecker {
306        const getPackagesMap = memoize(() => {
307            // A package name maps to true when we detect it has .d.ts files.
308            // This is useful as an approximation of whether a package bundles its own types.
309            // Note: we only look at files already found by module resolution,
310            // so there may be files we did not consider.
311            const map = new Map<string, boolean>();
312            host.getSourceFiles().forEach(sf => {
313                if (!sf.resolvedModules) return;
314
315                sf.resolvedModules.forEach(r => {
316                    if (r && r.packageId) map.set(r.packageId.name, r.extension === Extension.Dts || !!map.get(r.packageId.name));
317                });
318            });
319            return map;
320        });
321
322        let deferredDiagnosticsCallbacks: (() => void)[] = [];
323
324        let addLazyDiagnostic = (arg: () => void) => {
325            deferredDiagnosticsCallbacks.push(arg);
326        };
327
328        // Cancellation that controls whether or not we can cancel in the middle of type checking.
329        // In general cancelling is *not* safe for the type checker.  We might be in the middle of
330        // computing something, and we will leave our internals in an inconsistent state.  Callers
331        // who set the cancellation token should catch if a cancellation exception occurs, and
332        // should throw away and create a new TypeChecker.
333        //
334        // Currently we only support setting the cancellation token when getting diagnostics.  This
335        // is because diagnostics can be quite expensive, and we want to allow hosts to bail out if
336        // they no longer need the information (for example, if the user started editing again).
337        let cancellationToken: CancellationToken | undefined;
338        let requestedExternalEmitHelpers: ExternalEmitHelpers;
339        let externalHelpersModule: Symbol;
340
341        const Symbol = objectAllocator.getSymbolConstructor();
342        const Type = objectAllocator.getTypeConstructor();
343        const Signature = objectAllocator.getSignatureConstructor();
344
345        let typeCount = 0;
346        let symbolCount = 0;
347        let enumCount = 0;
348        let totalInstantiationCount = 0;
349        let instantiationCount = 0;
350        let instantiationDepth = 0;
351        let inlineLevel = 0;
352        let currentNode: Node | undefined;
353        let varianceTypeParameter: TypeParameter | undefined;
354
355        const emptySymbols = createSymbolTable();
356        const arrayVariances = [VarianceFlags.Covariant];
357
358        let getJsDocNodeCheckedConfig = host.getJsDocNodeCheckedConfig;
359        let compilerOptions: CompilerOptions = {...host.getCompilerOptions()};
360
361        if (!!compilerOptions.needDoArkTsLinter) {
362            compilerOptions.skipLibCheck = false;
363        }
364
365        if (isTypeCheckerForLinter) {
366            // make the configuration as arkts linter required
367            compilerOptions.strictNullChecks = true;
368            compilerOptions.strictFunctionTypes = true;
369            compilerOptions.strictPropertyInitialization = true;
370            compilerOptions.noImplicitReturns = true;
371
372            getJsDocNodeCheckedConfig = undefined;
373        }
374
375        const languageVersion = getEmitScriptTarget(compilerOptions);
376        const moduleKind = getEmitModuleKind(compilerOptions);
377        const useDefineForClassFields = getUseDefineForClassFields(compilerOptions);
378        const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions);
379        const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
380        const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
381        const strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply");
382        const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization");
383        const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
384        const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
385        const useUnknownInCatchVariables = getStrictOptionValue(compilerOptions, "useUnknownInCatchVariables");
386        const keyofStringsOnly = !!compilerOptions.keyofStringsOnly;
387        const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral;
388        const exactOptionalPropertyTypes = compilerOptions.exactOptionalPropertyTypes;
389
390        const checkBinaryExpression = createCheckBinaryExpression();
391        const emitResolver = createResolver();
392        const nodeBuilder = createNodeBuilder();
393
394        const globals = createSymbolTable();
395        const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String);
396        undefinedSymbol.declarations = [];
397
398        const globalThisSymbol = createSymbol(SymbolFlags.Module, "globalThis" as __String, CheckFlags.Readonly);
399        globalThisSymbol.exports = globals;
400        globalThisSymbol.declarations = [];
401        globals.set(globalThisSymbol.escapedName, globalThisSymbol);
402
403        const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String);
404        const requireSymbol = createSymbol(SymbolFlags.Property, "require" as __String);
405
406        /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */
407        let apparentArgumentCount: number | undefined;
408
409        let constEnumRelate: ESMap<string, ESMap<string, string>> = new Map();
410
411        // for public members that accept a Node or one of its subtypes, we must guard against
412        // synthetic nodes created during transformations by calling `getParseTreeNode`.
413        // for most of these, we perform the guard only on `checker` to avoid any possible
414        // extra cost of calling `getParseTreeNode` when calling these functions from inside the
415        // checker.
416        const checker: TypeChecker = {
417            getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"),
418            getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"),
419            getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount,
420            getTypeCount: () => typeCount,
421            getInstantiationCount: () => totalInstantiationCount,
422            getRelationCacheSizes: () => ({
423                assignable: assignableRelation.size,
424                identity: identityRelation.size,
425                subtype: subtypeRelation.size,
426                strictSubtype: strictSubtypeRelation.size,
427            }),
428            isUndefinedSymbol: symbol => symbol === undefinedSymbol,
429            isArgumentsSymbol: symbol => symbol === argumentsSymbol,
430            isUnknownSymbol: symbol => symbol === unknownSymbol,
431            getMergedSymbol,
432            getDiagnostics,
433            getGlobalDiagnostics,
434            getRecursionIdentity,
435            getUnmatchedProperties,
436            getTypeOfSymbolAtLocation: (symbol, locationIn) => {
437                const location = getParseTreeNode(locationIn);
438                return location ? getTypeOfSymbolAtLocation(symbol, location) : errorType;
439            },
440            getTypeOfSymbol,
441            getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => {
442                const parameter = getParseTreeNode(parameterIn, isParameter);
443                if (parameter === undefined) return Debug.fail("Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node.");
444                return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName));
445            },
446            getDeclaredTypeOfSymbol,
447            getPropertiesOfType,
448            getPropertyOfType: (type, name) => getPropertyOfType(type, escapeLeadingUnderscores(name)),
449            getPrivateIdentifierPropertyOfType: (leftType: Type, name: string, location: Node) => {
450                const node = getParseTreeNode(location);
451                if (!node) {
452                    return undefined;
453                }
454                const propName = escapeLeadingUnderscores(name);
455                const lexicallyScopedIdentifier = lookupSymbolForPrivateIdentifierDeclaration(propName, node);
456                return lexicallyScopedIdentifier ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedIdentifier) : undefined;
457            },
458            getTypeOfPropertyOfType: (type, name) => getTypeOfPropertyOfType(type, escapeLeadingUnderscores(name)),
459            getIndexInfoOfType: (type, kind) => getIndexInfoOfType(type, kind === IndexKind.String ? stringType : numberType),
460            getIndexInfosOfType,
461            getIndexInfosOfIndexSymbol,
462            getSignaturesOfType,
463            getIndexTypeOfType: (type, kind) => getIndexTypeOfType(type, kind === IndexKind.String ? stringType : numberType),
464            getIndexType: type => getIndexType(type),
465            getBaseTypes,
466            getBaseTypeOfLiteralType,
467            getWidenedType,
468            getTypeFromTypeNode: nodeIn => {
469                const node = getParseTreeNode(nodeIn, isTypeNode);
470                return node ? getTypeFromTypeNode(node) : errorType;
471            },
472            getParameterType: getTypeAtPosition,
473            getParameterIdentifierNameAtPosition,
474            getPromisedTypeOfPromise,
475            getAwaitedType: type => getAwaitedType(type),
476            getReturnTypeOfSignature,
477            isNullableType,
478            getNullableType,
479            getNonNullableType,
480            getNonOptionalType: removeOptionalTypeMarker,
481            getTypeArguments,
482            typeToTypeNode: nodeBuilder.typeToTypeNode,
483            indexInfoToIndexSignatureDeclaration: nodeBuilder.indexInfoToIndexSignatureDeclaration,
484            signatureToSignatureDeclaration: nodeBuilder.signatureToSignatureDeclaration,
485            symbolToEntityName: nodeBuilder.symbolToEntityName,
486            symbolToExpression: nodeBuilder.symbolToExpression,
487            symbolToNode: nodeBuilder.symbolToNode,
488            symbolToTypeParameterDeclarations: nodeBuilder.symbolToTypeParameterDeclarations,
489            symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration,
490            typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration,
491            getSymbolsInScope: (locationIn, meaning) => {
492                const location = getParseTreeNode(locationIn);
493                return location ? getSymbolsInScope(location, meaning) : [];
494            },
495            getSymbolAtLocation: nodeIn => {
496                const node = getParseTreeNode(nodeIn);
497                // set ignoreErrors: true because any lookups invoked by the API shouldn't cause any new errors
498                return node ? getSymbolAtLocation(node, /*ignoreErrors*/ true) : undefined;
499            },
500            getIndexInfosAtLocation: nodeIn => {
501                const node = getParseTreeNode(nodeIn);
502                return node ? getIndexInfosAtLocation(node) : undefined;
503            },
504            getShorthandAssignmentValueSymbol: nodeIn => {
505                const node = getParseTreeNode(nodeIn);
506                return node ? getShorthandAssignmentValueSymbol(node) : undefined;
507            },
508            getExportSpecifierLocalTargetSymbol: nodeIn => {
509                const node = getParseTreeNode(nodeIn, isExportSpecifier);
510                return node ? getExportSpecifierLocalTargetSymbol(node) : undefined;
511            },
512            getExportSymbolOfSymbol(symbol) {
513                return getMergedSymbol(symbol.exportSymbol || symbol);
514            },
515            getTypeAtLocation: nodeIn => {
516                const node = getParseTreeNode(nodeIn);
517                return node ? getTypeOfNode(node) : errorType;
518            },
519            tryGetTypeAtLocationWithoutCheck: nodeIn => {
520                const node = getParseTreeNode(nodeIn);
521                return node ? tryGetTypeOfNodeWithoutCheck(node) : errorType;
522            },
523            getTypeOfAssignmentPattern: nodeIn => {
524                const node = getParseTreeNode(nodeIn, isAssignmentPattern);
525                return node && getTypeOfAssignmentPattern(node) || errorType;
526            },
527            getPropertySymbolOfDestructuringAssignment: locationIn => {
528                const location = getParseTreeNode(locationIn, isIdentifier);
529                return location ? getPropertySymbolOfDestructuringAssignment(location) : undefined;
530            },
531            signatureToString: (signature, enclosingDeclaration, flags, kind) => {
532                return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind);
533            },
534            typeToString: (type, enclosingDeclaration, flags) => {
535                return typeToString(type, getParseTreeNode(enclosingDeclaration), flags);
536            },
537            symbolToString: (symbol, enclosingDeclaration, meaning, flags) => {
538                return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning, flags);
539            },
540            typePredicateToString: (predicate, enclosingDeclaration, flags) => {
541                return typePredicateToString(predicate, getParseTreeNode(enclosingDeclaration), flags);
542            },
543            writeSignature: (signature, enclosingDeclaration, flags, kind, writer) => {
544                return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind, writer);
545            },
546            writeType: (type, enclosingDeclaration, flags, writer) => {
547                return typeToString(type, getParseTreeNode(enclosingDeclaration), flags, writer);
548            },
549            writeSymbol: (symbol, enclosingDeclaration, meaning, flags, writer) => {
550                return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning, flags, writer);
551            },
552            writeTypePredicate: (predicate, enclosingDeclaration, flags, writer) => {
553                return typePredicateToString(predicate, getParseTreeNode(enclosingDeclaration), flags, writer);
554            },
555            getAugmentedPropertiesOfType,
556            getRootSymbols,
557            getSymbolOfExpando,
558            getContextualType: (nodeIn: Expression, contextFlags?: ContextFlags) => {
559                const node = getParseTreeNode(nodeIn, isExpression);
560                if (!node) {
561                    return undefined;
562                }
563                if (contextFlags! & ContextFlags.Completions) {
564                    return runWithInferenceBlockedFromSourceNode(node, () => getContextualType(node, contextFlags));
565                }
566                return getContextualType(node, contextFlags);
567            },
568            getContextualTypeForObjectLiteralElement: nodeIn => {
569                const node = getParseTreeNode(nodeIn, isObjectLiteralElementLike);
570                return node ? getContextualTypeForObjectLiteralElement(node, /*contextFlags*/ undefined) : undefined;
571            },
572            getContextualTypeForArgumentAtIndex: (nodeIn, argIndex) => {
573                const node = getParseTreeNode(nodeIn, isCallLikeExpression);
574                return node && getContextualTypeForArgumentAtIndex(node, argIndex);
575            },
576            getContextualTypeForJsxAttribute: (nodeIn) => {
577                const node = getParseTreeNode(nodeIn, isJsxAttributeLike);
578                return node && getContextualTypeForJsxAttribute(node, /*contextFlags*/ undefined);
579            },
580            isContextSensitive,
581            getTypeOfPropertyOfContextualType,
582            getFullyQualifiedName,
583            tryGetResolvedSignatureWithoutCheck: (node, candidatesOutArray, argumentCount) =>
584                getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.SkipEtsComponentBody),
585            getResolvedSignature: (node, candidatesOutArray, argumentCount) =>
586                getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal),
587            getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray) =>
588                getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument),
589            getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) =>
590                getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp),
591            getExpandedParameters,
592            hasEffectiveRestParameter,
593            containsArgumentsReference,
594            getConstantValue: nodeIn => {
595                const node = getParseTreeNode(nodeIn, canHaveConstantValue);
596                return node ? getConstantValue(node) : undefined;
597            },
598            isValidPropertyAccess: (nodeIn, propertyName) => {
599                const node = getParseTreeNode(nodeIn, isPropertyAccessOrQualifiedNameOrImportTypeNode);
600                return !!node && isValidPropertyAccess(node, escapeLeadingUnderscores(propertyName));
601            },
602            isValidPropertyAccessForCompletions: (nodeIn, type, property) => {
603                const node = getParseTreeNode(nodeIn, isPropertyAccessExpression);
604                return !!node && isValidPropertyAccessForCompletions(node, type, property);
605            },
606            getSignatureFromDeclaration: declarationIn => {
607                const declaration = getParseTreeNode(declarationIn, isFunctionLike);
608                return declaration ? getSignatureFromDeclaration(declaration) : undefined;
609            },
610            isImplementationOfOverload: nodeIn => {
611                const node = getParseTreeNode(nodeIn, isFunctionLike);
612                return node ? isImplementationOfOverload(node) : undefined;
613            },
614            getImmediateAliasedSymbol,
615            getAliasedSymbol: resolveAlias,
616            getEmitResolver,
617            getExportsOfModule: getExportsOfModuleAsArray,
618            getExportsAndPropertiesOfModule,
619            forEachExportAndPropertyOfModule,
620            getSymbolWalker: createGetSymbolWalker(
621                getRestTypeOfSignature,
622                getTypePredicateOfSignature,
623                getReturnTypeOfSignature,
624                getBaseTypes,
625                resolveStructuredTypeMembers,
626                getTypeOfSymbol,
627                getResolvedSymbol,
628                getConstraintOfTypeParameter,
629                getFirstIdentifier,
630                getTypeArguments,
631            ),
632            getAmbientModules,
633            getJsxIntrinsicTagNamesAt,
634            isOptionalParameter: nodeIn => {
635                const node = getParseTreeNode(nodeIn, isParameter);
636                return node ? isOptionalParameter(node) : false;
637            },
638            tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol),
639            tryGetMemberInModuleExportsAndProperties: (name, symbol) => tryGetMemberInModuleExportsAndProperties(escapeLeadingUnderscores(name), symbol),
640            tryFindAmbientModule: moduleName => tryFindAmbientModule(moduleName, /*withAugmentations*/ true),
641            tryFindAmbientModuleWithoutAugmentations: moduleName => {
642                // we deliberately exclude augmentations
643                // since we are only interested in declarations of the module itself
644                return tryFindAmbientModule(moduleName, /*withAugmentations*/ false);
645            },
646            getApparentType,
647            getUnionType,
648            isTypeAssignableTo,
649            createAnonymousType,
650            createSignature,
651            createSymbol,
652            createIndexInfo,
653            getAnyType: () => anyType,
654            getStringType: () => stringType,
655            getNumberType: () => numberType,
656            createPromiseType,
657            createArrayType,
658            getElementTypeOfArrayType,
659            getBooleanType: () => booleanType,
660            getFalseType: (fresh?) => fresh ? falseType : regularFalseType,
661            getTrueType: (fresh?) => fresh ? trueType : regularTrueType,
662            getVoidType: () => voidType,
663            getUndefinedType: () => undefinedType,
664            getNullType: () => nullType,
665            getESSymbolType: () => esSymbolType,
666            getNeverType: () => neverType,
667            getOptionalType: () => optionalType,
668            getPromiseType: () => getGlobalPromiseType(/*reportErrors*/ false),
669            getPromiseLikeType: () => getGlobalPromiseLikeType(/*reportErrors*/ false),
670            getAsyncIterableType: () => {
671                const type = getGlobalAsyncIterableType(/*reportErrors*/ false);
672                if (type === emptyGenericType) return undefined;
673                return type;
674            },
675            isSymbolAccessible,
676            isArrayType,
677            isTupleType,
678            isArrayLikeType,
679            isTypeInvalidDueToUnionDiscriminant,
680            getExactOptionalProperties,
681            getAllPossiblePropertiesOfTypes,
682            getSuggestedSymbolForNonexistentProperty,
683            getSuggestionForNonexistentProperty,
684            getSuggestedSymbolForNonexistentJSXAttribute,
685            getSuggestedSymbolForNonexistentSymbol: (location, name, meaning) => getSuggestedSymbolForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
686            getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
687            getSuggestedSymbolForNonexistentModule,
688            getSuggestionForNonexistentExport,
689            getSuggestedSymbolForNonexistentClassMember,
690            getBaseConstraintOfType,
691            getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined,
692            resolveName(name, location, meaning, excludeGlobals) {
693                return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals);
694            },
695            getJsxNamespace: n => unescapeLeadingUnderscores(getJsxNamespace(n)),
696            getJsxFragmentFactory: n => {
697                const jsxFragmentFactory = getJsxFragmentFactoryEntity(n);
698                return jsxFragmentFactory && unescapeLeadingUnderscores(getFirstIdentifier(jsxFragmentFactory).escapedText);
699            },
700            getAccessibleSymbolChain,
701            getTypePredicateOfSignature,
702            resolveExternalModuleName: moduleSpecifierIn => {
703                const moduleSpecifier = getParseTreeNode(moduleSpecifierIn, isExpression);
704                return moduleSpecifier && resolveExternalModuleName(moduleSpecifier, moduleSpecifier, /*ignoreErrors*/ true);
705            },
706            resolveExternalModuleSymbol,
707            tryGetThisTypeAt: (nodeIn, includeGlobalThis, container) => {
708                const node = getParseTreeNode(nodeIn);
709                return node && tryGetThisTypeAt(node, includeGlobalThis, container);
710            },
711            getTypeArgumentConstraint: nodeIn => {
712                const node = getParseTreeNode(nodeIn, isTypeNode);
713                return node && getTypeArgumentConstraint(node);
714            },
715            getSuggestionDiagnostics: (fileIn, ct) => {
716                const file = getParseTreeNode(fileIn, isSourceFile) || Debug.fail("Could not determine parsed source file.");
717                if (skipTypeChecking(file, compilerOptions, host) || (file.isDeclarationFile && !!compilerOptions.needDoArkTsLinter)) {
718                    return emptyArray;
719                }
720
721                let diagnostics: DiagnosticWithLocation[] | undefined;
722                try {
723                    // Record the cancellation token so it can be checked later on during checkSourceElement.
724                    // Do this in a finally block so we can ensure that it gets reset back to nothing after
725                    // this call is done.
726                    cancellationToken = ct;
727
728                    // Ensure file is type checked, with _eager_ diagnostic production, so identifiers are registered as potentially unused
729                    checkSourceFileWithEagerDiagnostics(file);
730                    Debug.assert(!!(getNodeLinks(file).flags & NodeCheckFlags.TypeChecked));
731
732                    diagnostics = addRange(diagnostics, suggestionDiagnostics.getDiagnostics(file.fileName));
733                    checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (containingNode, kind, diag) => {
734                        if (!containsParseError(containingNode) && !unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) {
735                            (diagnostics || (diagnostics = [])).push({ ...diag, category: DiagnosticCategory.Suggestion });
736                        }
737                    });
738
739                    return diagnostics || emptyArray;
740                }
741                finally {
742                    cancellationToken = undefined;
743                }
744            },
745
746            runWithCancellationToken: (token, callback) => {
747                try {
748                    cancellationToken = token;
749                    return callback(checker);
750                }
751                finally {
752                    cancellationToken = undefined;
753                }
754            },
755
756            getLocalTypeParametersOfClassOrInterfaceOrTypeAlias,
757            isDeclarationVisible,
758            isPropertyAccessible,
759            getTypeOnlyAliasDeclaration,
760            getMemberOverrideModifierStatus,
761            isTypeParameterPossiblyReferenced,
762            getConstEnumRelate: () => constEnumRelate,
763            clearConstEnumRelate: () => {constEnumRelate && constEnumRelate.clear()},
764            deleteConstEnumRelate: (path: string) => {constEnumRelate && constEnumRelate.delete(path)},
765        };
766
767        function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
768            const containingCall = findAncestor(node, isCallLikeExpression);
769            const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
770            if (containingCall) {
771                let toMarkSkip = node!;
772                do {
773                    getNodeLinks(toMarkSkip).skipDirectInference = true;
774                    toMarkSkip = toMarkSkip.parent;
775                } while (toMarkSkip && toMarkSkip !== containingCall);
776                getNodeLinks(containingCall).resolvedSignature = undefined;
777            }
778            const result = fn();
779            if (containingCall) {
780                let toMarkSkip = node!;
781                do {
782                    getNodeLinks(toMarkSkip).skipDirectInference = undefined;
783                    toMarkSkip = toMarkSkip.parent;
784                } while (toMarkSkip && toMarkSkip !== containingCall);
785                getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
786            }
787            return result;
788        }
789
790        function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: Node): Signature | undefined {
791            const node = getParseTreeNode(nodeIn, isCallLikeExpression);
792            apparentArgumentCount = argumentCount;
793            const res =
794                !node ? undefined :
795                editingArgument ? runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignature(node, candidatesOutArray, checkMode)) :
796                getResolvedSignature(node, candidatesOutArray, checkMode);
797            apparentArgumentCount = undefined;
798            return res;
799        }
800
801        const tupleTypes = new Map<string, GenericType>();
802        const unionTypes = new Map<string, UnionType>();
803        const intersectionTypes = new Map<string, Type>();
804        const stringLiteralTypes = new Map<string, StringLiteralType>();
805        const numberLiteralTypes = new Map<number, NumberLiteralType>();
806        const bigIntLiteralTypes = new Map<string, BigIntLiteralType>();
807        const enumLiteralTypes = new Map<string, LiteralType>();
808        const indexedAccessTypes = new Map<string, IndexedAccessType>();
809        const templateLiteralTypes = new Map<string, TemplateLiteralType>();
810        const stringMappingTypes = new Map<string, StringMappingType>();
811        const substitutionTypes = new Map<string, SubstitutionType>();
812        const subtypeReductionCache = new Map<string, Type[]>();
813        const cachedTypes = new Map<string, Type>();
814        const evolvingArrayTypes: EvolvingArrayType[] = [];
815        const undefinedProperties: SymbolTable = new Map();
816        const markerTypes = new Set<number>();
817
818        const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as __String);
819        const resolvingSymbol = createSymbol(0, InternalSymbolName.Resolving);
820        const unresolvedSymbols = new Map<string, TransientSymbol>();
821        const errorTypes = new Map<string, Type>();
822
823        const anyType = createIntrinsicType(TypeFlags.Any, "any");
824        const autoType = createIntrinsicType(TypeFlags.Any, "any", ObjectFlags.NonInferrableType);
825        const wildcardType = createIntrinsicType(TypeFlags.Any, "any");
826        const errorType = createIntrinsicType(TypeFlags.Any, "error");
827        const unresolvedType = createIntrinsicType(TypeFlags.Any, "unresolved");
828        const nonInferrableAnyType = createIntrinsicType(TypeFlags.Any, "any", ObjectFlags.ContainsWideningType);
829        const intrinsicMarkerType = createIntrinsicType(TypeFlags.Any, "intrinsic");
830        const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown");
831        const nonNullUnknownType = createIntrinsicType(TypeFlags.Unknown, "unknown");
832        const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
833        const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType);
834        const optionalType = createIntrinsicType(TypeFlags.Undefined, "undefined");
835        const missingType = exactOptionalPropertyTypes ? createIntrinsicType(TypeFlags.Undefined, "undefined") : undefinedType;
836        const nullType = createIntrinsicType(TypeFlags.Null, "null");
837        const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType);
838        const stringType = createIntrinsicType(TypeFlags.String, "string");
839        const numberType = createIntrinsicType(TypeFlags.Number, "number");
840        const bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint");
841        const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType;
842        const regularFalseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType;
843        const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType;
844        const regularTrueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType;
845        trueType.regularType = regularTrueType;
846        trueType.freshType = trueType;
847        regularTrueType.regularType = regularTrueType;
848        regularTrueType.freshType = trueType;
849        falseType.regularType = regularFalseType;
850        falseType.freshType = falseType;
851        regularFalseType.regularType = regularFalseType;
852        regularFalseType.freshType = falseType;
853        const booleanType = getUnionType([regularFalseType, regularTrueType]);
854        const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
855        const voidType = createIntrinsicType(TypeFlags.Void, "void");
856        const neverType = createIntrinsicType(TypeFlags.Never, "never");
857        const silentNeverType = createIntrinsicType(TypeFlags.Never, "never", ObjectFlags.NonInferrableType);
858        const implicitNeverType = createIntrinsicType(TypeFlags.Never, "never");
859        const unreachableNeverType = createIntrinsicType(TypeFlags.Never, "never");
860        const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object");
861        const stringOrNumberType = getUnionType([stringType, numberType]);
862        const stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]);
863        const keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType;
864        const numberOrBigIntType = getUnionType([numberType, bigintType]);
865        const templateConstraintType = getUnionType([stringType, numberType, booleanType, bigintType, nullType, undefinedType]) as UnionType;
866        const numericStringType = getTemplateLiteralType(["", ""], [numberType]);  // The `${number}` type
867
868        const restrictiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? getRestrictiveTypeParameter(t as TypeParameter) : t, () => "(restrictive mapper)");
869        const permissiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? wildcardType : t, () => "(permissive mapper)");
870        const uniqueLiteralType = createIntrinsicType(TypeFlags.Never, "never"); // `uniqueLiteralType` is a special `never` flagged by union reduction to behave as a literal
871        const uniqueLiteralMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? uniqueLiteralType : t, () => "(unique literal mapper)"); // replace all type parameters with the unique literal type (disregarding constraints)
872        let outofbandVarianceMarkerHandler: ((onlyUnreliable: boolean) => void) | undefined;
873        const reportUnreliableMapper = makeFunctionTypeMapper(t => {
874            if (outofbandVarianceMarkerHandler && (t === markerSuperType || t === markerSubType || t === markerOtherType)) {
875                outofbandVarianceMarkerHandler(/*onlyUnreliable*/ true);
876            }
877            return t;
878        }, () => "(unmeasurable reporter)");
879        const reportUnmeasurableMapper = makeFunctionTypeMapper(t => {
880            if (outofbandVarianceMarkerHandler && (t === markerSuperType || t === markerSubType || t === markerOtherType)) {
881                outofbandVarianceMarkerHandler(/*onlyUnreliable*/ false);
882            }
883            return t;
884        }, () => "(unreliable reporter)");
885
886        const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
887        const emptyJsxObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
888        emptyJsxObjectType.objectFlags |= ObjectFlags.JsxAttributes;
889
890        const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
891        emptyTypeLiteralSymbol.members = createSymbolTable();
892        const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, emptyArray);
893
894        const unknownEmptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
895        const unknownUnionType = strictNullChecks ? getUnionType([undefinedType, nullType, unknownEmptyObjectType]) : unknownType;
896
897        const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray) as ObjectType as GenericType;
898        emptyGenericType.instantiations = new Map<string, TypeReference>();
899
900        const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
901        // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated
902        // in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes.
903        anyFunctionType.objectFlags |= ObjectFlags.NonInferrableType;
904
905        const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
906        const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
907        const resolvingDefaultType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
908
909        const markerSuperType = createTypeParameter();
910        const markerSubType = createTypeParameter();
911        markerSubType.constraint = markerSuperType;
912        const markerOtherType = createTypeParameter();
913
914        const markerSuperTypeForCheck = createTypeParameter();
915        const markerSubTypeForCheck = createTypeParameter();
916        markerSubTypeForCheck.constraint = markerSuperTypeForCheck;
917
918        const noTypePredicate = createTypePredicate(TypePredicateKind.Identifier, "<<unresolved>>", 0, anyType);
919
920        const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
921        const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
922        const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
923        const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
924        const annotationDefaultSignature = createSignature(undefined, undefined, undefined, emptyArray, voidType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
925
926        const enumNumberIndexInfo = createIndexInfo(numberType, stringType, /*isReadonly*/ true);
927
928        const iterationTypesCache = new Map<string, IterationTypes>(); // cache for common IterationTypes instances
929        const noIterationTypes: IterationTypes = {
930            get yieldType(): Type { return Debug.fail("Not supported"); },
931            get returnType(): Type { return Debug.fail("Not supported"); },
932            get nextType(): Type { return Debug.fail("Not supported"); },
933        };
934
935        const anyIterationTypes = createIterationTypes(anyType, anyType, anyType);
936        const anyIterationTypesExceptNext = createIterationTypes(anyType, anyType, unknownType);
937        const defaultIterationTypes = createIterationTypes(neverType, anyType, undefinedType); // default iteration types for `Iterator`.
938
939        const asyncIterationTypesResolver: IterationTypesResolver = {
940            iterableCacheKey: "iterationTypesOfAsyncIterable",
941            iteratorCacheKey: "iterationTypesOfAsyncIterator",
942            iteratorSymbolName: "asyncIterator",
943            getGlobalIteratorType: getGlobalAsyncIteratorType,
944            getGlobalIterableType: getGlobalAsyncIterableType,
945            getGlobalIterableIteratorType: getGlobalAsyncIterableIteratorType,
946            getGlobalGeneratorType: getGlobalAsyncGeneratorType,
947            resolveIterationType: getAwaitedType,
948            mustHaveANextMethodDiagnostic: Diagnostics.An_async_iterator_must_have_a_next_method,
949            mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_async_iterator_must_be_a_method,
950            mustHaveAValueDiagnostic: Diagnostics.The_type_returned_by_the_0_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property,
951        };
952
953        const syncIterationTypesResolver: IterationTypesResolver = {
954            iterableCacheKey: "iterationTypesOfIterable",
955            iteratorCacheKey: "iterationTypesOfIterator",
956            iteratorSymbolName: "iterator",
957            getGlobalIteratorType,
958            getGlobalIterableType,
959            getGlobalIterableIteratorType,
960            getGlobalGeneratorType,
961            resolveIterationType: (type, _errorNode) => type,
962            mustHaveANextMethodDiagnostic: Diagnostics.An_iterator_must_have_a_next_method,
963            mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_iterator_must_be_a_method,
964            mustHaveAValueDiagnostic: Diagnostics.The_type_returned_by_the_0_method_of_an_iterator_must_have_a_value_property,
965        };
966
967        interface DuplicateInfoForSymbol {
968            readonly firstFileLocations: Declaration[];
969            readonly secondFileLocations: Declaration[];
970            readonly isBlockScoped: boolean;
971        }
972        interface DuplicateInfoForFiles {
973            readonly firstFile: SourceFile;
974            readonly secondFile: SourceFile;
975            /** Key is symbol name. */
976            readonly conflictingSymbols: ESMap<string, DuplicateInfoForSymbol>;
977        }
978        /** Key is "/path/to/a.ts|/path/to/b.ts". */
979        let amalgamatedDuplicates: ESMap<string, DuplicateInfoForFiles> | undefined;
980        const reverseMappedCache = new Map<string, Type | undefined>();
981        let inInferTypeForHomomorphicMappedType = false;
982        let ambientModulesCache: Symbol[] | undefined;
983        /**
984         * List of every ambient module with a "*" wildcard.
985         * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches.
986         * This is only used if there is no exact match.
987         */
988        let patternAmbientModules: PatternAmbientModule[];
989        let patternAmbientModuleAugmentations: ESMap<string, Symbol> | undefined;
990
991        let globalObjectType: ObjectType;
992        let globalFunctionType: ObjectType;
993        let globalCallableFunctionType: ObjectType;
994        let globalNewableFunctionType: ObjectType;
995        let globalArrayType: GenericType;
996        let globalReadonlyArrayType: GenericType;
997        let globalStringType: ObjectType;
998        let globalNumberType: ObjectType;
999        let globalBooleanType: ObjectType;
1000        let globalRegExpType: ObjectType;
1001        let globalThisType: GenericType;
1002        let anyArrayType: Type;
1003        let autoArrayType: Type;
1004        let anyReadonlyArrayType: Type;
1005        let deferredGlobalNonNullableTypeAlias: Symbol;
1006
1007        // The library files are only loaded when the feature is used.
1008        // This allows users to just specify library files they want to used through --lib
1009        // and they will not get an error from not having unrelated library files
1010        let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
1011        let deferredGlobalESSymbolConstructorTypeSymbol: Symbol | undefined;
1012        let deferredGlobalESSymbolType: ObjectType | undefined;
1013        let deferredGlobalTypedPropertyDescriptorType: GenericType;
1014        let deferredGlobalPromiseType: GenericType | undefined;
1015        let deferredGlobalPromiseLikeType: GenericType | undefined;
1016        let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
1017        let deferredGlobalPromiseConstructorLikeType: ObjectType | undefined;
1018        let deferredGlobalIterableType: GenericType | undefined;
1019        let deferredGlobalIteratorType: GenericType | undefined;
1020        let deferredGlobalIterableIteratorType: GenericType | undefined;
1021        let deferredGlobalGeneratorType: GenericType | undefined;
1022        let deferredGlobalIteratorYieldResultType: GenericType | undefined;
1023        let deferredGlobalIteratorReturnResultType: GenericType | undefined;
1024        let deferredGlobalAsyncIterableType: GenericType | undefined;
1025        let deferredGlobalAsyncIteratorType: GenericType | undefined;
1026        let deferredGlobalAsyncIterableIteratorType: GenericType | undefined;
1027        let deferredGlobalAsyncGeneratorType: GenericType | undefined;
1028        let deferredGlobalTemplateStringsArrayType: ObjectType | undefined;
1029        let deferredGlobalImportMetaType: ObjectType;
1030        let deferredGlobalImportMetaExpressionType: ObjectType;
1031        let deferredGlobalImportCallOptionsType: ObjectType | undefined;
1032        let deferredGlobalExtractSymbol: Symbol | undefined;
1033        let deferredGlobalOmitSymbol: Symbol | undefined;
1034        let deferredGlobalAwaitedSymbol: Symbol | undefined;
1035        let deferredGlobalBigIntType: ObjectType | undefined;
1036        let deferredGlobalNaNSymbol: Symbol | undefined;
1037        let deferredGlobalRecordSymbol: Symbol | undefined;
1038
1039        const allPotentiallyUnusedIdentifiers = new Map<Path, PotentiallyUnusedIdentifier[]>(); // key is file name
1040
1041        let flowLoopStart = 0;
1042        let flowLoopCount = 0;
1043        let sharedFlowCount = 0;
1044        let flowAnalysisDisabled = false;
1045        let flowInvocationCount = 0;
1046        let lastFlowNode: FlowNode | undefined;
1047        let lastFlowNodeReachable: boolean;
1048        let flowTypeCache: Type[] | undefined;
1049
1050        const emptyStringType = getStringLiteralType("");
1051        const zeroType = getNumberLiteralType(0);
1052        const zeroBigIntType = getBigIntLiteralType({ negative: false, base10Value: "0" });
1053
1054        const resolutionTargets: TypeSystemEntity[] = [];
1055        const resolutionResults: boolean[] = [];
1056        const resolutionPropertyNames: TypeSystemPropertyName[] = [];
1057
1058        let suggestionCount = 0;
1059        const maximumSuggestionCount = 10;
1060        const mergedSymbols: Symbol[] = [];
1061        const symbolLinks: SymbolLinks[] = [];
1062        const nodeLinks: NodeLinks[] = [];
1063        const flowLoopCaches: ESMap<string, Type>[] = [];
1064        const flowLoopNodes: FlowNode[] = [];
1065        const flowLoopKeys: string[] = [];
1066        const flowLoopTypes: Type[][] = [];
1067        const sharedFlowNodes: FlowNode[] = [];
1068        const sharedFlowTypes: FlowType[] = [];
1069        const flowNodeReachable: (boolean | undefined)[] = [];
1070        const flowNodePostSuper: (boolean | undefined)[] = [];
1071        const potentialThisCollisions: Node[] = [];
1072        const potentialNewTargetCollisions: Node[] = [];
1073        const potentialWeakMapSetCollisions: Node[] = [];
1074        const potentialReflectCollisions: Node[] = [];
1075        const potentialUnusedRenamedBindingElementsInTypes: BindingElement[] = [];
1076        const awaitedTypeStack: number[] = [];
1077
1078        const diagnostics = createDiagnosticCollection();
1079        const suggestionDiagnostics = createDiagnosticCollection();
1080
1081        const typeofType = createTypeofType();
1082
1083        let _jsxNamespace: __String;
1084        let _jsxFactoryEntity: EntityName | undefined;
1085
1086        const subtypeRelation = new Map<string, RelationComparisonResult>();
1087        const strictSubtypeRelation = new Map<string, RelationComparisonResult>();
1088        const assignableRelation = new Map<string, RelationComparisonResult>();
1089        const comparableRelation = new Map<string, RelationComparisonResult>();
1090        const identityRelation = new Map<string, RelationComparisonResult>();
1091        const enumRelation = new Map<string, RelationComparisonResult>();
1092
1093        const builtinGlobals = createSymbolTable();
1094        builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol);
1095
1096        // Extensions suggested for path imports when module resolution is node16 or higher.
1097        // The first element of each tuple is the extension a file has.
1098        // The second element of each tuple is the extension that should be used in a path import.
1099        // e.g. if we want to import file `foo.mts`, we should write `import {} from "./foo.mjs".
1100        const suggestedExtensions: [string, string][] = [
1101            [".mts", ".mjs"],
1102            [".ts", ".js"],
1103            [".cts", ".cjs"],
1104            [".mjs", ".mjs"],
1105            [".js", ".js"],
1106            [".cjs", ".cjs"],
1107            [".tsx", compilerOptions.jsx === JsxEmit.Preserve ? ".jsx" : ".js"],
1108            [".jsx", ".jsx"],
1109            [".json", ".json"],
1110        ];
1111
1112        let jsDocFileCheckInfo: FileCheckModuleInfo = {
1113            fileNeedCheck: false,
1114            checkPayload: undefined,
1115            currentFileName: "",
1116        }
1117
1118        initializeTypeChecker();
1119
1120        return checker;
1121
1122        function getCachedType(key: string | undefined) {
1123            return key ? cachedTypes.get(key) : undefined;
1124        }
1125
1126        function setCachedType(key: string | undefined, type: Type) {
1127            if (key) cachedTypes.set(key, type);
1128            return type;
1129        }
1130
1131        function getJsxNamespace(location: Node | undefined): __String {
1132            if (location) {
1133                const file = getSourceFileOfNode(location);
1134                if (file) {
1135                    if (isJsxOpeningFragment(location)) {
1136                        if (file.localJsxFragmentNamespace) {
1137                            return file.localJsxFragmentNamespace;
1138                        }
1139                        const jsxFragmentPragma = file.pragmas.get("jsxfrag");
1140                        if (jsxFragmentPragma) {
1141                            const chosenPragma = isArray(jsxFragmentPragma) ? jsxFragmentPragma[0] : jsxFragmentPragma;
1142                            file.localJsxFragmentFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion);
1143                            visitNode(file.localJsxFragmentFactory, markAsSynthetic);
1144                            if (file.localJsxFragmentFactory) {
1145                                return file.localJsxFragmentNamespace = getFirstIdentifier(file.localJsxFragmentFactory).escapedText;
1146                            }
1147                        }
1148                        const entity = getJsxFragmentFactoryEntity(location);
1149                        if (entity) {
1150                            file.localJsxFragmentFactory = entity;
1151                            return file.localJsxFragmentNamespace = getFirstIdentifier(entity).escapedText;
1152                        }
1153                    }
1154                    else {
1155                        const localJsxNamespace = getLocalJsxNamespace(file);
1156                        if (localJsxNamespace) {
1157                            return file.localJsxNamespace = localJsxNamespace;
1158                        }
1159                    }
1160                }
1161            }
1162            if (!_jsxNamespace) {
1163                _jsxNamespace = "React" as __String;
1164                if (compilerOptions.jsxFactory) {
1165                    _jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion);
1166                    visitNode(_jsxFactoryEntity, markAsSynthetic);
1167                    if (_jsxFactoryEntity) {
1168                        _jsxNamespace = getFirstIdentifier(_jsxFactoryEntity).escapedText;
1169                    }
1170                }
1171                else if (compilerOptions.reactNamespace) {
1172                    _jsxNamespace = escapeLeadingUnderscores(compilerOptions.reactNamespace);
1173                }
1174            }
1175            if (!_jsxFactoryEntity) {
1176                _jsxFactoryEntity = factory.createQualifiedName(factory.createIdentifier(unescapeLeadingUnderscores(_jsxNamespace)), "createElement");
1177            }
1178            return _jsxNamespace;
1179        }
1180
1181        function getLocalJsxNamespace(file: SourceFile): __String | undefined {
1182            if (file.localJsxNamespace) {
1183                return file.localJsxNamespace;
1184            }
1185            const jsxPragma = file.pragmas.get("jsx");
1186            if (jsxPragma) {
1187                const chosenPragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma;
1188                file.localJsxFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion);
1189                visitNode(file.localJsxFactory, markAsSynthetic);
1190                if (file.localJsxFactory) {
1191                    return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText;
1192                }
1193            }
1194        }
1195
1196        function markAsSynthetic(node: Node): VisitResult<Node> {
1197            setTextRangePosEnd(node, -1, -1);
1198            return visitEachChild(node, markAsSynthetic, nullTransformationContext);
1199        }
1200
1201        function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) {
1202            // Ensure we have all the type information in place for this file so that all the
1203            // emitter questions of this resolver will return the right information.
1204            getDiagnostics(sourceFile, cancellationToken);
1205            return emitResolver;
1206        }
1207
1208        function lookupOrIssueError(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
1209            const diagnostic = location
1210                ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3)
1211                : createCompilerDiagnostic(message, arg0, arg1, arg2, arg3);
1212            const existing = diagnostics.lookup(diagnostic);
1213            if (existing) {
1214                return existing;
1215            }
1216            else {
1217                diagnostics.add(diagnostic);
1218                return diagnostic;
1219            }
1220        }
1221
1222        function errorSkippedOn(key: keyof CompilerOptions, location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
1223            const diagnostic = error(location, message, arg0, arg1, arg2, arg3);
1224            diagnostic.skippedOn = key;
1225            return diagnostic;
1226        }
1227
1228        function createError(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
1229            return location
1230                ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3)
1231                : createCompilerDiagnostic(message, arg0, arg1, arg2, arg3);
1232        }
1233
1234        function error(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
1235            const diagnostic = createError(location, message, arg0, arg1, arg2, arg3);
1236            diagnostics.add(diagnostic);
1237            return diagnostic;
1238        }
1239
1240        function addErrorOrSuggestion(isError: boolean, diagnostic: Diagnostic) {
1241            if (isError) {
1242                diagnostics.add(diagnostic);
1243            }
1244            else {
1245                suggestionDiagnostics.add({ ...diagnostic, category: DiagnosticCategory.Suggestion });
1246            }
1247        }
1248        function errorOrSuggestion(isError: boolean, location: Node, message: DiagnosticMessage | DiagnosticMessageChain, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void {
1249             // Pseudo-synthesized input node
1250            if (location.pos < 0 || location.end < 0) {
1251                if (!isError) {
1252                    return; // Drop suggestions (we have no span to suggest on)
1253                }
1254                // Issue errors globally
1255                const file = getSourceFileOfNode(location);
1256                addErrorOrSuggestion(isError, "message" in message ? createFileDiagnostic(file, 0, 0, message, arg0, arg1, arg2, arg3) : createDiagnosticForFileFromMessageChain(file, message)); // eslint-disable-line local/no-in-operator
1257                return;
1258            }
1259            addErrorOrSuggestion(isError, "message" in message ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : createDiagnosticForNodeFromMessageChain(location, message)); // eslint-disable-line local/no-in-operator
1260        }
1261
1262        function errorAndMaybeSuggestAwait(
1263            location: Node,
1264            maybeMissingAwait: boolean,
1265            message: DiagnosticMessage,
1266            arg0?: string | number | undefined, arg1?: string | number | undefined, arg2?: string | number | undefined, arg3?: string | number | undefined): Diagnostic {
1267            const diagnostic = error(location, message, arg0, arg1, arg2, arg3);
1268            if (maybeMissingAwait) {
1269                const related = createDiagnosticForNode(location, Diagnostics.Did_you_forget_to_use_await);
1270                addRelatedInfo(diagnostic, related);
1271            }
1272            return diagnostic;
1273        }
1274
1275        function addDeprecatedSuggestionWorker(declarations: Node | Node[], diagnostic: DiagnosticWithLocation) {
1276            const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations);
1277            if (deprecatedTag) {
1278                addRelatedInfo(
1279                    diagnostic,
1280                    createDiagnosticForNode(deprecatedTag, Diagnostics.The_declaration_was_marked_as_deprecated_here)
1281                );
1282            }
1283            // We call `addRelatedInfo()` before adding the diagnostic to prevent duplicates.
1284            suggestionDiagnostics.add(diagnostic);
1285            return diagnostic;
1286        }
1287
1288        function isDeprecatedSymbol(symbol: Symbol) {
1289            return !!(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Deprecated);
1290        }
1291
1292        function addDeprecatedSuggestion(location: Node, declarations: Node[], deprecatedEntity: string) {
1293            const diagnostic = createDiagnosticForNode(location, Diagnostics._0_is_deprecated, deprecatedEntity);
1294            return addDeprecatedSuggestionWorker(declarations, diagnostic);
1295        }
1296
1297        function addDeprecatedSuggestionWithSignature(location: Node, declaration: Node, deprecatedEntity: string | undefined, signatureString: string) {
1298            const diagnostic = deprecatedEntity
1299                ? createDiagnosticForNode(location, Diagnostics.The_signature_0_of_1_is_deprecated, signatureString, deprecatedEntity)
1300                : createDiagnosticForNode(location, Diagnostics._0_is_deprecated, signatureString);
1301            return addDeprecatedSuggestionWorker(declaration, diagnostic);
1302        }
1303
1304        function createSymbol(flags: SymbolFlags, name: __String, checkFlags?: CheckFlags) {
1305            symbolCount++;
1306            const symbol = (new Symbol(flags | SymbolFlags.Transient, name) as TransientSymbol);
1307            symbol.checkFlags = checkFlags || 0;
1308            return symbol;
1309        }
1310
1311        function getExcludedSymbolFlags(flags: SymbolFlags): SymbolFlags {
1312            let result: SymbolFlags = 0;
1313            if (flags & SymbolFlags.BlockScopedVariable) result |= SymbolFlags.BlockScopedVariableExcludes;
1314            if (flags & SymbolFlags.FunctionScopedVariable) result |= SymbolFlags.FunctionScopedVariableExcludes;
1315            if (flags & SymbolFlags.Property) result |= SymbolFlags.PropertyExcludes;
1316            if (flags & SymbolFlags.EnumMember) result |= SymbolFlags.EnumMemberExcludes;
1317            if (flags & SymbolFlags.Function) result |= SymbolFlags.FunctionExcludes;
1318            if (flags & SymbolFlags.Class) result |= SymbolFlags.ClassExcludes;
1319            if (flags & SymbolFlags.Interface) result |= SymbolFlags.InterfaceExcludes;
1320            if (flags & SymbolFlags.RegularEnum) result |= SymbolFlags.RegularEnumExcludes;
1321            if (flags & SymbolFlags.ConstEnum) result |= SymbolFlags.ConstEnumExcludes;
1322            if (flags & SymbolFlags.ValueModule) result |= SymbolFlags.ValueModuleExcludes;
1323            if (flags & SymbolFlags.Method) result |= SymbolFlags.MethodExcludes;
1324            if (flags & SymbolFlags.GetAccessor) result |= SymbolFlags.GetAccessorExcludes;
1325            if (flags & SymbolFlags.SetAccessor) result |= SymbolFlags.SetAccessorExcludes;
1326            if (flags & SymbolFlags.TypeParameter) result |= SymbolFlags.TypeParameterExcludes;
1327            if (flags & SymbolFlags.TypeAlias) result |= SymbolFlags.TypeAliasExcludes;
1328            if (flags & SymbolFlags.Alias) result |= SymbolFlags.AliasExcludes;
1329            return result;
1330        }
1331
1332        function recordMergedSymbol(target: Symbol, source: Symbol) {
1333            if (!source.mergeId) {
1334                source.mergeId = nextMergeId;
1335                nextMergeId++;
1336            }
1337            mergedSymbols[source.mergeId] = target;
1338        }
1339
1340        function cloneSymbol(symbol: Symbol): Symbol {
1341            const result = createSymbol(symbol.flags, symbol.escapedName);
1342            result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
1343            result.parent = symbol.parent;
1344            if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
1345            if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
1346            if (symbol.members) result.members = new Map(symbol.members);
1347            if (symbol.exports) result.exports = new Map(symbol.exports);
1348            recordMergedSymbol(result, symbol);
1349            return result;
1350        }
1351
1352        /**
1353         * Note: if target is transient, then it is mutable, and mergeSymbol with both mutate and return it.
1354         * If target is not transient, mergeSymbol will produce a transient clone, mutate that and return it.
1355         */
1356        function mergeSymbol(target: Symbol, source: Symbol, unidirectional = false): Symbol {
1357            if (!(target.flags & getExcludedSymbolFlags(source.flags)) ||
1358                (source.flags | target.flags) & SymbolFlags.Assignment) {
1359                if (source === target) {
1360                    // This can happen when an export assigned namespace exports something also erroneously exported at the top level
1361                    // See `declarationFileNoCrashOnExtraExportModifier` for an example
1362                    return target;
1363                }
1364                if (!(target.flags & SymbolFlags.Transient)) {
1365                    const resolvedTarget = resolveSymbol(target);
1366                    if (resolvedTarget === unknownSymbol) {
1367                        return source;
1368                    }
1369                    target = cloneSymbol(resolvedTarget);
1370                }
1371                // Javascript static-property-assignment declarations always merge, even though they are also values
1372                if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) {
1373                    // reset flag when merging instantiated module into value module that has only const enums
1374                    target.constEnumOnlyModule = false;
1375                }
1376                target.flags |= source.flags;
1377                if (source.valueDeclaration) {
1378                    setValueDeclaration(target, source.valueDeclaration);
1379                }
1380                addRange(target.declarations, source.declarations);
1381                if (source.members) {
1382                    if (!target.members) target.members = createSymbolTable();
1383                    mergeSymbolTable(target.members, source.members, unidirectional);
1384                }
1385                if (source.exports) {
1386                    if (!target.exports) target.exports = createSymbolTable();
1387                    mergeSymbolTable(target.exports, source.exports, unidirectional);
1388                }
1389                if (!unidirectional) {
1390                    recordMergedSymbol(target, source);
1391                }
1392            }
1393            else if (target.flags & SymbolFlags.NamespaceModule) {
1394                // Do not report an error when merging `var globalThis` with the built-in `globalThis`,
1395                // as we will already report a "Declaration name conflicts..." error, and this error
1396                // won't make much sense.
1397                if (target !== globalThisSymbol) {
1398                    error(
1399                        source.declarations && getNameOfDeclaration(source.declarations[0]),
1400                        Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity,
1401                        symbolToString(target));
1402                }
1403            }
1404            else { // error
1405                const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum);
1406                const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable);
1407                const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations
1408                    : isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0
1409                    : Diagnostics.Duplicate_identifier_0;
1410                const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]);
1411                const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]);
1412
1413                const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs);
1414                const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs);
1415                const symbolName = symbolToString(source);
1416
1417                // Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch
1418                if (sourceSymbolFile && targetSymbolFile && amalgamatedDuplicates && !isEitherEnum && sourceSymbolFile !== targetSymbolFile) {
1419                    const firstFile = comparePaths(sourceSymbolFile.path, targetSymbolFile.path) === Comparison.LessThan ? sourceSymbolFile : targetSymbolFile;
1420                    const secondFile = firstFile === sourceSymbolFile ? targetSymbolFile : sourceSymbolFile;
1421                    const filesDuplicates = getOrUpdate(amalgamatedDuplicates, `${firstFile.path}|${secondFile.path}`, () =>
1422                        ({ firstFile, secondFile, conflictingSymbols: new Map() } as DuplicateInfoForFiles));
1423                    const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () =>
1424                        ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] } as DuplicateInfoForSymbol));
1425                    if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source);
1426                    if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target);
1427                }
1428                else {
1429                    if (!isSourcePlainJs) addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target);
1430                    if (!isTargetPlainJs) addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source);
1431                }
1432            }
1433            return target;
1434
1435            function addDuplicateLocations(locs: Declaration[], symbol: Symbol): void {
1436                if (symbol.declarations) {
1437                    for (const decl of symbol.declarations) {
1438                        pushIfUnique(locs, decl);
1439                    }
1440                }
1441            }
1442        }
1443
1444        function addDuplicateDeclarationErrorsForSymbols(target: Symbol, message: DiagnosticMessage, symbolName: string, source: Symbol) {
1445            forEach(target.declarations, node => {
1446                addDuplicateDeclarationError(node, message, symbolName, source.declarations);
1447            });
1448        }
1449
1450        function addDuplicateDeclarationError(node: Declaration, message: DiagnosticMessage, symbolName: string, relatedNodes: readonly Declaration[] | undefined) {
1451            const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) : getNameOfDeclaration(node)) || node;
1452            const err = lookupOrIssueError(errorNode, message, symbolName);
1453            for (const relatedNode of relatedNodes || emptyArray) {
1454                const adjustedNode = (getExpandoInitializer(relatedNode, /*isPrototypeAssignment*/ false) ? getNameOfExpando(relatedNode) : getNameOfDeclaration(relatedNode)) || relatedNode;
1455                if (adjustedNode === errorNode) continue;
1456                err.relatedInformation = err.relatedInformation || [];
1457                const leadingMessage = createDiagnosticForNode(adjustedNode, Diagnostics._0_was_also_declared_here, symbolName);
1458                const followOnMessage = createDiagnosticForNode(adjustedNode, Diagnostics.and_here);
1459                if (length(err.relatedInformation) >= 5 || some(err.relatedInformation, r => compareDiagnostics(r, followOnMessage) === Comparison.EqualTo || compareDiagnostics(r, leadingMessage) === Comparison.EqualTo)) continue;
1460                addRelatedInfo(err, !length(err.relatedInformation) ? leadingMessage : followOnMessage);
1461            }
1462        }
1463
1464        function combineSymbolTables(first: SymbolTable | undefined, second: SymbolTable | undefined): SymbolTable | undefined {
1465            if (!first?.size) return second;
1466            if (!second?.size) return first;
1467            const combined = createSymbolTable();
1468            mergeSymbolTable(combined, first);
1469            mergeSymbolTable(combined, second);
1470            return combined;
1471        }
1472
1473        function mergeSymbolTable(target: SymbolTable, source: SymbolTable, unidirectional = false) {
1474            source.forEach((sourceSymbol, id) => {
1475                const targetSymbol = target.get(id);
1476                target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol));
1477            });
1478        }
1479
1480        function mergeModuleAugmentation(moduleName: StringLiteral | Identifier): void {
1481            const moduleAugmentation = moduleName.parent as ModuleDeclaration;
1482            if (moduleAugmentation.symbol.declarations?.[0] !== moduleAugmentation) {
1483                // this is a combined symbol for multiple augmentations within the same file.
1484                // its symbol already has accumulated information for all declarations
1485                // so we need to add it just once - do the work only for first declaration
1486                Debug.assert(moduleAugmentation.symbol.declarations!.length > 1);
1487                return;
1488            }
1489
1490            if (isGlobalScopeAugmentation(moduleAugmentation)) {
1491                mergeSymbolTable(globals, moduleAugmentation.symbol.exports!);
1492            }
1493            else {
1494                // find a module that about to be augmented
1495                // do not validate names of augmentations that are defined in ambient context
1496                const moduleNotFoundError = !(moduleName.parent.parent.flags & NodeFlags.Ambient)
1497                    ? Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found
1498                    : undefined;
1499                let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true);
1500                if (!mainModule) {
1501                    return;
1502                }
1503                // obtain item referenced by 'export='
1504                mainModule = resolveExternalModuleSymbol(mainModule);
1505                if (mainModule.flags & SymbolFlags.Namespace) {
1506                    // If we're merging an augmentation to a pattern ambient module, we want to
1507                    // perform the merge unidirectionally from the augmentation ('a.foo') to
1508                    // the pattern ('*.foo'), so that 'getMergedSymbol()' on a.foo gives you
1509                    // all the exports both from the pattern and from the augmentation, but
1510                    // 'getMergedSymbol()' on *.foo only gives you exports from *.foo.
1511                    if (some(patternAmbientModules, module => mainModule === module.symbol)) {
1512                        const merged = mergeSymbol(moduleAugmentation.symbol, mainModule, /*unidirectional*/ true);
1513                        if (!patternAmbientModuleAugmentations) {
1514                            patternAmbientModuleAugmentations = new Map();
1515                        }
1516                        // moduleName will be a StringLiteral since this is not `declare global`.
1517                        patternAmbientModuleAugmentations.set((moduleName as StringLiteral).text, merged);
1518                    }
1519                    else {
1520                        if (mainModule.exports?.get(InternalSymbolName.ExportStar) && moduleAugmentation.symbol.exports?.size) {
1521                            // We may need to merge the module augmentation's exports into the target symbols of the resolved exports
1522                            const resolvedExports = getResolvedMembersOrExportsOfSymbol(mainModule, MembersOrExportsResolutionKind.resolvedExports);
1523                            for (const [key, value] of arrayFrom(moduleAugmentation.symbol.exports.entries())) {
1524                                if (resolvedExports.has(key) && !mainModule.exports.has(key)) {
1525                                    mergeSymbol(resolvedExports.get(key)!, value);
1526                                }
1527                            }
1528                        }
1529                        mergeSymbol(mainModule, moduleAugmentation.symbol);
1530                    }
1531                }
1532                else {
1533                    // moduleName will be a StringLiteral since this is not `declare global`.
1534                    error(moduleName, Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, (moduleName as StringLiteral).text);
1535                }
1536            }
1537        }
1538
1539        function addToSymbolTable(target: SymbolTable, source: SymbolTable, message: DiagnosticMessage) {
1540            source.forEach((sourceSymbol, id) => {
1541                const targetSymbol = target.get(id);
1542                if (targetSymbol) {
1543                    // Error on redeclarations
1544                    forEach(targetSymbol.declarations, addDeclarationDiagnostic(unescapeLeadingUnderscores(id), message));
1545                }
1546                else {
1547                    target.set(id, sourceSymbol);
1548                }
1549            });
1550
1551            function addDeclarationDiagnostic(id: string, message: DiagnosticMessage) {
1552                return (declaration: Declaration) => diagnostics.add(createDiagnosticForNode(declaration, message, id));
1553            }
1554        }
1555
1556        function getSymbolLinks(symbol: Symbol): SymbolLinks {
1557            if (symbol.flags & SymbolFlags.Transient) return symbol as TransientSymbol;
1558            const id = getSymbolId(symbol);
1559            return symbolLinks[id] || (symbolLinks[id] = new (SymbolLinks as any)());
1560        }
1561
1562        function getNodeLinks(node: Node): NodeLinks {
1563            const nodeId = getNodeId(node);
1564            return nodeLinks[nodeId] || (nodeLinks[nodeId] = new (NodeLinks as any)());
1565        }
1566
1567        function isGlobalSourceFile(node: Node) {
1568            return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node as SourceFile);
1569        }
1570
1571        function isValidFromLibs(symbol: Symbol, node?: Node): boolean {
1572            if (!node || !symbol.declarations || !symbol.declarations.length) {
1573                return true;
1574            }
1575
1576            const etsLibFilesNames = getEtsLibs(host);
1577            const sourceFileName = getSourceFileOfNode(node).fileName.trim();
1578            if (!sourceFileName) {
1579                return true;
1580            }
1581
1582            const fileName = sys?.resolvePath(sourceFileName);
1583            if (fileName?.endsWith(Extension.Ets) || etsLibFilesNames.includes(fileName)) {
1584                return true;
1585            }
1586
1587            const declaration = symbol.declarations.filter(declaration => {
1588                if (!getSourceFileOfNode(declaration).fileName) {
1589                    return true;
1590                }
1591                const symbolFileName = sys?.resolvePath(getSourceFileOfNode(declaration).fileName);
1592                if (etsLibFilesNames.indexOf(symbolFileName) !== -1) {
1593                    return false;
1594                }
1595                return true;
1596            });
1597
1598            if (!declaration.length) {
1599                return false;
1600            }
1601
1602            return true;
1603        }
1604
1605        function getSymbol(symbols: SymbolTable, name: __String, meaning: SymbolFlags, node?: Node): Symbol | undefined {
1606            if (meaning) {
1607                const symbol = getMergedSymbol(symbols.get(name));
1608                if (symbol) {
1609                    Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
1610                    if (!isValidFromLibs(symbol, node)) {
1611                        return undefined;
1612                    }
1613
1614                    if (symbol.flags & meaning) {
1615                        return symbol;
1616                    }
1617                    if (symbol.flags & SymbolFlags.Alias) {
1618                        const targetFlags = getAllSymbolFlags(symbol);
1619                        // `targetFlags` will be `SymbolFlags.All` if an error occurred in alias resolution; this avoids cascading errors
1620                        if (targetFlags & meaning) {
1621                            return symbol;
1622                        }
1623                    }
1624                }
1625            }
1626            // return undefined if we can't find a symbol.
1627        }
1628
1629        /**
1630         * Get symbols that represent parameter-property-declaration as parameter and as property declaration
1631         * @param parameter a parameterDeclaration node
1632         * @param parameterName a name of the parameter to get the symbols for.
1633         * @return a tuple of two symbols
1634         */
1635        function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [Symbol, Symbol] {
1636            const constructorDeclaration = parameter.parent;
1637            const classDeclaration = parameter.parent.parent;
1638
1639            const parameterSymbol = getSymbol(constructorDeclaration.locals!, parameterName, SymbolFlags.Value);
1640            const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, SymbolFlags.Value);
1641
1642            if (parameterSymbol && propertySymbol) {
1643                return [parameterSymbol, propertySymbol];
1644            }
1645
1646            return Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration");
1647        }
1648
1649        function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean {
1650            const declarationFile = getSourceFileOfNode(declaration);
1651            const useFile = getSourceFileOfNode(usage);
1652            const declContainer = getEnclosingBlockScopeContainer(declaration);
1653            if (declarationFile !== useFile) {
1654                if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) ||
1655                    (!outFile(compilerOptions)) ||
1656                    isInTypeQuery(usage) ||
1657                    declaration.flags & NodeFlags.Ambient) {
1658                    // nodes are in different files and order cannot be determined
1659                    return true;
1660                }
1661                // declaration is after usage
1662                // can be legal if usage is deferred (i.e. inside function or in initializer of instance property)
1663                if (isUsedInFunctionOrInstanceProperty(usage, declaration)) {
1664                    return true;
1665                }
1666                const sourceFiles = host.getSourceFiles();
1667                return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile);
1668            }
1669
1670            if (declaration.pos <= usage.pos && !(isPropertyDeclaration(declaration) && isThisProperty(usage.parent) && !declaration.initializer && !declaration.exclamationToken)) {
1671                // declaration is before usage
1672                if (declaration.kind === SyntaxKind.BindingElement) {
1673                    // still might be illegal if declaration and usage are both binding elements (eg var [a = b, b = b] = [1, 2])
1674                    const errorBindingElement = getAncestor(usage, SyntaxKind.BindingElement) as BindingElement;
1675                    if (errorBindingElement) {
1676                        return findAncestor(errorBindingElement, isBindingElement) !== findAncestor(declaration, isBindingElement) ||
1677                            declaration.pos < errorBindingElement.pos;
1678                    }
1679                    // or it might be illegal if usage happens before parent variable is declared (eg var [a] = a)
1680                    return isBlockScopedNameDeclaredBeforeUse(getAncestor(declaration, SyntaxKind.VariableDeclaration) as Declaration, usage);
1681                }
1682                else if (declaration.kind === SyntaxKind.VariableDeclaration) {
1683                    // still might be illegal if usage is in the initializer of the variable declaration (eg var a = a)
1684                    return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration as VariableDeclaration, usage);
1685                }
1686                else if (isClassDeclaration(declaration)) {
1687                    // still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} })
1688                    return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration);
1689                }
1690                else if (isPropertyDeclaration(declaration)) {
1691                    // still might be illegal if a self-referencing property initializer (eg private x = this.x)
1692                    return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ false);
1693                }
1694                else if (isParameterPropertyDeclaration(declaration, declaration.parent)) {
1695                    // foo = this.bar is illegal in esnext+useDefineForClassFields when bar is a parameter property
1696                    return !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields
1697                             && getContainingClass(declaration) === getContainingClass(usage)
1698                             && isUsedInFunctionOrInstanceProperty(usage, declaration));
1699                }
1700                return true;
1701            }
1702
1703
1704            // declaration is after usage, but it can still be legal if usage is deferred:
1705            // 1. inside an export specifier
1706            // 2. inside a function
1707            // 3. inside an instance property initializer, a reference to a non-instance property
1708            //    (except when target: "esnext" and useDefineForClassFields: true and the reference is to a parameter property)
1709            // 4. inside a static property initializer, a reference to a static method in the same class
1710            // 5. inside a TS export= declaration (since we will move the export statement during emit to avoid TDZ)
1711            // or if usage is in a type context:
1712            // 1. inside a type query (typeof in type position)
1713            // 2. inside a jsdoc comment
1714            if (usage.parent.kind === SyntaxKind.ExportSpecifier || (usage.parent.kind === SyntaxKind.ExportAssignment && (usage.parent as ExportAssignment).isExportEquals)) {
1715                // export specifiers do not use the variable, they only make it available for use
1716                return true;
1717            }
1718            // When resolving symbols for exports, the `usage` location passed in can be the export site directly
1719            if (usage.kind === SyntaxKind.ExportAssignment && (usage as ExportAssignment).isExportEquals) {
1720                return true;
1721            }
1722
1723            if (!!(usage.flags & NodeFlags.JSDoc) || isInTypeQuery(usage) || usageInTypeDeclaration()) {
1724                return true;
1725            }
1726            if (isUsedInFunctionOrInstanceProperty(usage, declaration)) {
1727                if (getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields
1728                    && getContainingClass(declaration)
1729                    && (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent))) {
1730                    return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true);
1731                }
1732                else {
1733                    return true;
1734                }
1735            }
1736            return false;
1737
1738            function usageInTypeDeclaration() {
1739                return !!findAncestor(usage, node => isInterfaceDeclaration(node) || isTypeAliasDeclaration(node));
1740            }
1741
1742            function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean {
1743                switch (declaration.parent.parent.kind) {
1744                    case SyntaxKind.VariableStatement:
1745                    case SyntaxKind.ForStatement:
1746                    case SyntaxKind.ForOfStatement:
1747                        // variable statement/for/for-of statement case,
1748                        // use site should not be inside variable declaration (initializer of declaration or binding element)
1749                        if (isSameScopeDescendentOf(usage, declaration, declContainer)) {
1750                            return true;
1751                        }
1752                        break;
1753                }
1754
1755                // ForIn/ForOf case - use site should not be used in expression part
1756                const grandparent = declaration.parent.parent;
1757                return isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, declContainer);
1758            }
1759
1760            function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node): boolean {
1761                return !!findAncestor(usage, current => {
1762                    if (current === declContainer) {
1763                        return "quit";
1764                    }
1765                    if (isFunctionLike(current)) {
1766                        return true;
1767                    }
1768                    if (isClassStaticBlockDeclaration(current)) {
1769                        return declaration.pos < usage.pos;
1770                    }
1771
1772                    const propertyDeclaration = tryCast(current.parent, isPropertyDeclaration);
1773                    if (propertyDeclaration) {
1774                        const initializerOfProperty = propertyDeclaration.initializer === current;
1775                        if (initializerOfProperty) {
1776                            if (isStatic(current.parent)) {
1777                                if (declaration.kind === SyntaxKind.MethodDeclaration) {
1778                                    return true;
1779                                }
1780                                if (isPropertyDeclaration(declaration) && getContainingClass(usage) === getContainingClass(declaration)) {
1781                                    const propName = declaration.name;
1782                                    if (isIdentifier(propName) || isPrivateIdentifier(propName)) {
1783                                        const type = getTypeOfSymbol(getSymbolOfNode(declaration));
1784                                        const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration);
1785                                        if (isPropertyInitializedInStaticBlocks(propName, type, staticBlocks, declaration.parent.pos, current.pos)) {
1786                                            return true;
1787                                        }
1788                                    }
1789                                }
1790                            }
1791                            else {
1792                                const isDeclarationInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !isStatic(declaration);
1793                                if (!isDeclarationInstanceProperty || getContainingClass(usage) !== getContainingClass(declaration)) {
1794                                    return true;
1795                                }
1796                            }
1797                        }
1798                    }
1799                    return false;
1800                });
1801            }
1802
1803            /** stopAtAnyPropertyDeclaration is used for detecting ES-standard class field use-before-def errors */
1804            function isPropertyImmediatelyReferencedWithinDeclaration(declaration: PropertyDeclaration | ParameterPropertyDeclaration, usage: Node, stopAtAnyPropertyDeclaration: boolean) {
1805                // always legal if usage is after declaration
1806                if (usage.end > declaration.end) {
1807                    return false;
1808                }
1809
1810                // still might be legal if usage is deferred (e.g. x: any = () => this.x)
1811                // otherwise illegal if immediately referenced within the declaration (e.g. x: any = this.x)
1812                const ancestorChangingReferenceScope = findAncestor(usage, (node: Node) => {
1813                    if (node === declaration) {
1814                        return "quit";
1815                    }
1816
1817                    switch (node.kind) {
1818                        case SyntaxKind.ArrowFunction:
1819                            return true;
1820                        case SyntaxKind.PropertyDeclaration:
1821                            // even when stopping at any property declaration, they need to come from the same class
1822                            return stopAtAnyPropertyDeclaration &&
1823                                (isPropertyDeclaration(declaration) && node.parent === declaration.parent
1824                                 || isParameterPropertyDeclaration(declaration, declaration.parent) && node.parent === declaration.parent.parent)
1825                                ? "quit": true;
1826                        case SyntaxKind.Block:
1827                            switch (node.parent.kind) {
1828                                case SyntaxKind.GetAccessor:
1829                                case SyntaxKind.MethodDeclaration:
1830                                case SyntaxKind.SetAccessor:
1831                                    return true;
1832                                default:
1833                                    return false;
1834                            }
1835                        default:
1836                            return false;
1837                    }
1838                });
1839
1840                return ancestorChangingReferenceScope === undefined;
1841            }
1842        }
1843
1844        function useOuterVariableScopeInParameter(result: Symbol, location: Node, lastLocation: Node) {
1845            const target = getEmitScriptTarget(compilerOptions);
1846            const functionLocation = location as FunctionLikeDeclaration;
1847            if (isParameter(lastLocation)
1848                && functionLocation.body
1849                && result.valueDeclaration
1850                && result.valueDeclaration.pos >= functionLocation.body.pos
1851                && result.valueDeclaration.end <= functionLocation.body.end) {
1852                // check for several cases where we introduce temporaries that require moving the name/initializer of the parameter to the body
1853                // - static field in a class expression
1854                // - optional chaining pre-es2020
1855                // - nullish coalesce pre-es2020
1856                // - spread assignment in binding pattern pre-es2017
1857                if (target >= ScriptTarget.ES2015) {
1858                    const links = getNodeLinks(functionLocation);
1859                    if (links.declarationRequiresScopeChange === undefined) {
1860                        links.declarationRequiresScopeChange = forEach(functionLocation.parameters, requiresScopeChange) || false;
1861                    }
1862                    return !links.declarationRequiresScopeChange;
1863                }
1864            }
1865            return false;
1866
1867            function requiresScopeChange(node: ParameterDeclaration): boolean {
1868                return requiresScopeChangeWorker(node.name)
1869                    || !!node.initializer && requiresScopeChangeWorker(node.initializer);
1870            }
1871
1872            function requiresScopeChangeWorker(node: Node): boolean {
1873                switch (node.kind) {
1874                    case SyntaxKind.ArrowFunction:
1875                    case SyntaxKind.FunctionExpression:
1876                    case SyntaxKind.FunctionDeclaration:
1877                    case SyntaxKind.Constructor:
1878                        // do not descend into these
1879                        return false;
1880                    case SyntaxKind.MethodDeclaration:
1881                    case SyntaxKind.GetAccessor:
1882                    case SyntaxKind.SetAccessor:
1883                    case SyntaxKind.PropertyAssignment:
1884                        return requiresScopeChangeWorker((node as MethodDeclaration | AccessorDeclaration | PropertyAssignment).name);
1885                    case SyntaxKind.PropertyDeclaration:
1886                        // static properties in classes introduce temporary variables
1887                        if (hasStaticModifier(node)) {
1888                            return target < ScriptTarget.ESNext || !useDefineForClassFields;
1889                        }
1890                        return requiresScopeChangeWorker((node as PropertyDeclaration).name);
1891                    case SyntaxKind.AnnotationPropertyDeclaration:
1892                        return requiresScopeChangeWorker((node as AnnotationPropertyDeclaration).name);
1893                    default:
1894                        // null coalesce and optional chain pre-es2020 produce temporary variables
1895                        if (isNullishCoalesce(node) || isOptionalChain(node)) {
1896                            return target < ScriptTarget.ES2020;
1897                        }
1898                        if (isBindingElement(node) && node.dotDotDotToken && isObjectBindingPattern(node.parent)) {
1899                            return target < ScriptTarget.ES2017;
1900                        }
1901                        if (isTypeNode(node)) return false;
1902                        return forEachChild(node, requiresScopeChangeWorker) || false;
1903                }
1904            }
1905        }
1906
1907        function isConstAssertion(location: Node) {
1908            return (isAssertionExpression(location) && isConstTypeReference(location.type))
1909                || (isJSDocTypeTag(location) && isConstTypeReference(location.typeExpression));
1910        }
1911
1912        /**
1913         * Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
1914         * the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with
1915         * the given name can be found.
1916         *
1917         * @param nameNotFoundMessage If defined, we will report errors found during resolve.
1918         * @param isUse If true, this will count towards --noUnusedLocals / --noUnusedParameters.
1919         */
1920        function resolveName(
1921            location: Node | undefined,
1922            name: __String,
1923            meaning: SymbolFlags,
1924            nameNotFoundMessage: DiagnosticMessage | undefined,
1925            nameArg: __String | Identifier | undefined,
1926            isUse: boolean,
1927            excludeGlobals = false,
1928            getSpellingSuggestions = true): Symbol | undefined {
1929            return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSpellingSuggestions, getSymbol);
1930        }
1931
1932        function resolveNameHelper(
1933            location: Node | undefined,
1934            name: __String,
1935            meaning: SymbolFlags,
1936            nameNotFoundMessage: DiagnosticMessage | undefined,
1937            nameArg: __String | Identifier | undefined,
1938            isUse: boolean,
1939            excludeGlobals: boolean,
1940            getSpellingSuggestions: boolean,
1941            lookup: typeof getSymbol): Symbol | undefined {
1942            const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location
1943            let result: Symbol | undefined;
1944            let lastLocation: Node | undefined;
1945            let lastSelfReferenceLocation: Node | undefined;
1946            let propertyWithInvalidInitializer: PropertyDeclaration | undefined;
1947            let associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined;
1948            let withinDeferredContext = false;
1949            const errorLocation = location;
1950            let grandparent: Node;
1951            let isInExternalModule = false;
1952
1953            loop: while (location) {
1954                if (name === "const" && isConstAssertion(location)) {
1955                    // `const` in an `as const` has no symbol, but issues no error because there is no *actual* lookup of the type
1956                    // (it refers to the constant type of the expression instead)
1957                    return undefined;
1958                }
1959                // Locals of a source file are not in scope (because they get merged into the global symbol table)
1960                if (location.locals && !isGlobalSourceFile(location)) {
1961                    if (result = lookup(location.locals, name, meaning)) {
1962                        let useResult = true;
1963                        if (isFunctionLike(location) && lastLocation && lastLocation !== (location as FunctionLikeDeclaration).body) {
1964                            // symbol lookup restrictions for function-like declarations
1965                            // - Type parameters of a function are in scope in the entire function declaration, including the parameter
1966                            //   list and return type. However, local types are only in scope in the function body.
1967                            // - parameters are only in the scope of function body
1968                            // This restriction does not apply to JSDoc comment types because they are parented
1969                            // at a higher level than type parameters would normally be
1970                            if (meaning & result.flags & SymbolFlags.Type && lastLocation.kind !== SyntaxKind.JSDoc) {
1971                                useResult = result.flags & SymbolFlags.TypeParameter
1972                                    // type parameters are visible in parameter list, return type and type parameter list
1973                                    ? lastLocation === (location as FunctionLikeDeclaration).type ||
1974                                    lastLocation.kind === SyntaxKind.Parameter ||
1975                                    lastLocation.kind === SyntaxKind.JSDocParameterTag ||
1976                                    lastLocation.kind === SyntaxKind.JSDocReturnTag ||
1977                                    lastLocation.kind === SyntaxKind.TypeParameter
1978                                    // local types not visible outside the function body
1979                                    : false;
1980                            }
1981                            if (meaning & result.flags & SymbolFlags.Variable) {
1982                                // expression inside parameter will lookup as normal variable scope when targeting es2015+
1983                                if (useOuterVariableScopeInParameter(result, location, lastLocation)) {
1984                                    useResult = false;
1985                                }
1986                                else if (result.flags & SymbolFlags.FunctionScopedVariable) {
1987                                    // parameters are visible only inside function body, parameter list and return type
1988                                    // technically for parameter list case here we might mix parameters and variables declared in function,
1989                                    // however it is detected separately when checking initializers of parameters
1990                                    // to make sure that they reference no variables declared after them.
1991                                    useResult =
1992                                        lastLocation.kind === SyntaxKind.Parameter ||
1993                                        (
1994                                            lastLocation === (location as FunctionLikeDeclaration).type &&
1995                                            !!findAncestor(result.valueDeclaration, isParameter)
1996                                        );
1997                                }
1998                            }
1999                        }
2000                        else if (location.kind === SyntaxKind.ConditionalType) {
2001                            // A type parameter declared using 'infer T' in a conditional type is visible only in
2002                            // the true branch of the conditional type.
2003                            useResult = lastLocation === (location as ConditionalTypeNode).trueType;
2004                        }
2005
2006                        if (useResult) {
2007                            break loop;
2008                        }
2009                        else {
2010                            result = undefined;
2011                        }
2012                    }
2013                }
2014                withinDeferredContext = withinDeferredContext || getIsDeferredContext(location, lastLocation);
2015                switch (location.kind) {
2016                    case SyntaxKind.SourceFile:
2017                        if (!isExternalOrCommonJsModule(location as SourceFile)) break;
2018                        isInExternalModule = true;
2019                        // falls through
2020                    case SyntaxKind.ModuleDeclaration:
2021                        const moduleExports = getSymbolOfNode(location) ? (getSymbolOfNode(location as SourceFile | ModuleDeclaration)?.exports || emptySymbols) : emptySymbols;
2022                        if (location.kind === SyntaxKind.SourceFile || (isModuleDeclaration(location) && location.flags & NodeFlags.Ambient && !isGlobalScopeAugmentation(location))) {
2023
2024                            // It's an external module. First see if the module has an export default and if the local
2025                            // name of that export default matches.
2026                            if (result = moduleExports.get(InternalSymbolName.Default)) {
2027                                const localSymbol = getLocalSymbolForExportDefault(result);
2028                                if (localSymbol && (result.flags & meaning) && localSymbol.escapedName === name) {
2029                                    break loop;
2030                                }
2031                                result = undefined;
2032                            }
2033
2034                            // Because of module/namespace merging, a module's exports are in scope,
2035                            // yet we never want to treat an export specifier as putting a member in scope.
2036                            // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope.
2037                            // Two things to note about this:
2038                            //     1. We have to check this without calling getSymbol. The problem with calling getSymbol
2039                            //        on an export specifier is that it might find the export specifier itself, and try to
2040                            //        resolve it as an alias. This will cause the checker to consider the export specifier
2041                            //        a circular alias reference when it might not be.
2042                            //     2. We check === SymbolFlags.Alias in order to check that the symbol is *purely*
2043                            //        an alias. If we used &, we'd be throwing out symbols that have non alias aspects,
2044                            //        which is not the desired behavior.
2045                            const moduleExport = moduleExports.get(name);
2046                            if (moduleExport &&
2047                                moduleExport.flags === SymbolFlags.Alias &&
2048                                (getDeclarationOfKind(moduleExport, SyntaxKind.ExportSpecifier) || getDeclarationOfKind(moduleExport, SyntaxKind.NamespaceExport))) {
2049                                break;
2050                            }
2051                        }
2052
2053                        // ES6 exports are also visible locally (except for 'default'), but commonjs exports are not (except typedefs)
2054                        if (name !== InternalSymbolName.Default && (result = lookup(moduleExports, name, meaning & SymbolFlags.ModuleMember))) {
2055                            if (isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations?.some(isJSDocTypeAlias)) {
2056                                result = undefined;
2057                            }
2058                            else {
2059                                break loop;
2060                            }
2061                        }
2062                        break;
2063                    case SyntaxKind.EnumDeclaration:
2064                        if (result = lookup(getSymbolOfNode(location)?.exports || emptySymbols, name, meaning & SymbolFlags.EnumMember)) {
2065                            break loop;
2066                        }
2067                        break;
2068                    case SyntaxKind.PropertyDeclaration:
2069                        // TypeScript 1.0 spec (April 2014): 8.4.1
2070                        // Initializer expressions for instance member variables are evaluated in the scope
2071                        // of the class constructor body but are not permitted to reference parameters or
2072                        // local variables of the constructor. This effectively means that entities from outer scopes
2073                        // by the same name as a constructor parameter or local variable are inaccessible
2074                        // in initializer expressions for instance member variables.
2075                        if (!isStatic(location)) {
2076                            const ctor = findConstructorDeclaration(location.parent as ClassLikeDeclaration);
2077                            if (ctor && ctor.locals) {
2078                                if (lookup(ctor.locals, name, meaning & SymbolFlags.Value)) {
2079                                    // Remember the property node, it will be used later to report appropriate error
2080                                    Debug.assertNode(location, isPropertyDeclaration);
2081                                    propertyWithInvalidInitializer = location;
2082                                }
2083                            }
2084                        }
2085                        break;
2086                    case SyntaxKind.ClassDeclaration:
2087                    case SyntaxKind.ClassExpression:
2088                    case SyntaxKind.InterfaceDeclaration:
2089                        // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals
2090                        // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would
2091                        // trigger resolving late-bound names, which we may already be in the process of doing while we're here!
2092                        if (result = lookup(getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) {
2093                            if (!isTypeParameterSymbolDeclaredInContainer(result, location)) {
2094                                // ignore type parameters not declared in this container
2095                                result = undefined;
2096                                break;
2097                            }
2098                            if (lastLocation && isStatic(lastLocation)) {
2099                                // TypeScript 1.0 spec (April 2014): 3.4.1
2100                                // The scope of a type parameter extends over the entire declaration with which the type
2101                                // parameter list is associated, with the exception of static member declarations in classes.
2102                                if (nameNotFoundMessage) {
2103                                    error(errorLocation, Diagnostics.Static_members_cannot_reference_class_type_parameters);
2104                                }
2105                                return undefined;
2106                            }
2107                            break loop;
2108                        }
2109                        if (location.kind === SyntaxKind.ClassExpression && meaning & SymbolFlags.Class) {
2110                            const className = (location as ClassExpression).name;
2111                            if (className && name === className.escapedText) {
2112                                result = location.symbol;
2113                                break loop;
2114                            }
2115                        }
2116                        break;
2117                    case SyntaxKind.ExpressionWithTypeArguments:
2118                        // The type parameters of a class are not in scope in the base class expression.
2119                        if (lastLocation === (location as ExpressionWithTypeArguments).expression && (location.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword) {
2120                            const container = location.parent.parent;
2121                            if (isClassLike(container) && (result = lookup(getSymbolOfNode(container).members!, name, meaning & SymbolFlags.Type))) {
2122                                if (nameNotFoundMessage) {
2123                                    error(errorLocation, Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters);
2124                                }
2125                                return undefined;
2126                            }
2127                        }
2128                        break;
2129                    // It is not legal to reference a class's own type parameters from a computed property name that
2130                    // belongs to the class. For example:
2131                    //
2132                    //   function foo<T>() { return '' }
2133                    //   class C<T> { // <-- Class's own type parameter T
2134                    //       [foo<T>()]() { } // <-- Reference to T from class's own computed property
2135                    //   }
2136                    //
2137                    case SyntaxKind.ComputedPropertyName:
2138                        grandparent = location.parent.parent;
2139                        if (isClassLike(grandparent) || grandparent.kind === SyntaxKind.InterfaceDeclaration) {
2140                            // A reference to this grandparent's type parameters would be an error
2141                            if (result = lookup(getSymbolOfNode(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.Type)) {
2142                                if (nameNotFoundMessage) {
2143                                    error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type);
2144                                }
2145                                return undefined;
2146                            }
2147                        }
2148                        break;
2149                    case SyntaxKind.ArrowFunction:
2150                        // when targeting ES6 or higher there is no 'arguments' in an arrow function
2151                        // for lower compile targets the resolved symbol is used to emit an error
2152                        if (getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015) {
2153                            break;
2154                        }
2155                        // falls through
2156                    case SyntaxKind.MethodDeclaration:
2157                    case SyntaxKind.Constructor:
2158                    case SyntaxKind.GetAccessor:
2159                    case SyntaxKind.SetAccessor:
2160                    case SyntaxKind.FunctionDeclaration:
2161                        if (meaning & SymbolFlags.Variable && name === "arguments") {
2162                            result = argumentsSymbol;
2163                            break loop;
2164                        }
2165                        break;
2166                    case SyntaxKind.FunctionExpression:
2167                        if (meaning & SymbolFlags.Variable && name === "arguments") {
2168                            result = argumentsSymbol;
2169                            break loop;
2170                        }
2171
2172                        if (meaning & SymbolFlags.Function) {
2173                            const functionName = (location as FunctionExpression).name;
2174                            if (functionName && name === functionName.escapedText) {
2175                                result = location.symbol;
2176                                break loop;
2177                            }
2178                        }
2179                        break;
2180                    case SyntaxKind.Decorator:
2181                        // Decorators are resolved at the class declaration. Resolving at the parameter
2182                        // or member would result in looking up locals in the method.
2183                        //
2184                        //   function y() {}
2185                        //   class C {
2186                        //       method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
2187                        //   }
2188                        //
2189                        if (location.parent && location.parent.kind === SyntaxKind.Parameter) {
2190                            location = location.parent;
2191                        }
2192                        //
2193                        //   function y() {}
2194                        //   class C {
2195                        //       @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
2196                        //   }
2197                        //
2198
2199                        // class Decorators are resolved outside of the class to avoid referencing type parameters of that class.
2200                        //
2201                        //   type T = number;
2202                        //   declare function y(x: T): any;
2203                        //   @param(1 as T) // <-- T should resolve to the type alias outside of class C
2204                        //   class C<T> {}
2205                        if (location.parent && (isClassElement(location.parent) || location.parent.kind === SyntaxKind.ClassDeclaration)) {
2206                            location = location.parent;
2207                        }
2208                        break;
2209                    case SyntaxKind.JSDocTypedefTag:
2210                    case SyntaxKind.JSDocCallbackTag:
2211                    case SyntaxKind.JSDocEnumTag:
2212                        // js type aliases do not resolve names from their host, so skip past it
2213                        const root = getJSDocRoot(location);
2214                        if (root) {
2215                            location = root.parent;
2216                        }
2217                        break;
2218                    case SyntaxKind.Parameter:
2219                        if (lastLocation && (
2220                            lastLocation === (location as ParameterDeclaration).initializer ||
2221                            lastLocation === (location as ParameterDeclaration).name && isBindingPattern(lastLocation))) {
2222                            if (!associatedDeclarationForContainingInitializerOrBindingName) {
2223                                associatedDeclarationForContainingInitializerOrBindingName = location as ParameterDeclaration;
2224                            }
2225                        }
2226                        break;
2227                    case SyntaxKind.BindingElement:
2228                        if (lastLocation && (
2229                            lastLocation === (location as BindingElement).initializer ||
2230                            lastLocation === (location as BindingElement).name && isBindingPattern(lastLocation))) {
2231                            if (isParameterDeclaration(location as BindingElement) && !associatedDeclarationForContainingInitializerOrBindingName) {
2232                                associatedDeclarationForContainingInitializerOrBindingName = location as BindingElement;
2233                            }
2234                        }
2235                        break;
2236                    case SyntaxKind.InferType:
2237                        if (meaning & SymbolFlags.TypeParameter) {
2238                            const parameterName = (location as InferTypeNode).typeParameter.name;
2239                            if (parameterName && name === parameterName.escapedText) {
2240                                result = (location as InferTypeNode).typeParameter.symbol;
2241                                break loop;
2242                            }
2243                        }
2244                        break;
2245                }
2246                if (isSelfReferenceLocation(location)) {
2247                    lastSelfReferenceLocation = location;
2248                }
2249                lastLocation = location;
2250                location = isJSDocTemplateTag(location) ? getEffectiveContainerForJSDocTemplateTag(location) || location.parent :
2251                    isJSDocParameterTag(location) || isJSDocReturnTag(location) ? getHostSignatureFromJSDoc(location) || location.parent :
2252                    location.parent;
2253            }
2254
2255            // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`.
2256            // If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself.
2257            // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used.
2258            if (isUse && result && (!lastSelfReferenceLocation || result !== lastSelfReferenceLocation.symbol)) {
2259                result.isReferenced! |= meaning;
2260            }
2261
2262            if (!result) {
2263                if (lastLocation) {
2264                    Debug.assert(lastLocation.kind === SyntaxKind.SourceFile);
2265                    if ((lastLocation as SourceFile).commonJsModuleIndicator && name === "exports" && meaning & lastLocation.symbol.flags) {
2266                        return lastLocation.symbol;
2267                    }
2268                }
2269
2270                if (!excludeGlobals) {
2271                    result = lookup(globals, name, meaning, originalLocation);
2272                }
2273            }
2274            if (!result) {
2275                if (originalLocation && isInJSFile(originalLocation) && originalLocation.parent) {
2276                    if (isRequireCall(originalLocation.parent, /*checkArgumentIsStringLiteralLike*/ false)) {
2277                        return requireSymbol;
2278                    }
2279                }
2280            }
2281
2282            // The invalid initializer error is needed in two situation:
2283            // 1. When result is undefined, after checking for a missing "this."
2284            // 2. When result is defined
2285            function checkAndReportErrorForInvalidInitializer() {
2286                if (propertyWithInvalidInitializer && !(useDefineForClassFields && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022)) {
2287                    // We have a match, but the reference occurred within a property initializer and the identifier also binds
2288                    // to a local variable in the constructor where the code will be emitted. Note that this is actually allowed
2289                    // with ESNext+useDefineForClassFields because the scope semantics are different.
2290                    error(errorLocation,
2291                        errorLocation && propertyWithInvalidInitializer.type && textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos)
2292                            ? Diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor
2293                            : Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor,
2294                        declarationNameToString(propertyWithInvalidInitializer.name), diagnosticName(nameArg!));
2295                    return true;
2296                }
2297                return false;
2298            }
2299
2300            if (!result) {
2301                if (nameNotFoundMessage) {
2302                    addLazyDiagnostic(() => {
2303                        if (!errorLocation ||
2304                            !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg!) && // TODO: GH#18217
2305                            !checkAndReportErrorForInvalidInitializer() &&
2306                            !checkAndReportErrorForExtendingInterface(errorLocation) &&
2307                            !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
2308                            !checkAndReportErrorForExportingPrimitiveType(errorLocation, name) &&
2309                            !checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation, name, meaning) &&
2310                            !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) &&
2311                            !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) {
2312                            let suggestion: Symbol | undefined;
2313                            let suggestedLib: string | undefined;
2314                            // Report missing lib first
2315                            if (nameArg) {
2316                                suggestedLib = getSuggestedLibForNonExistentName(nameArg);
2317                                if (suggestedLib) {
2318                                    error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg), suggestedLib);
2319                                }
2320                            }
2321                            // then spelling suggestions
2322                            if (!suggestedLib && getSpellingSuggestions && suggestionCount < maximumSuggestionCount) {
2323                                suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning);
2324                                const isGlobalScopeAugmentationDeclaration = suggestion?.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration);
2325                                if (isGlobalScopeAugmentationDeclaration) {
2326                                    suggestion = undefined;
2327                                }
2328                                if (suggestion) {
2329                                    const suggestionName = symbolToString(suggestion);
2330                                    const isUncheckedJS = isUncheckedJSSuggestion(originalLocation, suggestion, /*excludeClasses*/ false);
2331                                    const message = meaning === SymbolFlags.Namespace || nameArg && typeof nameArg !== "string" && nodeIsSynthesized(nameArg) ? Diagnostics.Cannot_find_namespace_0_Did_you_mean_1
2332                                        : isUncheckedJS ? Diagnostics.Could_not_find_name_0_Did_you_mean_1
2333                                        : Diagnostics.Cannot_find_name_0_Did_you_mean_1;
2334                                    const diagnostic = createError(errorLocation, message, diagnosticName(nameArg!), suggestionName);
2335                                    addErrorOrSuggestion(!isUncheckedJS, diagnostic);
2336                                    if (suggestion.valueDeclaration) {
2337                                        addRelatedInfo(
2338                                            diagnostic,
2339                                            createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
2340                                        );
2341                                    }
2342                                }
2343                            }
2344                            // And then fall back to unspecified "not found"
2345                            if (!suggestion && !suggestedLib && nameArg) {
2346                                error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg));
2347                            }
2348                            suggestionCount++;
2349                        }
2350                    });
2351                }
2352                return undefined;
2353            }
2354            else if (nameNotFoundMessage && checkAndReportErrorForInvalidInitializer()) {
2355                return undefined;
2356            }
2357
2358            // Perform extra checks only if error reporting was requested
2359            if (nameNotFoundMessage) {
2360                addLazyDiagnostic(() => {
2361                    // Only check for block-scoped variable if we have an error location and are looking for the
2362                    // name with variable meaning
2363                    //      For example,
2364                    //          declare module foo {
2365                    //              interface bar {}
2366                    //          }
2367                    //      const foo/*1*/: foo/*2*/.bar;
2368                    // The foo at /*1*/ and /*2*/ will share same symbol with two meanings:
2369                    // block-scoped variable and namespace module. However, only when we
2370                    // try to resolve name in /*1*/ which is used in variable position,
2371                    // we want to check for block-scoped
2372                    if (errorLocation &&
2373                        (meaning & SymbolFlags.BlockScopedVariable ||
2374                         ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) && (meaning & SymbolFlags.Value) === SymbolFlags.Value))) {
2375                        const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result!);
2376                        if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class || exportOrLocalSymbol.flags & SymbolFlags.Enum) {
2377                            checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation);
2378                        }
2379                    }
2380
2381                    // If we're in an external module, we can't reference value symbols created from UMD export declarations
2382                    if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation!.flags & NodeFlags.JSDoc)) {
2383                        const merged = getMergedSymbol(result);
2384                        if (length(merged.declarations) && every(merged.declarations, d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports)) {
2385                            errorOrSuggestion(!compilerOptions.allowUmdGlobalAccess, errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name));
2386                        }
2387                    }
2388
2389                    // If we're in a parameter initializer or binding name, we can't reference the values of the parameter whose initializer we're within or parameters to the right
2390                    if (result && associatedDeclarationForContainingInitializerOrBindingName && !withinDeferredContext && (meaning & SymbolFlags.Value) === SymbolFlags.Value) {
2391                        const candidate = getMergedSymbol(getLateBoundSymbol(result));
2392                        const root = (getRootDeclaration(associatedDeclarationForContainingInitializerOrBindingName) as ParameterDeclaration);
2393                        // A parameter initializer or binding pattern initializer within a parameter cannot refer to itself
2394                        if (candidate === getSymbolOfNode(associatedDeclarationForContainingInitializerOrBindingName)) {
2395                            error(errorLocation, Diagnostics.Parameter_0_cannot_reference_itself, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name));
2396                        }
2397                        // And it cannot refer to any declarations which come after it
2398                        else if (candidate.valueDeclaration && candidate.valueDeclaration.pos > associatedDeclarationForContainingInitializerOrBindingName.pos && root.parent.locals && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate) {
2399                            error(errorLocation, Diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), declarationNameToString(errorLocation as Identifier));
2400                        }
2401                    }
2402                    if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) {
2403                        const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, SymbolFlags.Value);
2404                        if (typeOnlyDeclaration) {
2405                            const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier
2406                                ? Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type
2407                                : Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type;
2408                            const unescapedName = unescapeLeadingUnderscores(name);
2409                            addTypeOnlyDeclarationRelatedInfo(
2410                                error(errorLocation, message, unescapedName),
2411                                typeOnlyDeclaration,
2412                                unescapedName);
2413                        }
2414                    }
2415                });
2416            }
2417            return result;
2418        }
2419
2420        function addTypeOnlyDeclarationRelatedInfo(diagnostic: Diagnostic, typeOnlyDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, unescapedName: string) {
2421            if (!typeOnlyDeclaration) return diagnostic;
2422            return addRelatedInfo(
2423                diagnostic,
2424                createDiagnosticForNode(
2425                    typeOnlyDeclaration,
2426                    typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here,
2427                    unescapedName));
2428        }
2429
2430        function getIsDeferredContext(location: Node, lastLocation: Node | undefined): boolean {
2431            if (location.kind !== SyntaxKind.ArrowFunction && location.kind !== SyntaxKind.FunctionExpression) {
2432                // initializers in instance property declaration of class like entities are executed in constructor and thus deferred
2433                return isTypeQueryNode(location) || ((
2434                    isFunctionLikeDeclaration(location) ||
2435                    (location.kind === SyntaxKind.PropertyDeclaration && !isStatic(location))
2436                ) && (!lastLocation || lastLocation !== (location as SignatureDeclaration | PropertyDeclaration).name)); // A name is evaluated within the enclosing scope - so it shouldn't count as deferred
2437            }
2438            if (lastLocation && lastLocation === (location as FunctionExpression | ArrowFunction).name) {
2439                return false;
2440            }
2441            // generator functions and async functions are not inlined in control flow when immediately invoked
2442            if ((location as FunctionExpression | ArrowFunction).asteriskToken || hasSyntacticModifier(location, ModifierFlags.Async)) {
2443                return true;
2444            }
2445            return !getImmediatelyInvokedFunctionExpression(location);
2446        }
2447
2448        function isSelfReferenceLocation(node: Node): boolean {
2449            switch (node.kind) {
2450                case SyntaxKind.FunctionDeclaration:
2451                case SyntaxKind.ClassDeclaration:
2452                case SyntaxKind.InterfaceDeclaration:
2453                case SyntaxKind.EnumDeclaration:
2454                case SyntaxKind.TypeAliasDeclaration:
2455                case SyntaxKind.ModuleDeclaration: // For `namespace N { N; }`
2456                    return true;
2457                default:
2458                    return false;
2459            }
2460        }
2461
2462        function diagnosticName(nameArg: __String | Identifier | PrivateIdentifier) {
2463            return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier);
2464        }
2465
2466        function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) {
2467            if (symbol.declarations) {
2468                for (const decl of symbol.declarations) {
2469                    if (decl.kind === SyntaxKind.TypeParameter) {
2470                        const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent;
2471                        if (parent === container) {
2472                            return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags, isJSDocTypeAlias));
2473                        }
2474                    }
2475                }
2476            }
2477
2478            return false;
2479        }
2480
2481        function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: __String, nameArg: __String | Identifier): boolean {
2482            if (!isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) {
2483                return false;
2484            }
2485
2486            const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ false);
2487            let location = container;
2488            while (location) {
2489                if (isClassLike(location.parent)) {
2490                    const classSymbol = getSymbolOfNode(location.parent);
2491                    if (!classSymbol) {
2492                        break;
2493                    }
2494
2495                    // Check to see if a static member exists.
2496                    const constructorType = getTypeOfSymbol(classSymbol);
2497                    if (getPropertyOfType(constructorType, name)) {
2498                        error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol));
2499                        return true;
2500                    }
2501
2502                    // No static member is present.
2503                    // Check if we're in an instance method and look for a relevant instance member.
2504                    if (location === container && !isStatic(location)) {
2505                        const instanceType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType!; // TODO: GH#18217
2506                        if (getPropertyOfType(instanceType, name)) {
2507                            error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg));
2508                            return true;
2509                        }
2510                    }
2511                }
2512
2513                location = location.parent;
2514            }
2515            return false;
2516        }
2517
2518
2519        function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean {
2520            const expression = getEntityNameForExtendingInterface(errorLocation);
2521            if (expression && resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) {
2522                error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression));
2523                return true;
2524            }
2525            return false;
2526        }
2527        /**
2528         * Climbs up parents to an ExpressionWithTypeArguments, and returns its expression,
2529         * but returns undefined if that expression is not an EntityNameExpression.
2530         */
2531        function getEntityNameForExtendingInterface(node: Node): EntityNameExpression | undefined {
2532            switch (node.kind) {
2533                case SyntaxKind.Identifier:
2534                case SyntaxKind.PropertyAccessExpression:
2535                    return node.parent ? getEntityNameForExtendingInterface(node.parent) : undefined;
2536                case SyntaxKind.ExpressionWithTypeArguments:
2537                    if (isEntityNameExpression((node as ExpressionWithTypeArguments).expression)) {
2538                        return (node as ExpressionWithTypeArguments).expression as EntityNameExpression;
2539                    }
2540                    // falls through
2541                default:
2542                    return undefined;
2543            }
2544        }
2545
2546        function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
2547            const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(errorLocation) ? SymbolFlags.Value : 0);
2548            if (meaning === namespaceMeaning) {
2549                const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~namespaceMeaning, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
2550                const parent = errorLocation.parent;
2551                if (symbol) {
2552                    if (isQualifiedName(parent)) {
2553                        Debug.assert(parent.left === errorLocation, "Should only be resolving left side of qualified name as a namespace");
2554                        const propName = parent.right.escapedText;
2555                        const propType = getPropertyOfType(getDeclaredTypeOfSymbol(symbol), propName);
2556                        if (propType) {
2557                            error(
2558                                parent,
2559                                Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1,
2560                                unescapeLeadingUnderscores(name),
2561                                unescapeLeadingUnderscores(propName),
2562                            );
2563                            return true;
2564                        }
2565                    }
2566                    error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeLeadingUnderscores(name));
2567                    return true;
2568                }
2569            }
2570
2571            return false;
2572        }
2573
2574        function checkAndReportErrorForUsingValueAsType(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
2575            if (meaning & (SymbolFlags.Type & ~SymbolFlags.Namespace)) {
2576                const symbol = resolveSymbol(resolveName(errorLocation, name, ~SymbolFlags.Type & SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
2577                if (symbol && !(symbol.flags & SymbolFlags.Namespace)) {
2578                    error(errorLocation, Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, unescapeLeadingUnderscores(name));
2579                    return true;
2580                }
2581            }
2582            return false;
2583        }
2584
2585        function isPrimitiveTypeName(name: __String) {
2586            return name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never" || name === "unknown";
2587        }
2588
2589        function checkAndReportErrorForExportingPrimitiveType(errorLocation: Node, name: __String): boolean {
2590            if (isPrimitiveTypeName(name) && errorLocation.parent.kind === SyntaxKind.ExportSpecifier) {
2591                error(errorLocation, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name as string);
2592                return true;
2593            }
2594            return false;
2595        }
2596
2597        function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
2598            if (meaning & SymbolFlags.Value) {
2599                if (isPrimitiveTypeName(name)) {
2600                    if (isExtendedByInterface(errorLocation)) {
2601                        error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name));
2602                    }
2603                    else {
2604                        error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
2605                    }
2606                    return true;
2607                }
2608                const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
2609                const allFlags = symbol && getAllSymbolFlags(symbol);
2610                if (symbol && allFlags !== undefined && !(allFlags & SymbolFlags.Value)) {
2611                    const rawName = unescapeLeadingUnderscores(name);
2612                    if (isES2015OrLaterConstructorName(name)) {
2613                        error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, rawName);
2614                    }
2615                    else if (maybeMappedType(errorLocation, symbol)) {
2616                        error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, rawName, rawName === "K" ? "P" : "K");
2617                    }
2618                    else {
2619                        error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, rawName);
2620                    }
2621                    return true;
2622                }
2623            }
2624            return false;
2625        }
2626
2627        function isExtendedByInterface(node: Node): boolean {
2628            const grandparent = node.parent.parent;
2629            const parentOfGrandparent = grandparent.parent;
2630            if(grandparent && parentOfGrandparent){
2631                const isExtending = isHeritageClause(grandparent) && grandparent.token === SyntaxKind.ExtendsKeyword;
2632                const isInterface = isInterfaceDeclaration(parentOfGrandparent);
2633                return isExtending && isInterface;
2634            }
2635            return false;
2636        }
2637
2638        function maybeMappedType(node: Node, symbol: Symbol) {
2639            const container = findAncestor(node.parent, n =>
2640                isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | undefined;
2641            if (container && container.members.length === 1) {
2642                const type = getDeclaredTypeOfSymbol(symbol);
2643                return !!(type.flags & TypeFlags.Union) && allTypesAssignableToKind(type, TypeFlags.StringOrNumberLiteral, /*strict*/ true);
2644            }
2645            return false;
2646        }
2647
2648        function isES2015OrLaterConstructorName(n: __String) {
2649            switch (n) {
2650                case "Promise":
2651                case "Symbol":
2652                case "Map":
2653                case "WeakMap":
2654                case "Set":
2655                case "WeakSet":
2656                    return true;
2657            }
2658            return false;
2659        }
2660
2661        function checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
2662            if (meaning & (SymbolFlags.Value & ~SymbolFlags.Type)) {
2663                const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
2664                if (symbol) {
2665                    error(
2666                        errorLocation,
2667                        Diagnostics.Cannot_use_namespace_0_as_a_value,
2668                        unescapeLeadingUnderscores(name));
2669                    return true;
2670                }
2671            }
2672            else if (meaning & (SymbolFlags.Type & ~SymbolFlags.Value)) {
2673                const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Module, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
2674                if (symbol) {
2675                    error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeLeadingUnderscores(name));
2676                    return true;
2677                }
2678            }
2679            return false;
2680        }
2681
2682        function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
2683            Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum));
2684            if (result.flags & (SymbolFlags.Function | SymbolFlags.FunctionScopedVariable | SymbolFlags.Assignment) && result.flags & SymbolFlags.Class) {
2685                // constructor functions aren't block scoped
2686                return;
2687            }
2688            // Block-scoped variables cannot be used before their definition
2689            const declaration = result.declarations?.find(
2690                d => isBlockOrCatchScoped(d) || isClassLike(d) || isAnnotationDeclaration(d) || (d.kind === SyntaxKind.EnumDeclaration));
2691
2692            if (declaration === undefined) return Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration");
2693
2694            if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) {
2695                let diagnosticMessage;
2696                const declarationName = declarationNameToString(getNameOfDeclaration(declaration));
2697                if (result.flags & SymbolFlags.BlockScopedVariable) {
2698                    diagnosticMessage = error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationName);
2699                }
2700                else if (result.flags & SymbolFlags.Annotation) {
2701                    diagnosticMessage = error(errorLocation, Diagnostics.Annotation_0_used_before_its_declaration, declarationName);
2702                }
2703                else if (result.flags & SymbolFlags.Class) {
2704                    diagnosticMessage = error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationName);
2705                }
2706                else if (result.flags & SymbolFlags.RegularEnum) {
2707                    diagnosticMessage = error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationName);
2708                }
2709                else {
2710                    Debug.assert(!!(result.flags & SymbolFlags.ConstEnum));
2711                    if (shouldPreserveConstEnums(compilerOptions)) {
2712                        diagnosticMessage = error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationName);
2713                    }
2714                }
2715
2716                if (diagnosticMessage) {
2717                    addRelatedInfo(diagnosticMessage,
2718                        createDiagnosticForNode(declaration, Diagnostics._0_is_declared_here, declarationName)
2719                    );
2720                }
2721            }
2722        }
2723
2724        /* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached.
2725         * If at any point current node is equal to 'parent' node - return true.
2726         * If current node is an IIFE, continue walking up.
2727         * Return false if 'stopAt' node is reached or isFunctionLike(current) === true.
2728         */
2729        function isSameScopeDescendentOf(initial: Node, parent: Node | undefined, stopAt: Node): boolean {
2730            return !!parent && !!findAncestor(initial, n => n === parent
2731                || (n === stopAt || isFunctionLike(n) && !getImmediatelyInvokedFunctionExpression(n) ? "quit" : false));
2732        }
2733
2734        function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined {
2735            switch (node.kind) {
2736                case SyntaxKind.ImportEqualsDeclaration:
2737                    return node as ImportEqualsDeclaration;
2738                case SyntaxKind.ImportClause:
2739                    return (node as ImportClause).parent;
2740                case SyntaxKind.NamespaceImport:
2741                    return (node as NamespaceImport).parent.parent;
2742                case SyntaxKind.ImportSpecifier:
2743                    return (node as ImportSpecifier).parent.parent.parent;
2744                default:
2745                    return undefined;
2746            }
2747        }
2748
2749        function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined {
2750            return symbol.declarations && findLast<Declaration>(symbol.declarations, isAliasSymbolDeclaration);
2751        }
2752
2753        /**
2754         * An alias symbol is created by one of the following declarations:
2755         * import <symbol> = ...
2756         * import <symbol> from ...
2757         * import * as <symbol> from ...
2758         * import { x as <symbol> } from ...
2759         * export { x as <symbol> } from ...
2760         * export * as ns <symbol> from ...
2761         * export = <EntityNameExpression>
2762         * export default <EntityNameExpression>
2763         * module.exports = <EntityNameExpression>
2764         * {<Identifier>}
2765         * {name: <EntityNameExpression>}
2766         * const { x } = require ...
2767         */
2768        function isAliasSymbolDeclaration(node: Node): boolean {
2769            return node.kind === SyntaxKind.ImportEqualsDeclaration
2770                || node.kind === SyntaxKind.NamespaceExportDeclaration
2771                || node.kind === SyntaxKind.ImportClause && !!(node as ImportClause).name
2772                || node.kind === SyntaxKind.NamespaceImport
2773                || node.kind === SyntaxKind.NamespaceExport
2774                || node.kind === SyntaxKind.ImportSpecifier
2775                || node.kind === SyntaxKind.ExportSpecifier
2776                || node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node as ExportAssignment)
2777                || isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node)
2778                || isAccessExpression(node)
2779                    && isBinaryExpression(node.parent)
2780                    && node.parent.left === node
2781                    && node.parent.operatorToken.kind === SyntaxKind.EqualsToken
2782                    && isAliasableOrJsExpression(node.parent.right)
2783                || node.kind === SyntaxKind.ShorthandPropertyAssignment
2784                || node.kind === SyntaxKind.PropertyAssignment && isAliasableOrJsExpression((node as PropertyAssignment).initializer)
2785                || node.kind === SyntaxKind.VariableDeclaration && isVariableDeclarationInitializedToBareOrAccessedRequire(node)
2786                || node.kind === SyntaxKind.BindingElement && isVariableDeclarationInitializedToBareOrAccessedRequire(node.parent.parent);
2787        }
2788
2789        function isAliasableOrJsExpression(e: Expression) {
2790            return isAliasableExpression(e) || isFunctionExpression(e) && isJSConstructor(e);
2791        }
2792
2793        function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration | VariableDeclaration, dontResolveAlias: boolean): Symbol | undefined {
2794            const commonJSPropertyAccess = getCommonJSPropertyAccess(node);
2795            if (commonJSPropertyAccess) {
2796                const name = (getLeftmostAccessExpression(commonJSPropertyAccess.expression) as CallExpression).arguments[0] as StringLiteral;
2797                return isIdentifier(commonJSPropertyAccess.name)
2798                    ? resolveSymbol(getPropertyOfType(resolveExternalModuleTypeByLiteral(name), commonJSPropertyAccess.name.escapedText))
2799                    : undefined;
2800            }
2801            if (isVariableDeclaration(node) || node.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
2802                const immediate = resolveExternalModuleName(
2803                    node,
2804                    getExternalModuleRequireArgument(node) || getExternalModuleImportEqualsDeclarationExpression(node));
2805                const resolved = resolveExternalModuleSymbol(immediate);
2806                markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false);
2807                return resolved;
2808            }
2809            const resolved = getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, dontResolveAlias);
2810            checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node, resolved);
2811            return resolved;
2812        }
2813
2814        function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ImportEqualsDeclaration, resolved: Symbol | undefined) {
2815            if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false) && !node.isTypeOnly) {
2816                const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfNode(node))!;
2817                const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier;
2818                const message = isExport
2819                    ? Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type
2820                    : Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_imported_using_import_type;
2821                const relatedMessage = isExport
2822                    ? Diagnostics._0_was_exported_here
2823                    : Diagnostics._0_was_imported_here;
2824
2825                const name = unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText);
2826                addRelatedInfo(error(node.moduleReference, message), createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name));
2827            }
2828        }
2829
2830        function resolveExportByName(moduleSymbol: Symbol, name: __String, sourceNode: TypeOnlyCompatibleAliasDeclaration | undefined, dontResolveAlias: boolean) {
2831            const exportValue = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals);
2832            const exportSymbol = exportValue ? getPropertyOfType(getTypeOfSymbol(exportValue), name) : moduleSymbol.exports!.get(name);
2833            const resolved = resolveSymbol(exportSymbol, dontResolveAlias);
2834            markSymbolOfAliasDeclarationIfTypeOnly(sourceNode, exportSymbol, resolved, /*overwriteEmpty*/ false);
2835            return resolved;
2836        }
2837
2838        function isSyntacticDefault(node: Node) {
2839            return ((isExportAssignment(node) && !node.isExportEquals) || hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node));
2840        }
2841
2842        function getUsageModeForExpression(usage: Expression) {
2843            return isStringLiteralLike(usage) ? getModeForUsageLocation(getSourceFileOfNode(usage), usage) : undefined;
2844        }
2845
2846        function isESMFormatImportImportingCommonjsFormatFile(usageMode: SourceFile["impliedNodeFormat"], targetMode: SourceFile["impliedNodeFormat"]) {
2847            return usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS;
2848        }
2849
2850        function isOnlyImportedAsDefault(usage: Expression) {
2851            const usageMode = getUsageModeForExpression(usage);
2852            return usageMode === ModuleKind.ESNext && endsWith((usage as StringLiteralLike).text, Extension.Json);
2853        }
2854
2855        function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean, usage: Expression) {
2856            const usageMode = file && getUsageModeForExpression(usage);
2857            if (file && usageMode !== undefined) {
2858                const result = isESMFormatImportImportingCommonjsFormatFile(usageMode, file.impliedNodeFormat);
2859                if (usageMode === ModuleKind.ESNext || result) {
2860                    return result;
2861                }
2862                // fallthrough on cjs usages so we imply defaults for interop'd imports, too
2863            }
2864            if (!allowSyntheticDefaultImports) {
2865                return false;
2866            }
2867            // Declaration files (and ambient modules)
2868            if (!file || file.isDeclarationFile) {
2869                // Definitely cannot have a synthetic default if they have a syntactic default member specified
2870                const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, /*sourceNode*/ undefined, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration
2871                if (defaultExportSymbol && some(defaultExportSymbol.declarations, isSyntacticDefault)) {
2872                    return false;
2873                }
2874                // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
2875                // So we check a bit more,
2876                if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias)) {
2877                    // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code),
2878                    // it definitely is a module and does not have a synthetic default
2879                    return false;
2880                }
2881                // There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set
2882                // Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member
2883                // as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm
2884                return true;
2885            }
2886            // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement
2887            if (!isSourceFileJS(file)) {
2888                return hasExportAssignmentSymbol(moduleSymbol);
2889            }
2890            // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker
2891            return typeof file.externalModuleIndicator !== "object" && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias);
2892        }
2893
2894        function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined {
2895            const moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier);
2896            if (moduleSymbol) {
2897                return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias);
2898            }
2899        }
2900
2901        function getTargetofModuleDefault(moduleSymbol: Symbol, node: ImportClause | ImportOrExportSpecifier, dontResolveAlias: boolean) {
2902            let exportDefaultSymbol: Symbol | undefined;
2903            if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
2904                exportDefaultSymbol = moduleSymbol;
2905            }
2906            else {
2907                exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, node, dontResolveAlias);
2908            }
2909
2910            const file = moduleSymbol.declarations?.find(isSourceFile);
2911            const specifier = getModuleSpecifierForImportOrExport(node);
2912            if (!specifier) {
2913                return exportDefaultSymbol;
2914            }
2915            const hasDefaultOnly = isOnlyImportedAsDefault(specifier);
2916            const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier);
2917            if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) {
2918                if (hasExportAssignmentSymbol(moduleSymbol)) {
2919                    const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop";
2920                    const exportEqualsSymbol = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals);
2921                    const exportAssignment = exportEqualsSymbol!.valueDeclaration;
2922                    const err = error(node.name, Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), compilerOptionName);
2923
2924                    if (exportAssignment) {
2925                        addRelatedInfo(err, createDiagnosticForNode(
2926                            exportAssignment,
2927                            Diagnostics.This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag,
2928                            compilerOptionName
2929                        ));
2930                    }
2931                }
2932                else if (isImportClause(node)) {
2933                    reportNonDefaultExport(moduleSymbol, node);
2934                }
2935                else {
2936                    errorNoModuleMemberSymbol(moduleSymbol, moduleSymbol, node, isImportOrExportSpecifier(node) && node.propertyName || node.name);
2937                }
2938            }
2939            else if (hasSyntheticDefault || hasDefaultOnly) {
2940                // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
2941                const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
2942                markSymbolOfAliasDeclarationIfTypeOnly(node, moduleSymbol, resolved, /*overwriteTypeOnly*/ false);
2943                return resolved;
2944            }
2945            markSymbolOfAliasDeclarationIfTypeOnly(node, exportDefaultSymbol, /*finalTarget*/ undefined, /*overwriteTypeOnly*/ false);
2946            return exportDefaultSymbol;
2947        }
2948
2949        function getModuleSpecifierForImportOrExport(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportOrExportSpecifier): Expression | undefined {
2950            switch (node.kind) {
2951                case SyntaxKind.ImportClause: return node.parent.moduleSpecifier;
2952                case SyntaxKind.ImportEqualsDeclaration: return isExternalModuleReference(node.moduleReference) ? node.moduleReference.expression : undefined;
2953                case SyntaxKind.NamespaceImport: return node.parent.parent.moduleSpecifier;
2954                case SyntaxKind.ImportSpecifier: return node.parent.parent.parent.moduleSpecifier;
2955                case SyntaxKind.ExportSpecifier: return node.parent.parent.moduleSpecifier;
2956                default: return Debug.assertNever(node);
2957            }
2958        }
2959
2960        function reportNonDefaultExport(moduleSymbol: Symbol, node: ImportClause) {
2961            if (moduleSymbol.exports?.has(node.symbol.escapedName)) {
2962                error(
2963                    node.name,
2964                    Diagnostics.Module_0_has_no_default_export_Did_you_mean_to_use_import_1_from_0_instead,
2965                    symbolToString(moduleSymbol),
2966                    symbolToString(node.symbol),
2967                );
2968            }
2969            else {
2970                const diagnostic = error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
2971                const exportStar = moduleSymbol.exports?.get(InternalSymbolName.ExportStar);
2972                if (exportStar) {
2973                    const defaultExport = exportStar.declarations?.find(decl => !!(
2974                        isExportDeclaration(decl) && decl.moduleSpecifier &&
2975                            resolveExternalModuleName(decl, decl.moduleSpecifier)?.exports?.has(InternalSymbolName.Default)
2976                    ));
2977                    if (defaultExport) {
2978                        addRelatedInfo(diagnostic, createDiagnosticForNode(defaultExport, Diagnostics.export_Asterisk_does_not_re_export_a_default));
2979                    }
2980                }
2981            }
2982        }
2983
2984        function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined {
2985            const moduleSpecifier = node.parent.parent.moduleSpecifier;
2986            const immediate = resolveExternalModuleName(node, moduleSpecifier);
2987            const resolved = resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
2988            markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false);
2989            return resolved;
2990        }
2991
2992        function getTargetOfNamespaceExport(node: NamespaceExport, dontResolveAlias: boolean): Symbol | undefined {
2993            const moduleSpecifier = node.parent.moduleSpecifier;
2994            const immediate = moduleSpecifier && resolveExternalModuleName(node, moduleSpecifier);
2995            const resolved = moduleSpecifier && resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
2996            markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false);
2997            return resolved;
2998        }
2999
3000        // This function creates a synthetic symbol that combines the value side of one symbol with the
3001        // type/namespace side of another symbol. Consider this example:
3002        //
3003        //   declare module graphics {
3004        //       interface Point {
3005        //           x: number;
3006        //           y: number;
3007        //       }
3008        //   }
3009        //   declare var graphics: {
3010        //       Point: new (x: number, y: number) => graphics.Point;
3011        //   }
3012        //   declare module "graphics" {
3013        //       export = graphics;
3014        //   }
3015        //
3016        // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point'
3017        // property with the type/namespace side interface 'Point'.
3018        function combineValueAndTypeSymbols(valueSymbol: Symbol, typeSymbol: Symbol): Symbol {
3019            if (valueSymbol === unknownSymbol && typeSymbol === unknownSymbol) {
3020                return unknownSymbol;
3021            }
3022            if (valueSymbol.flags & (SymbolFlags.Type | SymbolFlags.Namespace)) {
3023                return valueSymbol;
3024            }
3025            const result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName);
3026            result.declarations = deduplicate(concatenate(valueSymbol.declarations, typeSymbol.declarations), equateValues);
3027            result.parent = valueSymbol.parent || typeSymbol.parent;
3028            if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration;
3029            if (typeSymbol.members) result.members = new Map(typeSymbol.members);
3030            if (valueSymbol.exports) result.exports = new Map(valueSymbol.exports);
3031            return result;
3032        }
3033
3034        function getExportOfModule(symbol: Symbol, name: Identifier, specifier: Declaration, dontResolveAlias: boolean): Symbol | undefined {
3035            if (symbol.flags & SymbolFlags.Module) {
3036                const exportSymbol = getExportsOfSymbol(symbol).get(name.escapedText);
3037                const resolved = resolveSymbol(exportSymbol, dontResolveAlias);
3038                markSymbolOfAliasDeclarationIfTypeOnly(specifier, exportSymbol, resolved, /*overwriteEmpty*/ false);
3039                return resolved;
3040            }
3041        }
3042
3043        function getPropertyOfVariable(symbol: Symbol, name: __String): Symbol | undefined {
3044            if (symbol.flags & SymbolFlags.Variable) {
3045                const typeAnnotation = (symbol.valueDeclaration as VariableDeclaration).type;
3046                if (typeAnnotation) {
3047                    return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name));
3048                }
3049            }
3050        }
3051
3052        function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, dontResolveAlias = false): Symbol | undefined {
3053            const moduleSpecifier = getExternalModuleRequireArgument(node) || (node as ImportDeclaration | ExportDeclaration).moduleSpecifier!;
3054            const moduleSymbol = resolveExternalModuleName(node, moduleSpecifier)!; // TODO: GH#18217
3055            const name = !isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name;
3056            if (!isIdentifier(name)) {
3057                return undefined;
3058            }
3059            const suppressInteropError = name.escapedText === InternalSymbolName.Default && !!(compilerOptions.allowSyntheticDefaultImports || getESModuleInterop(compilerOptions));
3060            const targetSymbol = resolveESModuleSymbol(moduleSymbol, moduleSpecifier, /*dontResolveAlias*/ false, suppressInteropError);
3061            if (targetSymbol) {
3062                if (name.escapedText) {
3063                    if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
3064                        return moduleSymbol;
3065                    }
3066
3067                    let symbolFromVariable: Symbol | undefined;
3068                    // First check if module was specified with "export=". If so, get the member from the resolved type
3069                    if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) {
3070                        symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText, /*skipObjectFunctionPropertyAugment*/ true);
3071                    }
3072                    else {
3073                        symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText);
3074                    }
3075                    // if symbolFromVariable is export - get its final target
3076                    symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias);
3077
3078                    let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias);
3079                    if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) {
3080                        const file = moduleSymbol.declarations?.find(isSourceFile);
3081                        if (isOnlyImportedAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) {
3082                            symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
3083                        }
3084                    }
3085
3086                    const symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable ?
3087                        combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
3088                        symbolFromModule || symbolFromVariable;
3089                    if (!symbol) {
3090                        errorNoModuleMemberSymbol(moduleSymbol, targetSymbol, node, name);
3091                    }
3092                    return symbol;
3093                }
3094            }
3095        }
3096
3097        function errorNoModuleMemberSymbol(moduleSymbol: Symbol, targetSymbol: Symbol, node: Node, name: Identifier) {
3098            const moduleName = getFullyQualifiedName(moduleSymbol, node);
3099            const declarationName = declarationNameToString(name);
3100            const suggestion = getSuggestedSymbolForNonexistentModule(name, targetSymbol);
3101            if (suggestion !== undefined) {
3102                const suggestionName = symbolToString(suggestion);
3103                const diagnostic = error(name, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName);
3104                if (suggestion.valueDeclaration) {
3105                    addRelatedInfo(diagnostic,
3106                        createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
3107                    );
3108                }
3109            }
3110            else {
3111                if (moduleSymbol.exports?.has(InternalSymbolName.Default)) {
3112                    error(
3113                        name,
3114                        Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_to_use_import_1_from_0_instead,
3115                        moduleName,
3116                        declarationName
3117                    );
3118                }
3119                else {
3120                    reportNonExportedMember(node, name, declarationName, moduleSymbol, moduleName);
3121                }
3122            }
3123        }
3124
3125        function reportNonExportedMember(node: Node, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void {
3126            const localSymbol = moduleSymbol.valueDeclaration?.locals?.get(name.escapedText);
3127            const exports = moduleSymbol.exports;
3128            if (localSymbol) {
3129                const exportedEqualsSymbol = exports?.get(InternalSymbolName.ExportEquals);
3130                if (exportedEqualsSymbol) {
3131                    getSymbolIfSameReference(exportedEqualsSymbol, localSymbol) ? reportInvalidImportEqualsExportMember(node, name, declarationName, moduleName) :
3132                        error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
3133                }
3134                else {
3135                    const exportedSymbol = exports ? find(symbolsToArray(exports), symbol => !!getSymbolIfSameReference(symbol, localSymbol)) : undefined;
3136                    const diagnostic = exportedSymbol ? error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, declarationName, symbolToString(exportedSymbol)) :
3137                        error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName);
3138                    if (localSymbol.declarations) {
3139                        addRelatedInfo(diagnostic,
3140                            ...map(localSymbol.declarations, (decl, index) =>
3141                                createDiagnosticForNode(decl, index === 0 ? Diagnostics._0_is_declared_here : Diagnostics.and_here, declarationName)));
3142                    }
3143                }
3144            }
3145            else {
3146                error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
3147            }
3148        }
3149
3150        function reportInvalidImportEqualsExportMember(node: Node, name: Identifier, declarationName: string, moduleName: string) {
3151            if (moduleKind >= ModuleKind.ES2015) {
3152                const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_default_import :
3153                    Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
3154                error(name, message, declarationName);
3155            }
3156            else {
3157                if (isInJSFile(node)) {
3158                    const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_using_a_default_import :
3159                        Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
3160                    error(name, message, declarationName);
3161                }
3162                else {
3163                    const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_a_default_import :
3164                        Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
3165                    error(name, message, declarationName, declarationName, moduleName);
3166                }
3167            }
3168        }
3169
3170        function getTargetOfImportSpecifier(node: ImportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined {
3171            if (isImportSpecifier(node) && idText(node.propertyName || node.name) === InternalSymbolName.Default) {
3172                const specifier = getModuleSpecifierForImportOrExport(node);
3173                const moduleSymbol = specifier && resolveExternalModuleName(node, specifier);
3174                if (moduleSymbol) {
3175                    return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias);
3176                }
3177            }
3178            const root = isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration : node.parent.parent.parent;
3179            const commonJSPropertyAccess = getCommonJSPropertyAccess(root);
3180            const resolved = getExternalModuleMember(root, commonJSPropertyAccess || node, dontResolveAlias);
3181            const name = node.propertyName || node.name;
3182            if (commonJSPropertyAccess && resolved && isIdentifier(name)) {
3183                return resolveSymbol(getPropertyOfType(getTypeOfSymbol(resolved), name.escapedText), dontResolveAlias);
3184            }
3185            markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
3186            return resolved;
3187        }
3188
3189        function getCommonJSPropertyAccess(node: Node) {
3190            if (isVariableDeclaration(node) && node.initializer && isPropertyAccessExpression(node.initializer)) {
3191                return node.initializer;
3192            }
3193        }
3194
3195        function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol {
3196            const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias);
3197            markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
3198            return resolved;
3199        }
3200
3201        function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) {
3202            if (idText(node.propertyName || node.name) === InternalSymbolName.Default) {
3203                const specifier = getModuleSpecifierForImportOrExport(node);
3204                const moduleSymbol = specifier && resolveExternalModuleName(node, specifier);
3205                if (moduleSymbol) {
3206                    return getTargetofModuleDefault(moduleSymbol, node, !!dontResolveAlias);
3207                }
3208            }
3209            const resolved = node.parent.parent.moduleSpecifier ?
3210                getExternalModuleMember(node.parent.parent, node, dontResolveAlias) :
3211                resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias);
3212            markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
3213            return resolved;
3214        }
3215
3216        function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined {
3217            const expression = isExportAssignment(node) ? node.expression : node.right;
3218            const resolved = getTargetOfAliasLikeExpression(expression, dontResolveAlias);
3219            markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
3220            return resolved;
3221        }
3222
3223        function getTargetOfAliasLikeExpression(expression: Expression, dontResolveAlias: boolean) {
3224            if (isClassExpression(expression)) {
3225                return checkExpressionCached(expression).symbol;
3226            }
3227            if (!isEntityName(expression) && !isEntityNameExpression(expression)) {
3228                return undefined;
3229            }
3230            const aliasLike = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias);
3231            if (aliasLike) {
3232                return aliasLike;
3233            }
3234            checkExpressionCached(expression);
3235            return getNodeLinks(expression).resolvedSymbol;
3236        }
3237
3238        function getTargetOfAccessExpression(node: AccessExpression, dontRecursivelyResolve: boolean): Symbol | undefined {
3239            if (!(isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken)) {
3240                return undefined;
3241            }
3242
3243            return getTargetOfAliasLikeExpression(node.parent.right, dontRecursivelyResolve);
3244        }
3245
3246        function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve = false): Symbol | undefined {
3247            switch (node.kind) {
3248                case SyntaxKind.ImportEqualsDeclaration:
3249                case SyntaxKind.VariableDeclaration:
3250                    return getTargetOfImportEqualsDeclaration(node as ImportEqualsDeclaration | VariableDeclaration, dontRecursivelyResolve);
3251                case SyntaxKind.ImportClause:
3252                    return getTargetOfImportClause(node as ImportClause, dontRecursivelyResolve);
3253                case SyntaxKind.NamespaceImport:
3254                    return getTargetOfNamespaceImport(node as NamespaceImport, dontRecursivelyResolve);
3255                case SyntaxKind.NamespaceExport:
3256                    return getTargetOfNamespaceExport(node as NamespaceExport, dontRecursivelyResolve);
3257                case SyntaxKind.ImportSpecifier:
3258                case SyntaxKind.BindingElement:
3259                    return getTargetOfImportSpecifier(node as ImportSpecifier | BindingElement, dontRecursivelyResolve);
3260                case SyntaxKind.ExportSpecifier:
3261                    return getTargetOfExportSpecifier(node as ExportSpecifier, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, dontRecursivelyResolve);
3262                case SyntaxKind.ExportAssignment:
3263                case SyntaxKind.BinaryExpression:
3264                    return getTargetOfExportAssignment((node as ExportAssignment | BinaryExpression), dontRecursivelyResolve);
3265                case SyntaxKind.NamespaceExportDeclaration:
3266                    return getTargetOfNamespaceExportDeclaration(node as NamespaceExportDeclaration, dontRecursivelyResolve);
3267                case SyntaxKind.ShorthandPropertyAssignment:
3268                    return resolveEntityName((node as ShorthandPropertyAssignment).name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontRecursivelyResolve);
3269                case SyntaxKind.PropertyAssignment:
3270                    return getTargetOfAliasLikeExpression((node as PropertyAssignment).initializer, dontRecursivelyResolve);
3271                case SyntaxKind.ElementAccessExpression:
3272                case SyntaxKind.PropertyAccessExpression:
3273                    return getTargetOfAccessExpression(node as AccessExpression, dontRecursivelyResolve);
3274                default:
3275                    return Debug.fail();
3276            }
3277        }
3278
3279        /**
3280         * Indicates that a symbol is an alias that does not merge with a local declaration.
3281         * OR Is a JSContainer which may merge an alias with a local declaration
3282         */
3283        function isNonLocalAlias(symbol: Symbol | undefined, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace): symbol is Symbol {
3284            if (!symbol) return false;
3285            return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.Assignment);
3286        }
3287
3288        function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol;
3289        function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined;
3290        function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined {
3291            return !dontResolveAlias && isNonLocalAlias(symbol) ? resolveAlias(symbol) : symbol;
3292        }
3293
3294        function resolveAlias(symbol: Symbol): Symbol {
3295            Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here.");
3296            const links = getSymbolLinks(symbol);
3297            if (!links.aliasTarget) {
3298                links.aliasTarget = resolvingSymbol;
3299                const node = getDeclarationOfAliasSymbol(symbol);
3300                if (!node) return Debug.fail();
3301                const target = getTargetOfAliasDeclaration(node);
3302                if (links.aliasTarget === resolvingSymbol) {
3303                    links.aliasTarget = target || unknownSymbol;
3304                }
3305                else {
3306                    error(node, Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol));
3307                }
3308            }
3309            else if (links.aliasTarget === resolvingSymbol) {
3310                links.aliasTarget = unknownSymbol;
3311            }
3312            return links.aliasTarget;
3313        }
3314
3315        function tryResolveAlias(symbol: Symbol): Symbol | undefined {
3316            const links = getSymbolLinks(symbol);
3317            if (links.aliasTarget !== resolvingSymbol) {
3318                return resolveAlias(symbol);
3319            }
3320
3321            return undefined;
3322        }
3323
3324        /**
3325         * Gets combined flags of a `symbol` and all alias targets it resolves to. `resolveAlias`
3326         * is typically recursive over chains of aliases, but stops mid-chain if an alias is merged
3327         * with another exported symbol, e.g.
3328         * ```ts
3329         * // a.ts
3330         * export const a = 0;
3331         * // b.ts
3332         * export { a } from "./a";
3333         * export type a = number;
3334         * // c.ts
3335         * import { a } from "./b";
3336         * ```
3337         * Calling `resolveAlias` on the `a` in c.ts would stop at the merged symbol exported
3338         * from b.ts, even though there is still more alias to resolve. Consequently, if we were
3339         * trying to determine if the `a` in c.ts has a value meaning, looking at the flags on
3340         * the local symbol and on the symbol returned by `resolveAlias` is not enough.
3341         * @returns SymbolFlags.All if `symbol` is an alias that ultimately resolves to `unknown`;
3342         * combined flags of all alias targets otherwise.
3343         */
3344        function getAllSymbolFlags(symbol: Symbol): SymbolFlags {
3345          let flags = symbol.flags;
3346          let seenSymbols;
3347          while (symbol.flags & SymbolFlags.Alias) {
3348              const target = resolveAlias(symbol);
3349              if (target === unknownSymbol) {
3350                  return SymbolFlags.All;
3351              }
3352
3353              // Optimizations - try to avoid creating or adding to
3354              // `seenSymbols` if possible
3355              if (target === symbol || seenSymbols?.has(target)) {
3356                  break;
3357              }
3358              if (target.flags & SymbolFlags.Alias) {
3359                  if (seenSymbols) {
3360                      seenSymbols.add(target);
3361                  }
3362                  else {
3363                      seenSymbols = new Set([symbol, target]);
3364                  }
3365              }
3366              flags |= target.flags;
3367              symbol = target;
3368          }
3369          return flags;
3370        }
3371
3372        /**
3373         * Marks a symbol as type-only if its declaration is syntactically type-only.
3374         * If it is not itself marked type-only, but resolves to a type-only alias
3375         * somewhere in its resolution chain, save a reference to the type-only alias declaration
3376         * so the alias _not_ marked type-only can be identified as _transitively_ type-only.
3377         *
3378         * This function is called on each alias declaration that could be type-only or resolve to
3379         * another type-only alias during `resolveAlias`, so that later, when an alias is used in a
3380         * JS-emitting expression, we can quickly determine if that symbol is effectively type-only
3381         * and issue an error if so.
3382         *
3383         * @param aliasDeclaration The alias declaration not marked as type-only
3384         * @param immediateTarget The symbol to which the alias declaration immediately resolves
3385         * @param finalTarget The symbol to which the alias declaration ultimately resolves
3386         * @param overwriteEmpty Checks `resolvesToSymbol` for type-only declarations even if `aliasDeclaration`
3387         * has already been marked as not resolving to a type-only alias. Used when recursively resolving qualified
3388         * names of import aliases, e.g. `import C = a.b.C`. If namespace `a` is not found to be type-only, the
3389         * import declaration will initially be marked as not resolving to a type-only symbol. But, namespace `b`
3390         * must still be checked for a type-only marker, overwriting the previous negative result if found.
3391         */
3392        function markSymbolOfAliasDeclarationIfTypeOnly(
3393            aliasDeclaration: Declaration | undefined,
3394            immediateTarget: Symbol | undefined,
3395            finalTarget: Symbol | undefined,
3396            overwriteEmpty: boolean,
3397        ): boolean {
3398            if (!aliasDeclaration || isPropertyAccessExpression(aliasDeclaration)) return false;
3399
3400            // If the declaration itself is type-only, mark it and return.
3401            // No need to check what it resolves to.
3402            const sourceSymbol = getSymbolOfNode(aliasDeclaration);
3403            if (isTypeOnlyImportOrExportDeclaration(aliasDeclaration)) {
3404                const links = getSymbolLinks(sourceSymbol);
3405                links.typeOnlyDeclaration = aliasDeclaration;
3406                return true;
3407            }
3408
3409            const links = getSymbolLinks(sourceSymbol);
3410            return markSymbolOfAliasDeclarationIfTypeOnlyWorker(links, immediateTarget, overwriteEmpty)
3411                || markSymbolOfAliasDeclarationIfTypeOnlyWorker(links, finalTarget, overwriteEmpty);
3412        }
3413
3414        function markSymbolOfAliasDeclarationIfTypeOnlyWorker(aliasDeclarationLinks: SymbolLinks, target: Symbol | undefined, overwriteEmpty: boolean): boolean {
3415            if (target && (aliasDeclarationLinks.typeOnlyDeclaration === undefined || overwriteEmpty && aliasDeclarationLinks.typeOnlyDeclaration === false)) {
3416                const exportSymbol = target.exports?.get(InternalSymbolName.ExportEquals) ?? target;
3417                const typeOnly = exportSymbol.declarations && find(exportSymbol.declarations, isTypeOnlyImportOrExportDeclaration);
3418                aliasDeclarationLinks.typeOnlyDeclaration = typeOnly ?? getSymbolLinks(exportSymbol).typeOnlyDeclaration ?? false;
3419            }
3420            return !!aliasDeclarationLinks.typeOnlyDeclaration;
3421        }
3422
3423        /** Indicates that a symbol directly or indirectly resolves to a type-only import or export. */
3424        function getTypeOnlyAliasDeclaration(symbol: Symbol, include?: SymbolFlags): TypeOnlyAliasDeclaration | undefined {
3425            if (!(symbol.flags & SymbolFlags.Alias)) {
3426                return undefined;
3427            }
3428            const links = getSymbolLinks(symbol);
3429            if (include === undefined) {
3430                return links.typeOnlyDeclaration || undefined;
3431            }
3432            if (links.typeOnlyDeclaration) {
3433                return getAllSymbolFlags(resolveAlias(links.typeOnlyDeclaration.symbol)) & include ? links.typeOnlyDeclaration : undefined;
3434            }
3435            return undefined;
3436        }
3437
3438        function markExportAsReferenced(node: ImportEqualsDeclaration | ExportSpecifier) {
3439            const symbol = getSymbolOfNode(node);
3440            const target = resolveAlias(symbol);
3441            if (target) {
3442                const markAlias = target === unknownSymbol ||
3443                    ((getAllSymbolFlags(target) & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value));
3444
3445                if (markAlias) {
3446                    markAliasSymbolAsReferenced(symbol);
3447                }
3448            }
3449        }
3450
3451        // When an alias symbol is referenced, we need to mark the entity it references as referenced and in turn repeat that until
3452        // we reach a non-alias or an exported entity (which is always considered referenced). We do this by checking the target of
3453        // the alias as an expression (which recursively takes us back here if the target references another alias).
3454        function markAliasSymbolAsReferenced(symbol: Symbol) {
3455            const links = getSymbolLinks(symbol);
3456            if (!links.referenced) {
3457                links.referenced = true;
3458                const node = getDeclarationOfAliasSymbol(symbol);
3459                if (!node) return Debug.fail();
3460                // We defer checking of the reference of an `import =` until the import itself is referenced,
3461                // This way a chain of imports can be elided if ultimately the final input is only used in a type
3462                // position.
3463                if (isInternalModuleImportEqualsDeclaration(node)) {
3464                    if (getAllSymbolFlags(resolveSymbol(symbol)) & SymbolFlags.Value) {
3465                        // import foo = <symbol>
3466                        checkExpressionCached(node.moduleReference as Expression);
3467                    }
3468                }
3469            }
3470        }
3471
3472        // Aliases that resolve to const enums are not marked as referenced because they are not emitted,
3473        // but their usage in value positions must be tracked to determine if the import can be type-only.
3474        function markConstEnumAliasAsReferenced(symbol: Symbol) {
3475            const links = getSymbolLinks(symbol);
3476            if (!links.constEnumReferenced) {
3477                links.constEnumReferenced = true;
3478            }
3479        }
3480
3481        // This function is only for imports with entity names
3482        function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol | undefined {
3483            // There are three things we might try to look for. In the following examples,
3484            // the search term is enclosed in |...|:
3485            //
3486            //     import a = |b|; // Namespace
3487            //     import a = |b.c|; // Value, type, namespace
3488            //     import a = |b.c|.d; // Namespace
3489            if (entityName.kind === SyntaxKind.Identifier && isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
3490                entityName = entityName.parent as QualifiedName;
3491            }
3492            // Check for case 1 and 3 in the above example
3493            if (entityName.kind === SyntaxKind.Identifier || entityName.parent.kind === SyntaxKind.QualifiedName) {
3494                return resolveEntityName(entityName, SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias);
3495            }
3496            else {
3497                // Case 2 in above example
3498                // entityName.kind could be a QualifiedName or a Missing identifier
3499                Debug.assert(entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration);
3500                return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias);
3501            }
3502        }
3503
3504        function getFullyQualifiedName(symbol: Symbol, containingLocation?: Node): string {
3505            return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, SymbolFormatFlags.DoNotIncludeSymbolChain | SymbolFormatFlags.AllowAnyNodeKind);
3506        }
3507
3508        function getContainingQualifiedNameNode(node: QualifiedName) {
3509            while (isQualifiedName(node.parent)) {
3510                node = node.parent;
3511            }
3512            return node;
3513        }
3514
3515        function tryGetQualifiedNameAsValue(node: QualifiedName) {
3516            let left: Identifier | QualifiedName = getFirstIdentifier(node);
3517            let symbol = resolveName(left, left.escapedText, SymbolFlags.Value, undefined, left, /*isUse*/ true);
3518            if (!symbol) {
3519                return undefined;
3520            }
3521            while (isQualifiedName(left.parent)) {
3522                const type = getTypeOfSymbol(symbol);
3523                symbol = getPropertyOfType(type, left.parent.right.escapedText);
3524                if (!symbol) {
3525                    return undefined;
3526                }
3527                left = left.parent;
3528            }
3529            return symbol;
3530        }
3531
3532        /**
3533         * Resolves a qualified name and any involved aliases.
3534         */
3535        function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: Node): Symbol | undefined {
3536            if (nodeIsMissing(name)) {
3537                return undefined;
3538            }
3539
3540            const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(name) ? meaning & SymbolFlags.Value : 0);
3541            let symbol: Symbol | undefined;
3542            if (name.kind === SyntaxKind.Identifier) {
3543                const message = meaning === namespaceMeaning || nodeIsSynthesized(name) ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name));
3544                const symbolFromJSPrototype = isInJSFile(name) && !nodeIsSynthesized(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined;
3545                symbol = getMergedSymbol(resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true, false));
3546                if (!symbol) {
3547                    return getMergedSymbol(symbolFromJSPrototype);
3548                }
3549            }
3550            else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) {
3551                const left = name.kind === SyntaxKind.QualifiedName ? name.left : name.expression;
3552                const right = name.kind === SyntaxKind.QualifiedName ? name.right : name.name;
3553                let namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, /*dontResolveAlias*/ false, location);
3554                if (!namespace || nodeIsMissing(right)) {
3555                    return undefined;
3556                }
3557                else if (namespace === unknownSymbol) {
3558                    return namespace;
3559                }
3560                if (
3561                    namespace.valueDeclaration &&
3562                    isInJSFile(namespace.valueDeclaration) &&
3563                    isVariableDeclaration(namespace.valueDeclaration) &&
3564                    namespace.valueDeclaration.initializer &&
3565                    isCommonJsRequire(namespace.valueDeclaration.initializer)
3566                ) {
3567                    const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral;
3568                    const moduleSym = resolveExternalModuleName(moduleName, moduleName);
3569                    if (moduleSym) {
3570                        const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym);
3571                        if (resolvedModuleSymbol) {
3572                            namespace = resolvedModuleSymbol;
3573                        }
3574                    }
3575                }
3576                symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(namespace), right.escapedText, meaning));
3577                if (!symbol) {
3578                    if (!ignoreErrors) {
3579                        const namespaceName = getFullyQualifiedName(namespace);
3580                        const declarationName = declarationNameToString(right);
3581                        const suggestionForNonexistentModule = getSuggestedSymbolForNonexistentModule(right, namespace);
3582                        if (suggestionForNonexistentModule) {
3583                            error(right, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, namespaceName, declarationName, symbolToString(suggestionForNonexistentModule));
3584                            return undefined;
3585                        }
3586
3587                        const containingQualifiedName = isQualifiedName(name) && getContainingQualifiedNameNode(name);
3588                        const canSuggestTypeof = globalObjectType // <-- can't pull on types if global types aren't initialized yet
3589                            && (meaning & SymbolFlags.Type)
3590                            && containingQualifiedName
3591                            && !isTypeOfExpression(containingQualifiedName.parent)
3592                            && tryGetQualifiedNameAsValue(containingQualifiedName);
3593                        if (canSuggestTypeof) {
3594                            error(
3595                                containingQualifiedName,
3596                                Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0,
3597                                entityNameToString(containingQualifiedName)
3598                            );
3599                            return undefined;
3600                        }
3601
3602                        if (meaning & SymbolFlags.Namespace && isQualifiedName(name.parent)) {
3603                            const exportedTypeSymbol = getMergedSymbol(getSymbol(getExportsOfSymbol(namespace), right.escapedText, SymbolFlags.Type));
3604                            if (exportedTypeSymbol) {
3605                                error(
3606                                    name.parent.right,
3607                                    Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1,
3608                                    symbolToString(exportedTypeSymbol),
3609                                    unescapeLeadingUnderscores(name.parent.right.escapedText)
3610                                );
3611                                return undefined;
3612                            }
3613                        }
3614
3615                        error(right, Diagnostics.Namespace_0_has_no_exported_member_1, namespaceName, declarationName);
3616                    }
3617                    return undefined;
3618                }
3619            }
3620            else {
3621                throw Debug.assertNever(name, "Unknown entity name kind.");
3622            }
3623            Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
3624            if (!nodeIsSynthesized(name) && isEntityName(name) && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment)) {
3625                markSymbolOfAliasDeclarationIfTypeOnly(getAliasDeclarationFromName(name), symbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ true);
3626            }
3627            return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol);
3628        }
3629
3630        /**
3631         * 1. For prototype-property methods like `A.prototype.m = function () ...`, try to resolve names in the scope of `A` too.
3632         * Note that prototype-property assignment to locations outside the current file (eg globals) doesn't work, so
3633         * name resolution won't work either.
3634         * 2. For property assignments like `{ x: function f () { } }`, try to resolve names in the scope of `f` too.
3635         */
3636        function resolveEntityNameFromAssignmentDeclaration(name: Identifier, meaning: SymbolFlags) {
3637            if (isJSDocTypeReference(name.parent)) {
3638                const secondaryLocation = getAssignmentDeclarationLocation(name.parent);
3639                if (secondaryLocation) {
3640                    return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true);
3641                }
3642            }
3643        }
3644
3645        function getAssignmentDeclarationLocation(node: TypeReferenceNode): Node | undefined {
3646            const typeAlias = findAncestor(node, node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : isJSDocTypeAlias(node));
3647            if (typeAlias) {
3648                return;
3649            }
3650            const host = getJSDocHost(node);
3651            if (host && isExpressionStatement(host) && isPrototypePropertyAssignment(host.expression)) {
3652                // /** @param {K} p */ X.prototype.m = function () { } <-- look for K on X's declaration
3653                const symbol = getSymbolOfNode(host.expression.left);
3654                if (symbol) {
3655                    return getDeclarationOfJSPrototypeContainer(symbol);
3656                }
3657            }
3658            if (host && isFunctionExpression(host) && isPrototypePropertyAssignment(host.parent) && isExpressionStatement(host.parent.parent)) {
3659                // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration
3660                const symbol = getSymbolOfNode(host.parent.left);
3661                if (symbol) {
3662                    return getDeclarationOfJSPrototypeContainer(symbol);
3663                }
3664            }
3665            if (host && (isObjectLiteralMethod(host) || isPropertyAssignment(host)) &&
3666                isBinaryExpression(host.parent.parent) &&
3667                getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype) {
3668                // X.prototype = { /** @param {K} p */m() { } } <-- look for K on X's declaration
3669                const symbol = getSymbolOfNode(host.parent.parent.left);
3670                if (symbol) {
3671                    return getDeclarationOfJSPrototypeContainer(symbol);
3672                }
3673            }
3674            const sig = getEffectiveJSDocHost(node);
3675            if (sig && isFunctionLike(sig)) {
3676                const symbol = getSymbolOfNode(sig);
3677                return symbol && symbol.valueDeclaration;
3678            }
3679        }
3680
3681        function getDeclarationOfJSPrototypeContainer(symbol: Symbol) {
3682            const decl = symbol.parent!.valueDeclaration;
3683            if (!decl) {
3684                return undefined;
3685            }
3686            const initializer = isAssignmentDeclaration(decl) ? getAssignedExpandoInitializer(decl) :
3687                hasOnlyExpressionInitializer(decl) ? getDeclaredExpandoInitializer(decl) :
3688                undefined;
3689            return initializer || decl;
3690        }
3691
3692        /**
3693         * Get the real symbol of a declaration with an expando initializer.
3694         *
3695         * Normally, declarations have an associated symbol, but when a declaration has an expando
3696         * initializer, the expando's symbol is the one that has all the members merged into it.
3697         */
3698        function getExpandoSymbol(symbol: Symbol): Symbol | undefined {
3699            const decl = symbol.valueDeclaration;
3700            if (!decl || !isInJSFile(decl) || symbol.flags & SymbolFlags.TypeAlias || getExpandoInitializer(decl, /*isPrototypeAssignment*/ false)) {
3701                return undefined;
3702            }
3703            const init = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
3704            if (init) {
3705                const initSymbol = getSymbolOfNode(init);
3706                if (initSymbol) {
3707                    return mergeJSSymbols(initSymbol, symbol);
3708                }
3709            }
3710        }
3711
3712        function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression, ignoreErrors?: boolean): Symbol | undefined {
3713            const isClassic = getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic;
3714            const errorMessage = isClassic?
3715                                    Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option
3716                                  : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations;
3717            return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? undefined : errorMessage);
3718        }
3719
3720        function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage | undefined, isForAugmentation = false): Symbol | undefined {
3721            return isStringLiteralLike(moduleReferenceExpression)
3722                ? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation)
3723                : undefined;
3724        }
3725
3726        function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined {
3727            if (startsWith(moduleReference, "@types/")) {
3728                const diag = Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1;
3729                const withoutAtTypePrefix = removePrefix(moduleReference, "@types/");
3730                error(errorNode, diag, withoutAtTypePrefix, moduleReference);
3731            }
3732
3733            const isSoFile = (moduleReference.lastIndexOf(".so") !== -1);
3734
3735            if (isSoFile && !(isInETSFile(location) && compilerOptions.needDoArkTsLinter && !compilerOptions.isCompatibleVersion)) {
3736                const diagnostic = createDiagnosticForNode(errorNode, Diagnostics.Currently_module_for_0_is_not_verified_If_you_re_importing_napi_its_verification_will_be_enabled_in_later_SDK_version_Please_make_sure_the_corresponding_d_ts_file_is_provided_and_the_napis_are_correctly_declared, moduleReference);
3737                diagnostics.add(diagnostic);
3738                return undefined;
3739            }
3740
3741            const ambientModule = tryFindAmbientModule(moduleReference, /*withAugmentations*/ true);
3742            if (ambientModule) {
3743                return ambientModule;
3744            }
3745            const currentSourceFile = getSourceFileOfNode(location);
3746            const contextSpecifier = isStringLiteralLike(location)
3747                ? location
3748                :   findAncestor(location, isImportCall)?.arguments[0] ||
3749                    findAncestor(location, isImportDeclaration)?.moduleSpecifier ||
3750                    findAncestor(location, isExternalModuleImportEqualsDeclaration)?.moduleReference.expression ||
3751                    findAncestor(location, isExportDeclaration)?.moduleSpecifier ||
3752                    (isModuleDeclaration(location) ? location : location.parent && isModuleDeclaration(location.parent) && location.parent.name === location ? location.parent : undefined)?.name ||
3753                    (isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal;
3754            const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat;
3755            const resolvedModule = getResolvedModule(currentSourceFile, moduleReference, mode);
3756            // the relative path of sdk
3757            const sdkPath = compilerOptions.etsLoaderPath ? resolvePath(compilerOptions.etsLoaderPath, '../..') : undefined;
3758            if (compilerOptions.needDoArkTsLinter &&
3759                currentSourceFile && currentSourceFile.scriptKind === ScriptKind.TS &&
3760                resolvedModule && (resolvedModule.extension === ".ets" || resolvedModule.extension === ".d.ets")) {
3761                const diagnosticType = compilerOptions.isCompatibleVersion ?
3762                    Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_about_to_be_forbidden :
3763                    Diagnostics.Importing_ArkTS_files_in_JS_and_TS_files_is_forbidden;
3764                if (contextSpecifier &&
3765                    !isImportDeclaration(contextSpecifier.parent) &&
3766                    !isExportDeclaration(contextSpecifier.parent) ||
3767                    !allowImportSendable(sdkPath, currentSourceFile)) {
3768                    // If the node is ImportCall throw error
3769                    // If currentSourceFile is not allowImportSendable (.d.ts inside sdk or .ts file when tsImportSendable is true)
3770                    error(errorNode, diagnosticType, moduleReference);
3771                }
3772            }
3773
3774            const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule);
3775            const sourceFile = resolvedModule
3776                && (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set)
3777                // For ets/ts files, in non linter check, skip resolving symbols from js files
3778                && (!compilerOptions.needDoArkTsLinter || isTypeCheckerForLinter || !hasJSFileExtension(resolvedModule.resolvedFileName))
3779                && host.getSourceFile(resolvedModule.resolvedFileName);
3780            if (sourceFile) {
3781                // If there's a resolutionDiagnostic we need to report it even if a sourceFile is found.
3782                if (resolutionDiagnostic) {
3783                    error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName);
3784                }
3785                if (sourceFile.symbol) {
3786                    if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) {
3787                        errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference);
3788                    }
3789                    if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) {
3790                        const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration);
3791                        const overrideClauseHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined;
3792                        const overrideClause = overrideClauseHost && isImportTypeNode(overrideClauseHost) ? overrideClauseHost.assertions?.assertClause : overrideClauseHost?.assertClause;
3793                        // An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of
3794                        // normal mode restrictions
3795                        if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !getResolutionModeOverrideForClause(overrideClause)) {
3796                            if (findAncestor(location, isImportEqualsDeclaration)) {
3797                                // ImportEquals in a ESM file resolving to another ESM file
3798                                error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, moduleReference);
3799                            }
3800                            else {
3801                                // CJS file resolving to an ESM file
3802                                let diagnosticDetails;
3803                                const ext = tryGetExtensionFromPath(currentSourceFile.fileName);
3804                                if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) {
3805                                    const scope = currentSourceFile.packageJsonScope;
3806                                    const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined;
3807                                    if (scope && !scope.contents.packageJsonContent.type) {
3808                                        if (targetExt) {
3809                                            diagnosticDetails = chainDiagnosticMessages(
3810                                                /*details*/ undefined,
3811                                                Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1,
3812                                                targetExt,
3813                                                combinePaths(scope.packageDirectory, getPackageJsonByPMType(compilerOptions.packageManagerType)));
3814                                        }
3815                                        else {
3816                                            diagnosticDetails = chainDiagnosticMessages(
3817                                                /*details*/ undefined,
3818                                                Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0,
3819                                                combinePaths(scope.packageDirectory, getPackageJsonByPMType(compilerOptions.packageManagerType)));
3820                                        }
3821                                    }
3822                                    else {
3823                                        if (targetExt) {
3824                                            diagnosticDetails = chainDiagnosticMessages(
3825                                                /*details*/ undefined,
3826                                                Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module,
3827                                                targetExt);
3828                                        }
3829                                        else {
3830                                            diagnosticDetails = chainDiagnosticMessages(
3831                                                /*details*/ undefined,
3832                                                Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module);
3833                                        }
3834                                    }
3835                                }
3836                                diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, chainDiagnosticMessages(
3837                                    diagnosticDetails,
3838                                    Diagnostics.The_current_file_is_a_CommonJS_module_whose_imports_will_produce_require_calls_however_the_referenced_file_is_an_ECMAScript_module_and_cannot_be_imported_with_require_Consider_writing_a_dynamic_import_0_call_instead,
3839                                    moduleReference)));
3840                            }
3841                        }
3842                    }
3843                    // merged symbol is module declaration symbol combined with all augmentations
3844                    return getMergedSymbol(sourceFile.symbol);
3845                }
3846                if (moduleNotFoundError) {
3847                    // report errors only if it was requested
3848                    error(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
3849                }
3850                return undefined;
3851            }
3852
3853            if (patternAmbientModules) {
3854                const pattern = findBestPatternMatch(patternAmbientModules, _ => _.pattern, moduleReference);
3855                if (pattern) {
3856                    // If the module reference matched a pattern ambient module ('*.foo') but there's also a
3857                    // module augmentation by the specific name requested ('a.foo'), we store the merged symbol
3858                    // by the augmentation name ('a.foo'), because asking for *.foo should not give you exports
3859                    // from a.foo.
3860                    const augmentation = patternAmbientModuleAugmentations && patternAmbientModuleAugmentations.get(moduleReference);
3861                    if (augmentation) {
3862                        return getMergedSymbol(augmentation);
3863                    }
3864                    return getMergedSymbol(pattern.symbol);
3865                }
3866            }
3867
3868            // May be an untyped module. If so, ignore resolutionDiagnostic.
3869            if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) {
3870                if (isForAugmentation) {
3871                    const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented;
3872                    error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName);
3873                }
3874                else {
3875                    errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule!, moduleReference);
3876                }
3877                // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first.
3878                return undefined;
3879            }
3880
3881            if (moduleNotFoundError) {
3882                // See if this was possibly a projectReference redirect
3883                if (resolvedModule) {
3884                    const redirect = host.getProjectReferenceRedirect(resolvedModule.resolvedFileName);
3885                    if (redirect) {
3886                        error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, resolvedModule.resolvedFileName);
3887                        return undefined;
3888                    }
3889                }
3890
3891                if (resolutionDiagnostic) {
3892                    error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName);
3893                }
3894                else {
3895                    const tsExtension = tryExtractTSExtension(moduleReference);
3896                    const isExtensionlessRelativePathImport = pathIsRelative(moduleReference) && !hasExtension(moduleReference);
3897                    const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions);
3898                    const resolutionIsNode16OrNext = moduleResolutionKind === ModuleResolutionKind.Node16 ||
3899                        moduleResolutionKind === ModuleResolutionKind.NodeNext;
3900                    if (tsExtension) {
3901                        const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead;
3902                        const importSourceWithoutExtension = removeExtension(moduleReference, tsExtension);
3903                        let replacedImportSource = importSourceWithoutExtension;
3904                        /**
3905                         * Direct users to import source with .js extension if outputting an ES module.
3906                         * @see https://github.com/microsoft/TypeScript/issues/42151
3907                         */
3908                        if (moduleKind >= ModuleKind.ES2015) {
3909                            replacedImportSource += tsExtension === Extension.Mts ? ".mjs" : tsExtension === Extension.Cts ? ".cjs" : ".js";
3910                        }
3911                        error(errorNode, diag, tsExtension, replacedImportSource);
3912                    }
3913                    else if (!compilerOptions.resolveJsonModule &&
3914                        fileExtensionIs(moduleReference, Extension.Json) &&
3915                        getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic &&
3916                        hasJsonModuleEmitEnabled(compilerOptions)) {
3917                        error(errorNode, Diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference);
3918                    }
3919                    else if (mode === ModuleKind.ESNext && resolutionIsNode16OrNext && isExtensionlessRelativePathImport) {
3920                        const absoluteRef = getNormalizedAbsolutePath(moduleReference, getDirectoryPath(currentSourceFile.path));
3921                        const suggestedExt = suggestedExtensions.find(([actualExt, _importExt]) => host.fileExists(absoluteRef + actualExt))?.[1];
3922                        if (suggestedExt) {
3923                            error(errorNode,
3924                                Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0,
3925                                moduleReference + suggestedExt);
3926                        }
3927                        else {
3928                            error(errorNode, Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path);
3929                        }
3930                    }
3931                    else {
3932                        if (isSoFile) {
3933                            const diagnostic = createDiagnosticForNode(errorNode, Diagnostics.Currently_module_for_0_is_not_verified_If_you_re_importing_napi_its_verification_will_be_enabled_in_later_SDK_version_Please_make_sure_the_corresponding_d_ts_file_is_provided_and_the_napis_are_correctly_declared, moduleReference);
3934                            diagnostics.add(diagnostic);
3935                        } else {
3936                            error(errorNode, moduleNotFoundError, moduleReference);
3937                        }
3938                    }
3939                }
3940            }
3941            return undefined;
3942        }
3943
3944        function allowImportSendable(sdkPath: string | undefined, currentSourceFile: SourceFile): boolean {
3945            const isInSdkPath = !!(sdkPath && ts.normalizePath(currentSourceFile.fileName).startsWith(sdkPath));
3946            // Check the file is a TypeScript file outside of the method
3947            // currentSourceFile must be a ts file
3948            return (
3949                (isInSdkPath && currentSourceFile.isDeclarationFile) ||
3950                (!!compilerOptions.tsImportSendableEnable && !currentSourceFile.isDeclarationFile)
3951            );
3952        }
3953
3954        function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void {
3955            const errorInfo = !isExternalModuleNameRelative(moduleReference) && packageId
3956                ? typesPackageExists(packageId.name)
3957                    ? chainDiagnosticMessages(
3958                        /*details*/ undefined,
3959                        Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1,
3960                        packageId.name, mangleScopedPackageName(packageId.name))
3961                    : packageBundlesTypes(packageId.name)
3962                        ? chainDiagnosticMessages(
3963                            /*details*/ undefined,
3964                            Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1,
3965                            packageId.name,
3966                            moduleReference)
3967                        : chainDiagnosticMessages(
3968                            /*details*/ undefined,
3969                            Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0,
3970                            moduleReference,
3971                            mangleScopedPackageName(packageId.name))
3972                : undefined;
3973            errorOrSuggestion(isError, errorNode, chainDiagnosticMessages(
3974                errorInfo,
3975                Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
3976                moduleReference,
3977                resolvedFileName));
3978        }
3979        function typesPackageExists(packageName: string): boolean {
3980            return getPackagesMap().has(getTypesPackageName(packageName));
3981        }
3982        function packageBundlesTypes(packageName: string): boolean {
3983            return !!getPackagesMap().get(packageName);
3984        }
3985
3986        function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol;
3987        function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined;
3988        function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol | undefined {
3989            if (moduleSymbol?.exports) {
3990                const exportEquals = resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias);
3991                const exported = getCommonJsExportEquals(getMergedSymbol(exportEquals), getMergedSymbol(moduleSymbol));
3992                return getMergedSymbol(exported) || moduleSymbol;
3993            }
3994            return undefined;
3995        }
3996
3997        function getCommonJsExportEquals(exported: Symbol | undefined, moduleSymbol: Symbol): Symbol | undefined {
3998            if (!exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1 || exported.flags & SymbolFlags.Alias) {
3999                return exported;
4000            }
4001            const links = getSymbolLinks(exported);
4002            if (links.cjsExportMerged) {
4003                return links.cjsExportMerged;
4004            }
4005            const merged = exported.flags & SymbolFlags.Transient ? exported : cloneSymbol(exported);
4006            merged.flags = merged.flags | SymbolFlags.ValueModule;
4007            if (merged.exports === undefined) {
4008                merged.exports = createSymbolTable();
4009            }
4010            moduleSymbol.exports!.forEach((s, name) => {
4011                if (name === InternalSymbolName.ExportEquals) return;
4012                merged.exports!.set(name, merged.exports!.has(name) ? mergeSymbol(merged.exports!.get(name)!, s) : s);
4013            });
4014            getSymbolLinks(merged).cjsExportMerged = merged;
4015            return links.cjsExportMerged = merged;
4016        }
4017
4018        // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export ='
4019        // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may
4020        // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable).
4021        function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, referencingLocation: Node, dontResolveAlias: boolean, suppressInteropError: boolean): Symbol | undefined {
4022            const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias);
4023
4024            if (!dontResolveAlias && symbol) {
4025                if (!suppressInteropError && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) && !getDeclarationOfKind(symbol, SyntaxKind.SourceFile)) {
4026                    const compilerOptionName = moduleKind >= ModuleKind.ES2015
4027                        ? "allowSyntheticDefaultImports"
4028                        : "esModuleInterop";
4029
4030                    error(referencingLocation, Diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName);
4031
4032                    return symbol;
4033                }
4034
4035                const referenceParent = referencingLocation.parent;
4036                if (
4037                    (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) ||
4038                    isImportCall(referenceParent)
4039                ) {
4040                    const reference = isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier;
4041                    const type = getTypeOfSymbol(symbol);
4042                    const defaultOnlyType = getTypeWithSyntheticDefaultOnly(type, symbol, moduleSymbol!, reference);
4043                    if (defaultOnlyType) {
4044                        return cloneTypeAsModuleType(symbol, defaultOnlyType, referenceParent);
4045                    }
4046
4047                    const targetFile = moduleSymbol?.declarations?.find(isSourceFile);
4048                    const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getUsageModeForExpression(reference), targetFile.impliedNodeFormat);
4049                    if (getESModuleInterop(compilerOptions) || isEsmCjsRef) {
4050                        let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call);
4051                        if (!sigs || !sigs.length) {
4052                            sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct);
4053                        }
4054                        if (
4055                            (sigs && sigs.length) ||
4056                            getPropertyOfType(type, InternalSymbolName.Default, /*skipObjectFunctionPropertyAugment*/ true) ||
4057                            isEsmCjsRef
4058                        ) {
4059                            const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!, reference);
4060                            return cloneTypeAsModuleType(symbol, moduleType, referenceParent);
4061                        }
4062                    }
4063                }
4064            }
4065            return symbol;
4066        }
4067
4068        /**
4069         * Create a new symbol which has the module's type less the call and construct signatures
4070         */
4071        function cloneTypeAsModuleType(symbol: Symbol, moduleType: Type, referenceParent: ImportDeclaration | ImportCall) {
4072            const result = createSymbol(symbol.flags, symbol.escapedName);
4073            result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
4074            result.parent = symbol.parent;
4075            result.target = symbol;
4076            result.originatingImport = referenceParent;
4077            if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
4078            if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
4079            if (symbol.members) result.members = new Map(symbol.members);
4080            if (symbol.exports) result.exports = new Map(symbol.exports);
4081            const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above
4082            result.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.indexInfos);
4083            return result;
4084        }
4085
4086        function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean {
4087            return moduleSymbol.exports!.get(InternalSymbolName.ExportEquals) !== undefined;
4088        }
4089
4090        function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] {
4091            return symbolsToArray(getExportsOfModule(moduleSymbol));
4092        }
4093
4094        function getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[] {
4095            const exports = getExportsOfModuleAsArray(moduleSymbol);
4096            const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
4097            if (exportEquals !== moduleSymbol) {
4098                const type = getTypeOfSymbol(exportEquals);
4099                if (shouldTreatPropertiesOfExternalModuleAsExports(type)) {
4100                    addRange(exports, getPropertiesOfType(type));
4101                }
4102            }
4103            return exports;
4104        }
4105
4106        function forEachExportAndPropertyOfModule(moduleSymbol: Symbol, cb: (symbol: Symbol, key: __String) => void): void {
4107            const exports = getExportsOfModule(moduleSymbol);
4108            exports.forEach((symbol, key) => {
4109                if (!isReservedMemberName(key)) {
4110                    cb(symbol, key);
4111                }
4112            });
4113            const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
4114            if (exportEquals !== moduleSymbol) {
4115                const type = getTypeOfSymbol(exportEquals);
4116                if (shouldTreatPropertiesOfExternalModuleAsExports(type)) {
4117                    forEachPropertyOfType(type, (symbol, escapedName) => {
4118                        cb(symbol, escapedName);
4119                    });
4120                }
4121            }
4122        }
4123
4124        function tryGetMemberInModuleExports(memberName: __String, moduleSymbol: Symbol): Symbol | undefined {
4125            const symbolTable = getExportsOfModule(moduleSymbol);
4126            if (symbolTable) {
4127                return symbolTable.get(memberName);
4128            }
4129        }
4130
4131        function tryGetMemberInModuleExportsAndProperties(memberName: __String, moduleSymbol: Symbol): Symbol | undefined {
4132            const symbol = tryGetMemberInModuleExports(memberName, moduleSymbol);
4133            if (symbol) {
4134                return symbol;
4135            }
4136
4137            const exportEquals = resolveExternalModuleSymbol(moduleSymbol);
4138            if (exportEquals === moduleSymbol) {
4139                return undefined;
4140            }
4141
4142            const type = getTypeOfSymbol(exportEquals);
4143            return shouldTreatPropertiesOfExternalModuleAsExports(type) ? getPropertyOfType(type, memberName) : undefined;
4144        }
4145
4146        function shouldTreatPropertiesOfExternalModuleAsExports(resolvedExternalModuleType: Type) {
4147            return !(resolvedExternalModuleType.flags & TypeFlags.Primitive ||
4148                    getObjectFlags(resolvedExternalModuleType) & ObjectFlags.Class ||
4149                    // `isArrayOrTupleLikeType` is too expensive to use in this auto-imports hot path
4150                    isArrayType(resolvedExternalModuleType) ||
4151                    isTupleType(resolvedExternalModuleType));
4152        }
4153
4154        function getExportsOfSymbol(symbol: Symbol): SymbolTable {
4155            return symbol.flags & SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) :
4156                symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) :
4157                symbol.exports || emptySymbols;
4158        }
4159
4160        function getExportsOfModule(moduleSymbol: Symbol): SymbolTable {
4161            const links = getSymbolLinks(moduleSymbol);
4162            return links.resolvedExports || (links.resolvedExports = getExportsOfModuleWorker(moduleSymbol));
4163        }
4164
4165        interface ExportCollisionTracker {
4166            specifierText: string;
4167            exportsWithDuplicate: ExportDeclaration[];
4168        }
4169
4170        type ExportCollisionTrackerTable = UnderscoreEscapedMap<ExportCollisionTracker>;
4171
4172        /**
4173         * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument
4174         * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables
4175         */
4176        function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) {
4177            if (!source) return;
4178            source.forEach((sourceSymbol, id) => {
4179                if (id === InternalSymbolName.Default) return;
4180
4181                const targetSymbol = target.get(id);
4182                if (!targetSymbol) {
4183                    target.set(id, sourceSymbol);
4184                    if (lookupTable && exportNode) {
4185                        lookupTable.set(id, {
4186                            specifierText: getTextOfNode(exportNode.moduleSpecifier!)
4187                        } as ExportCollisionTracker);
4188                    }
4189                }
4190                else if (lookupTable && exportNode && targetSymbol && resolveSymbol(targetSymbol) !== resolveSymbol(sourceSymbol)) {
4191                    const collisionTracker = lookupTable.get(id)!;
4192                    if (!collisionTracker.exportsWithDuplicate) {
4193                        collisionTracker.exportsWithDuplicate = [exportNode];
4194                    }
4195                    else {
4196                        collisionTracker.exportsWithDuplicate.push(exportNode);
4197                    }
4198                }
4199            });
4200        }
4201
4202        function getExportsOfModuleWorker(moduleSymbol: Symbol): SymbolTable {
4203            const visitedSymbols: Symbol[] = [];
4204
4205            // A module defined by an 'export=' consists of one export that needs to be resolved
4206            moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
4207
4208            return visit(moduleSymbol) || emptySymbols;
4209
4210            // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example,
4211            // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error.
4212            function visit(symbol: Symbol | undefined): SymbolTable | undefined {
4213                if (!(symbol && symbol.exports && pushIfUnique(visitedSymbols, symbol))) {
4214                    return;
4215                }
4216                const symbols = new Map(symbol.exports);
4217                // All export * declarations are collected in an __export symbol by the binder
4218                const exportStars = symbol.exports.get(InternalSymbolName.ExportStar);
4219                if (exportStars) {
4220                    const nestedSymbols = createSymbolTable();
4221                    const lookupTable: ExportCollisionTrackerTable = new Map();
4222                    if (exportStars.declarations) {
4223                        for (const node of exportStars.declarations) {
4224                            const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!);
4225                            const exportedSymbols = visit(resolvedModule);
4226                            extendExportSymbols(
4227                                nestedSymbols,
4228                                exportedSymbols,
4229                                lookupTable,
4230                                node as ExportDeclaration
4231                            );
4232                        }
4233                    }
4234                    lookupTable.forEach(({ exportsWithDuplicate }, id) => {
4235                        // It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself
4236                        if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || symbols.has(id)) {
4237                            return;
4238                        }
4239                        for (const node of exportsWithDuplicate) {
4240                            diagnostics.add(createDiagnosticForNode(
4241                                node,
4242                                Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity,
4243                                lookupTable.get(id)!.specifierText,
4244                                unescapeLeadingUnderscores(id)
4245                            ));
4246                        }
4247                    });
4248                    extendExportSymbols(symbols, nestedSymbols);
4249                }
4250                return symbols;
4251            }
4252        }
4253
4254        function getMergedSymbol(symbol: Symbol): Symbol;
4255        function getMergedSymbol(symbol: Symbol | undefined): Symbol | undefined;
4256        function getMergedSymbol(symbol: Symbol | undefined): Symbol | undefined {
4257            let merged: Symbol;
4258            return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol;
4259        }
4260
4261        function getSymbolOfNode(node: Declaration): Symbol;
4262        function getSymbolOfNode(node: Node): Symbol | undefined;
4263        function getSymbolOfNode(node: Node): Symbol | undefined {
4264            return getMergedSymbol(node.symbol && getLateBoundSymbol(node.symbol));
4265        }
4266
4267        function getParentOfSymbol(symbol: Symbol): Symbol | undefined {
4268            return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent));
4269        }
4270
4271        function getAlternativeContainingModules(symbol: Symbol, enclosingDeclaration: Node): Symbol[] {
4272            const containingFile = getSourceFileOfNode(enclosingDeclaration);
4273            const id = getNodeId(containingFile);
4274            const links = getSymbolLinks(symbol);
4275            let results: Symbol[] | undefined;
4276            if (links.extendedContainersByFile && (results = links.extendedContainersByFile.get(id))) {
4277                return results;
4278            }
4279            if (containingFile && containingFile.imports) {
4280                // Try to make an import using an import already in the enclosing file, if possible
4281                for (const importRef of containingFile.imports) {
4282                    if (nodeIsSynthesized(importRef)) continue; // Synthetic names can't be resolved by `resolveExternalModuleName` - they'll cause a debug assert if they error
4283                    const resolvedModule = resolveExternalModuleName(enclosingDeclaration, importRef, /*ignoreErrors*/ true);
4284                    if (!resolvedModule) continue;
4285                    const ref = getAliasForSymbolInContainer(resolvedModule, symbol);
4286                    if (!ref) continue;
4287                    results = append(results, resolvedModule);
4288                }
4289                if (length(results)) {
4290                    (links.extendedContainersByFile || (links.extendedContainersByFile = new Map())).set(id, results!);
4291                    return results!;
4292                }
4293            }
4294            if (links.extendedContainers) {
4295                return links.extendedContainers;
4296            }
4297            // No results from files already being imported by this file - expand search (expensive, but not location-specific, so cached)
4298            const otherFiles = host.getSourceFiles();
4299            for (const file of otherFiles) {
4300                if (!isExternalModule(file)) continue;
4301                const sym = getSymbolOfNode(file);
4302                const ref = getAliasForSymbolInContainer(sym, symbol);
4303                if (!ref) continue;
4304                results = append(results, sym);
4305            }
4306            return links.extendedContainers = results || emptyArray;
4307        }
4308
4309        /**
4310         * Attempts to find the symbol corresponding to the container a symbol is in - usually this
4311         * is just its' `.parent`, but for locals, this value is `undefined`
4312         */
4313        function getContainersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): Symbol[] | undefined {
4314            const container = getParentOfSymbol(symbol);
4315            // Type parameters end up in the `members` lists but are not externally visible
4316            if (container && !(symbol.flags & SymbolFlags.TypeParameter)) {
4317                const additionalContainers = mapDefined(container.declarations, fileSymbolIfFileSymbolExportEqualsContainer);
4318                const reexportContainers = enclosingDeclaration && getAlternativeContainingModules(symbol, enclosingDeclaration);
4319                const objectLiteralContainer = getVariableDeclarationOfObjectLiteral(container, meaning);
4320                if (
4321                    enclosingDeclaration &&
4322                    container.flags & getQualifiedLeftMeaning(meaning) &&
4323                    getAccessibleSymbolChain(container, enclosingDeclaration, SymbolFlags.Namespace, /*externalOnly*/ false)
4324                ) {
4325                    return append(concatenate(concatenate([container], additionalContainers), reexportContainers), objectLiteralContainer); // This order expresses a preference for the real container if it is in scope
4326                }
4327                // we potentially have a symbol which is a member of the instance side of something - look for a variable in scope with the container's type
4328                // which may be acting like a namespace (eg, `Symbol` acts like a namespace when looking up `Symbol.toStringTag`)
4329                const firstVariableMatch = !(container.flags & getQualifiedLeftMeaning(meaning))
4330                    && container.flags & SymbolFlags.Type
4331                    && getDeclaredTypeOfSymbol(container).flags & TypeFlags.Object
4332                    && meaning === SymbolFlags.Value
4333                ? forEachSymbolTableInScope(enclosingDeclaration, t => {
4334                    return forEachEntry(t, s => {
4335                        if (s.flags & getQualifiedLeftMeaning(meaning) && getTypeOfSymbol(s) === getDeclaredTypeOfSymbol(container)) {
4336                            return s;
4337                        }
4338                    });
4339                }) : undefined;
4340                let res = firstVariableMatch ? [firstVariableMatch, ...additionalContainers, container] : [...additionalContainers, container];
4341                res = append(res, objectLiteralContainer);
4342                res = addRange(res, reexportContainers);
4343                return res;
4344            }
4345            const candidates = mapDefined(symbol.declarations, d => {
4346                if (!isAmbientModule(d) && d.parent){
4347                    // direct children of a module
4348                    if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) {
4349                        return getSymbolOfNode(d.parent);
4350                    }
4351                    // export ='d member of an ambient module
4352                    if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfNode(d.parent.parent)) === symbol) {
4353                        return getSymbolOfNode(d.parent.parent);
4354                    }
4355                }
4356                if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) {
4357                    if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) {
4358                        return getSymbolOfNode(getSourceFileOfNode(d));
4359                    }
4360                    checkExpressionCached(d.parent.left.expression);
4361                    return getNodeLinks(d.parent.left.expression).resolvedSymbol;
4362                }
4363            });
4364            if (!length(candidates)) {
4365                return undefined;
4366            }
4367            return mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined);
4368
4369            function fileSymbolIfFileSymbolExportEqualsContainer(d: Declaration) {
4370                return container && getFileSymbolIfFileSymbolExportEqualsContainer(d, container);
4371            }
4372        }
4373
4374        function getVariableDeclarationOfObjectLiteral(symbol: Symbol, meaning: SymbolFlags) {
4375            // If we're trying to reference some object literal in, eg `var a = { x: 1 }`, the symbol for the literal, `__object`, is distinct
4376            // from the symbol of the declaration it is being assigned to. Since we can use the declaration to refer to the literal, however,
4377            // we'd like to make that connection here - potentially causing us to paint the declaration's visibility, and therefore the literal.
4378            const firstDecl: Node | false = !!length(symbol.declarations) && first(symbol.declarations!);
4379            if (meaning & SymbolFlags.Value && firstDecl && firstDecl.parent && isVariableDeclaration(firstDecl.parent)) {
4380                if (isObjectLiteralExpression(firstDecl) && firstDecl === firstDecl.parent.initializer || isTypeLiteralNode(firstDecl) && firstDecl === firstDecl.parent.type) {
4381                    return getSymbolOfNode(firstDecl.parent);
4382                }
4383            }
4384        }
4385
4386        function getFileSymbolIfFileSymbolExportEqualsContainer(d: Declaration, container: Symbol) {
4387            const fileSymbol = getExternalModuleContainer(d);
4388            const exported = fileSymbol && fileSymbol.exports && fileSymbol.exports.get(InternalSymbolName.ExportEquals);
4389            return exported && getSymbolIfSameReference(exported, container) ? fileSymbol : undefined;
4390        }
4391
4392        function getAliasForSymbolInContainer(container: Symbol, symbol: Symbol) {
4393            if (container === getParentOfSymbol(symbol)) {
4394                // fast path, `symbol` is either already the alias or isn't aliased
4395                return symbol;
4396            }
4397            // Check if container is a thing with an `export=` which points directly at `symbol`, and if so, return
4398            // the container itself as the alias for the symbol
4399            const exportEquals = container.exports && container.exports.get(InternalSymbolName.ExportEquals);
4400            if (exportEquals && getSymbolIfSameReference(exportEquals, symbol)) {
4401                return container;
4402            }
4403            const exports = getExportsOfSymbol(container);
4404            const quick = exports.get(symbol.escapedName);
4405            if (quick && getSymbolIfSameReference(quick, symbol)) {
4406                return quick;
4407            }
4408            return forEachEntry(exports, exported => {
4409                if (getSymbolIfSameReference(exported, symbol)) {
4410                    return exported;
4411                }
4412            });
4413        }
4414
4415        /**
4416         * Checks if two symbols, through aliasing and/or merging, refer to the same thing
4417         */
4418        function getSymbolIfSameReference(s1: Symbol, s2: Symbol) {
4419            if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) {
4420                return s1;
4421            }
4422        }
4423
4424        function getExportSymbolOfValueSymbolIfExported(symbol: Symbol): Symbol;
4425        function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined;
4426        function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined {
4427            return getMergedSymbol(symbol && (symbol.flags & SymbolFlags.ExportValue) !== 0 && symbol.exportSymbol || symbol);
4428        }
4429
4430        function symbolIsValue(symbol: Symbol, includeTypeOnlyMembers?: boolean): boolean {
4431            return !!(
4432                symbol.flags & SymbolFlags.Value ||
4433                symbol.flags & SymbolFlags.Alias && getAllSymbolFlags(symbol) & SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol)));
4434        }
4435
4436        function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration | undefined {
4437            const members = node.members;
4438            for (const member of members) {
4439                if (member.kind === SyntaxKind.Constructor && nodeIsPresent((member as ConstructorDeclaration).body)) {
4440                    return member as ConstructorDeclaration;
4441                }
4442            }
4443        }
4444
4445        function createType(flags: TypeFlags): Type {
4446            const result = new Type(checker, flags);
4447            typeCount++;
4448            result.id = typeCount;
4449            tracing?.recordType(result);
4450            return result;
4451        }
4452
4453        function createOriginType(flags: TypeFlags): Type {
4454            return new Type(checker, flags);
4455        }
4456
4457        function createIntrinsicType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags = 0): IntrinsicType {
4458            const type = createType(kind) as IntrinsicType;
4459            type.intrinsicName = intrinsicName;
4460            type.objectFlags = objectFlags;
4461            return type;
4462        }
4463
4464        function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType {
4465            const type = createType(TypeFlags.Object) as ObjectType;
4466            type.objectFlags = objectFlags;
4467            type.symbol = symbol!;
4468            type.members = undefined;
4469            type.properties = undefined;
4470            type.callSignatures = undefined;
4471            type.constructSignatures = undefined;
4472            type.indexInfos = undefined;
4473            return type;
4474        }
4475
4476        function createTypeofType() {
4477            return getUnionType(arrayFrom(typeofNEFacts.keys(), getStringLiteralType));
4478        }
4479
4480        function createTypeParameter(symbol?: Symbol) {
4481            const type = createType(TypeFlags.TypeParameter) as TypeParameter;
4482            if (symbol) type.symbol = symbol;
4483            return type;
4484        }
4485
4486        // A reserved member name starts with two underscores, but the third character cannot be an underscore,
4487        // @, or #. A third underscore indicates an escaped form of an identifier that started
4488        // with at least two underscores. The @ character indicates that the name is denoted by a well known ES
4489        // Symbol instance and the # character indicates that the name is a PrivateIdentifier.
4490        function isReservedMemberName(name: __String) {
4491            return (name as string).charCodeAt(0) === CharacterCodes._ &&
4492                (name as string).charCodeAt(1) === CharacterCodes._ &&
4493                (name as string).charCodeAt(2) !== CharacterCodes._ &&
4494                (name as string).charCodeAt(2) !== CharacterCodes.at &&
4495                (name as string).charCodeAt(2) !== CharacterCodes.hash;
4496        }
4497
4498        function getNamedMembers(members: SymbolTable): Symbol[] {
4499            let result: Symbol[] | undefined;
4500            members.forEach((symbol, id) => {
4501                if (isNamedMember(symbol, id)) {
4502                    (result || (result = [])).push(symbol);
4503                }
4504            });
4505            return result || emptyArray;
4506        }
4507
4508        function isNamedMember(member: Symbol, escapedName: __String) {
4509            return !isReservedMemberName(escapedName) && symbolIsValue(member);
4510        }
4511
4512        function getNamedOrIndexSignatureMembers(members: SymbolTable): Symbol[] {
4513            const result = getNamedMembers(members);
4514            const index = getIndexSymbolFromSymbolTable(members);
4515            return index ? concatenate(result, [index]) : result;
4516        }
4517
4518        function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], indexInfos: readonly IndexInfo[]): ResolvedType {
4519            const resolved = type as ResolvedType;
4520            resolved.members = members;
4521            resolved.properties = emptyArray;
4522            resolved.callSignatures = callSignatures;
4523            resolved.constructSignatures = constructSignatures;
4524            resolved.indexInfos = indexInfos;
4525            // This can loop back to getPropertyOfType() which would crash if `callSignatures` & `constructSignatures` are not initialized.
4526            if (members !== emptySymbols) resolved.properties = getNamedMembers(members);
4527            return resolved;
4528        }
4529
4530        function createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], indexInfos: readonly IndexInfo[]): ResolvedType {
4531            return setStructuredTypeMembers(createObjectType(ObjectFlags.Anonymous, symbol),
4532                members, callSignatures, constructSignatures, indexInfos);
4533        }
4534
4535        function getResolvedTypeWithoutAbstractConstructSignatures(type: ResolvedType) {
4536            if (type.constructSignatures.length === 0) return type;
4537            if (type.objectTypeWithoutAbstractConstructSignatures) return type.objectTypeWithoutAbstractConstructSignatures;
4538            const constructSignatures = filter(type.constructSignatures, signature => !(signature.flags & SignatureFlags.Abstract));
4539            if (type.constructSignatures === constructSignatures) return type;
4540            const typeCopy = createAnonymousType(
4541                type.symbol,
4542                type.members,
4543                type.callSignatures,
4544                some(constructSignatures) ? constructSignatures : emptyArray,
4545                type.indexInfos);
4546            type.objectTypeWithoutAbstractConstructSignatures = typeCopy;
4547            typeCopy.objectTypeWithoutAbstractConstructSignatures = typeCopy;
4548            return typeCopy;
4549        }
4550
4551        function forEachSymbolTableInScope<T>(enclosingDeclaration: Node | undefined, callback: (symbolTable: SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean, scopeNode?: Node) => T): T {
4552            let result: T;
4553            for (let location = enclosingDeclaration; location; location = location.parent) {
4554                // Locals of a source file are not in scope (because they get merged into the global symbol table)
4555                if (location.locals && !isGlobalSourceFile(location)) {
4556                    if (result = callback(location.locals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true, location)) {
4557                        return result;
4558                    }
4559                }
4560                switch (location.kind) {
4561                    case SyntaxKind.SourceFile:
4562                        if (!isExternalOrCommonJsModule(location as SourceFile)) {
4563                            break;
4564                        }
4565                        // falls through
4566                    case SyntaxKind.ModuleDeclaration:
4567                        const sym = getSymbolOfNode(location as ModuleDeclaration);
4568                        // `sym` may not have exports if this module declaration is backed by the symbol for a `const` that's being rewritten
4569                        // into a namespace - in such cases, it's best to just let the namespace appear empty (the const members couldn't have referred
4570                        // to one another anyway)
4571                        if (result = callback(sym?.exports || emptySymbols, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true, location)) {
4572                            return result;
4573                        }
4574                        break;
4575                    case SyntaxKind.ClassDeclaration:
4576                    case SyntaxKind.ClassExpression:
4577                    case SyntaxKind.InterfaceDeclaration:
4578                        // Type parameters are bound into `members` lists so they can merge across declarations
4579                        // This is troublesome, since in all other respects, they behave like locals :cries:
4580                        // TODO: the below is shared with similar code in `resolveName` - in fact, rephrasing all this symbol
4581                        // lookup logic in terms of `resolveName` would be nice
4582                        // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals
4583                        // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would
4584                        // trigger resolving late-bound names, which we may already be in the process of doing while we're here!
4585                        let table: UnderscoreEscapedMap<Symbol> | undefined;
4586                        // TODO: Should this filtered table be cached in some way?
4587                        (getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols).forEach((memberSymbol, key) => {
4588                            if (memberSymbol.flags & (SymbolFlags.Type & ~SymbolFlags.Assignment)) {
4589                                (table || (table = createSymbolTable())).set(key, memberSymbol);
4590                            }
4591                        });
4592                        if (table && (result = callback(table, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ false, location))) {
4593                            return result;
4594                        }
4595                        break;
4596                }
4597            }
4598
4599            return callback(globals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true);
4600        }
4601
4602        function getQualifiedLeftMeaning(rightMeaning: SymbolFlags) {
4603            // If we are looking in value space, the parent meaning is value, other wise it is namespace
4604            return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace;
4605        }
4606
4607        function getAccessibleSymbolChain(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: ESMap<SymbolId, SymbolTable[]> = new Map()): Symbol[] | undefined {
4608            if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) {
4609                return undefined;
4610            }
4611            const links = getSymbolLinks(symbol);
4612            const cache = (links.accessibleChainCache ||= new Map());
4613            // Go from enclosingDeclaration to the first scope we check, so the cache is keyed off the scope and thus shared more
4614            const firstRelevantLocation = forEachSymbolTableInScope(enclosingDeclaration, (_, __, ___, node) => node);
4615            const key = `${useOnlyExternalAliasing ? 0 : 1}|${firstRelevantLocation && getNodeId(firstRelevantLocation)}|${meaning}`;
4616            if (cache.has(key)) {
4617                return cache.get(key);
4618            }
4619
4620            const id = getSymbolId(symbol);
4621            let visitedSymbolTables = visitedSymbolTablesMap.get(id);
4622            if (!visitedSymbolTables) {
4623                visitedSymbolTablesMap.set(id, visitedSymbolTables = []);
4624            }
4625            const result = forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
4626            cache.set(key, result);
4627            return result;
4628
4629            /**
4630             * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already)
4631             */
4632            function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean): Symbol[] | undefined {
4633                if (!pushIfUnique(visitedSymbolTables!, symbols)) {
4634                    return undefined;
4635                }
4636
4637                const result = trySymbolTable(symbols, ignoreQualification, isLocalNameLookup);
4638                visitedSymbolTables!.pop();
4639                return result;
4640            }
4641
4642            function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) {
4643                // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
4644                return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) ||
4645                    // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too
4646                    !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap);
4647            }
4648
4649            function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) {
4650                return (symbol === (resolvedAliasSymbol || symbolFromSymbolTable) || getMergedSymbol(symbol) === getMergedSymbol(resolvedAliasSymbol || symbolFromSymbolTable)) &&
4651                    // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table)
4652                    // and if symbolFromSymbolTable or alias resolution matches the symbol,
4653                    // check the symbol can be qualified, it is only then this symbol is accessible
4654                    !some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) &&
4655                    (ignoreQualification || canQualifySymbol(getMergedSymbol(symbolFromSymbolTable), meaning));
4656            }
4657
4658            function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined, isLocalNameLookup: boolean | undefined): Symbol[] | undefined {
4659                // If symbol is directly available by its name in the symbol table
4660                if (isAccessible(symbols.get(symbol!.escapedName)!, /*resolvedAliasSymbol*/ undefined, ignoreQualification)) {
4661                    return [symbol!];
4662                }
4663
4664                // Check if symbol is any of the aliases in scope
4665                const result = forEachEntry(symbols, symbolFromSymbolTable => {
4666                    if (symbolFromSymbolTable.flags & SymbolFlags.Alias
4667                        && symbolFromSymbolTable.escapedName !== InternalSymbolName.ExportEquals
4668                        && symbolFromSymbolTable.escapedName !== InternalSymbolName.Default
4669                        && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && isExternalModule(getSourceFileOfNode(enclosingDeclaration)))
4670                        // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name
4671                        && (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration))
4672                        // If we're looking up a local name to reference directly, omit namespace reexports, otherwise when we're trawling through an export list to make a dotted name, we can keep it
4673                        && (isLocalNameLookup ? !some(symbolFromSymbolTable.declarations, isNamespaceReexportDeclaration) : true)
4674                        // While exports are generally considered to be in scope, export-specifier declared symbols are _not_
4675                        // See similar comment in `resolveName` for details
4676                        && (ignoreQualification || !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier))
4677                    ) {
4678
4679                        const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
4680                        const candidate = getCandidateListForSymbol(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification);
4681                        if (candidate) {
4682                            return candidate;
4683                        }
4684                    }
4685                    if (symbolFromSymbolTable.escapedName === symbol!.escapedName && symbolFromSymbolTable.exportSymbol) {
4686                        if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), /*aliasSymbol*/ undefined, ignoreQualification)) {
4687                            return [symbol!];
4688                        }
4689                    }
4690                });
4691
4692                // If there's no result and we're looking at the global symbol table, treat `globalThis` like an alias and try to lookup thru that
4693                return result || (symbols === globals ? getCandidateListForSymbol(globalThisSymbol, globalThisSymbol, ignoreQualification) : undefined);
4694            }
4695
4696            function getCandidateListForSymbol(symbolFromSymbolTable: Symbol, resolvedImportedSymbol: Symbol, ignoreQualification: boolean | undefined) {
4697                if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) {
4698                    return [symbolFromSymbolTable];
4699                }
4700
4701                // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
4702                // but only if the symbolFromSymbolTable can be qualified
4703                const candidateTable = getExportsOfSymbol(resolvedImportedSymbol);
4704                const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true);
4705                if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
4706                    return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
4707                }
4708            }
4709        }
4710
4711        function needsQualification(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags) {
4712            let qualify = false;
4713            forEachSymbolTableInScope(enclosingDeclaration, symbolTable => {
4714                // If symbol of this name is not available in the symbol table we are ok
4715                let symbolFromSymbolTable = getMergedSymbol(symbolTable.get(symbol.escapedName));
4716                if (!symbolFromSymbolTable) {
4717                    // Continue to the next symbol table
4718                    return false;
4719                }
4720                // If the symbol with this name is present it should refer to the symbol
4721                if (symbolFromSymbolTable === symbol) {
4722                    // No need to qualify
4723                    return true;
4724                }
4725
4726                // Qualify if the symbol from symbol table has same meaning as expected
4727                const shouldResolveAlias = (symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier));
4728                symbolFromSymbolTable = shouldResolveAlias ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable;
4729                const flags = shouldResolveAlias ? getAllSymbolFlags(symbolFromSymbolTable) : symbolFromSymbolTable.flags;
4730                if (flags & meaning) {
4731                    qualify = true;
4732                    return true;
4733                }
4734
4735                // Continue to the next symbol table
4736                return false;
4737            });
4738
4739            return qualify;
4740        }
4741
4742        function isPropertyOrMethodDeclarationSymbol(symbol: Symbol) {
4743            if (symbol.declarations && symbol.declarations.length) {
4744                for (const declaration of symbol.declarations) {
4745                    switch (declaration.kind) {
4746                        case SyntaxKind.PropertyDeclaration:
4747                        case SyntaxKind.MethodDeclaration:
4748                        case SyntaxKind.GetAccessor:
4749                        case SyntaxKind.SetAccessor:
4750                            continue;
4751                        default:
4752                            return false;
4753                    }
4754                }
4755                return true;
4756            }
4757            return false;
4758        }
4759
4760        function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean {
4761            const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true);
4762            return access.accessibility === SymbolAccessibility.Accessible;
4763        }
4764
4765        function isValueSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean {
4766            const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, SymbolFlags.Value, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true);
4767            return access.accessibility === SymbolAccessibility.Accessible;
4768        }
4769
4770        function isSymbolAccessibleByFlags(typeSymbol: Symbol, enclosingDeclaration: Node | undefined, flags: SymbolFlags): boolean {
4771            const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, flags, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ false);
4772            return access.accessibility === SymbolAccessibility.Accessible;
4773        }
4774
4775        function isAnySymbolAccessible(symbols: Symbol[] | undefined, enclosingDeclaration: Node | undefined, initialSymbol: Symbol, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): SymbolAccessibilityResult | undefined {
4776            if (!length(symbols)) return;
4777
4778            let hadAccessibleChain: Symbol | undefined;
4779            let earlyModuleBail = false;
4780            for (const symbol of symbols!) {
4781                // Symbol is accessible if it by itself is accessible
4782                const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, /*useOnlyExternalAliasing*/ false);
4783                if (accessibleSymbolChain) {
4784                    hadAccessibleChain = symbol;
4785                    const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible);
4786                    if (hasAccessibleDeclarations) {
4787                        return hasAccessibleDeclarations;
4788                    }
4789                }
4790                if (allowModules) {
4791                    if (some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) {
4792                        if (shouldComputeAliasesToMakeVisible) {
4793                            earlyModuleBail = true;
4794                            // Generally speaking, we want to use the aliases that already exist to refer to a module, if present
4795                            // In order to do so, we need to find those aliases in order to retain them in declaration emit; so
4796                            // if we are in declaration emit, we cannot use the fast path for module visibility until we've exhausted
4797                            // all other visibility options (in order to capture the possible aliases used to reference the module)
4798                            continue;
4799                        }
4800                        // Any meaning of a module symbol is always accessible via an `import` type
4801                        return {
4802                            accessibility: SymbolAccessibility.Accessible
4803                        };
4804                    }
4805                }
4806
4807                // If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible.
4808                // It could be a qualified symbol and hence verify the path
4809                // e.g.:
4810                // module m {
4811                //     export class c {
4812                //     }
4813                // }
4814                // const x: typeof m.c
4815                // In the above example when we start with checking if typeof m.c symbol is accessible,
4816                // we are going to see if c can be accessed in scope directly.
4817                // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible
4818                // It is accessible if the parent m is accessible because then m.c can be accessed through qualification
4819
4820                const containers = getContainersOfSymbol(symbol, enclosingDeclaration, meaning);
4821                const parentResult = isAnySymbolAccessible(containers, enclosingDeclaration, initialSymbol, initialSymbol === symbol ? getQualifiedLeftMeaning(meaning) : meaning, shouldComputeAliasesToMakeVisible, allowModules);
4822                if (parentResult) {
4823                    return parentResult;
4824                }
4825            }
4826
4827            if (earlyModuleBail) {
4828                return {
4829                    accessibility: SymbolAccessibility.Accessible
4830                };
4831            }
4832
4833            if (hadAccessibleChain) {
4834                return {
4835                    accessibility: SymbolAccessibility.NotAccessible,
4836                    errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
4837                    errorModuleName: hadAccessibleChain !== initialSymbol ? symbolToString(hadAccessibleChain, enclosingDeclaration, SymbolFlags.Namespace) : undefined,
4838                };
4839            }
4840        }
4841
4842        /**
4843         * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested
4844         *
4845         * @param symbol a Symbol to check if accessible
4846         * @param enclosingDeclaration a Node containing reference to the symbol
4847         * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible
4848         * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible
4849         */
4850        function isSymbolAccessible(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult {
4851            return isSymbolAccessibleWorker(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible, /*allowModules*/ true);
4852        }
4853
4854        function isSymbolAccessibleWorker(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): SymbolAccessibilityResult {
4855            if (symbol && enclosingDeclaration) {
4856                const result = isAnySymbolAccessible([symbol], enclosingDeclaration, symbol, meaning, shouldComputeAliasesToMakeVisible, allowModules);
4857                if (result) {
4858                    return result;
4859                }
4860
4861                // This could be a symbol that is not exported in the external module
4862                // or it could be a symbol from different external module that is not aliased and hence cannot be named
4863                const symbolExternalModule = forEach(symbol.declarations, getExternalModuleContainer);
4864                if (symbolExternalModule) {
4865                    const enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration);
4866                    if (symbolExternalModule !== enclosingExternalModule) {
4867                        // name from different external module that is not visible
4868                        return {
4869                            accessibility: SymbolAccessibility.CannotBeNamed,
4870                            errorSymbolName: symbolToString(symbol, enclosingDeclaration, meaning),
4871                            errorModuleName: symbolToString(symbolExternalModule),
4872                            errorNode: isInJSFile(enclosingDeclaration) ? enclosingDeclaration : undefined,
4873                        };
4874                    }
4875                }
4876
4877                // Just a local name that is not accessible
4878                return {
4879                    accessibility: SymbolAccessibility.NotAccessible,
4880                    errorSymbolName: symbolToString(symbol, enclosingDeclaration, meaning),
4881                };
4882            }
4883
4884            return { accessibility: SymbolAccessibility.Accessible };
4885        }
4886
4887        function getExternalModuleContainer(declaration: Node) {
4888            const node = findAncestor(declaration, hasExternalModuleSymbol);
4889            return node && getSymbolOfNode(node);
4890        }
4891
4892        function hasExternalModuleSymbol(declaration: Node) {
4893            return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile));
4894        }
4895
4896        function hasNonGlobalAugmentationExternalModuleSymbol(declaration: Node) {
4897            return isModuleWithStringLiteralName(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile));
4898        }
4899
4900        function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined {
4901            let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined;
4902            if (!every(filter(symbol.declarations, d => d.kind !== SyntaxKind.Identifier), getIsDeclarationVisible)) {
4903                return undefined;
4904            }
4905            return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible };
4906
4907            function getIsDeclarationVisible(declaration: Declaration) {
4908                if (!isDeclarationVisible(declaration)) {
4909                    // Mark the unexported alias as visible if its parent is visible
4910                    // because these kind of aliases can be used to name types in declaration file
4911
4912                    const anyImportSyntax = getAnyImportSyntax(declaration);
4913                    if (anyImportSyntax &&
4914                        !hasSyntacticModifier(anyImportSyntax, ModifierFlags.Export) && // import clause without export
4915                        isDeclarationVisible(anyImportSyntax.parent)) {
4916                        return addVisibleAlias(declaration, anyImportSyntax);
4917                    }
4918                    else if (isVariableDeclaration(declaration) && isVariableStatement(declaration.parent.parent) &&
4919                        !hasSyntacticModifier(declaration.parent.parent, ModifierFlags.Export) && // unexported variable statement
4920                        isDeclarationVisible(declaration.parent.parent.parent)) {
4921                        return addVisibleAlias(declaration, declaration.parent.parent);
4922                    }
4923                    else if (isLateVisibilityPaintedStatement(declaration) // unexported top-level statement
4924                        && !hasSyntacticModifier(declaration, ModifierFlags.Export)
4925                        && isDeclarationVisible(declaration.parent)) {
4926                        return addVisibleAlias(declaration, declaration);
4927                    }
4928                    else if (isBindingElement(declaration)) {
4929                        if (symbol.flags & SymbolFlags.Alias && isInJSFile(declaration) && declaration.parent?.parent // exported import-like top-level JS require statement
4930                            && isVariableDeclaration(declaration.parent.parent)
4931                            && declaration.parent.parent.parent?.parent && isVariableStatement(declaration.parent.parent.parent.parent)
4932                            && !hasSyntacticModifier(declaration.parent.parent.parent.parent, ModifierFlags.Export)
4933                            && declaration.parent.parent.parent.parent.parent // check if the thing containing the variable statement is visible (ie, the file)
4934                            && isDeclarationVisible(declaration.parent.parent.parent.parent.parent)) {
4935                            return addVisibleAlias(declaration, declaration.parent.parent.parent.parent);
4936                        }
4937                        else if (symbol.flags & SymbolFlags.BlockScopedVariable) {
4938                            const variableStatement = findAncestor(declaration, isVariableStatement)!;
4939                            if (hasSyntacticModifier(variableStatement, ModifierFlags.Export)) {
4940                                return true;
4941                            }
4942                            if (!isDeclarationVisible(variableStatement.parent)) {
4943                                return false;
4944                            }
4945                            return addVisibleAlias(declaration, variableStatement);
4946                        }
4947                    }
4948
4949                    // Declaration is not visible
4950                    return false;
4951                }
4952
4953                return true;
4954            }
4955
4956            function addVisibleAlias(declaration: Declaration, aliasingStatement: LateVisibilityPaintedStatement) {
4957                // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types,
4958                // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time
4959                // since we will do the emitting later in trackSymbol.
4960                if (shouldComputeAliasToMakeVisible) {
4961                    getNodeLinks(declaration).isVisible = true;
4962                    aliasesToMakeVisible = appendIfUnique(aliasesToMakeVisible, aliasingStatement);
4963                }
4964                return true;
4965            }
4966        }
4967
4968        function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult {
4969            // get symbol of the first identifier of the entityName
4970            let meaning: SymbolFlags;
4971            if (entityName.parent.kind === SyntaxKind.TypeQuery ||
4972                entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) ||
4973                entityName.parent.kind === SyntaxKind.ComputedPropertyName) {
4974                // Typeof value
4975                meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
4976            }
4977            else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression ||
4978                entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) {
4979                // Left identifier from type reference or TypeAlias
4980                // Entity name of the import declaration
4981                meaning = SymbolFlags.Namespace;
4982            }
4983            else {
4984                // Type Reference or TypeAlias entity = Identifier
4985                meaning = SymbolFlags.Type;
4986            }
4987
4988            const firstIdentifier = getFirstIdentifier(entityName);
4989            const symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false);
4990            if (symbol && symbol.flags & SymbolFlags.TypeParameter && meaning & SymbolFlags.Type) {
4991                return { accessibility: SymbolAccessibility.Accessible };
4992            }
4993            if (!symbol && isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfNode(getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false)), firstIdentifier, meaning, /*computeAliases*/ false).accessibility === SymbolAccessibility.Accessible) {
4994                return { accessibility: SymbolAccessibility.Accessible };
4995            }
4996
4997            // Verify if the symbol is accessible
4998            return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || {
4999                accessibility: SymbolAccessibility.NotAccessible,
5000                errorSymbolName: getTextOfNode(firstIdentifier),
5001                errorNode: firstIdentifier
5002            };
5003        }
5004
5005        function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.AllowAnyNodeKind, writer?: EmitTextWriter): string {
5006            let nodeFlags = NodeBuilderFlags.IgnoreErrors;
5007            if (flags & SymbolFormatFlags.UseOnlyExternalAliasing) {
5008                nodeFlags |= NodeBuilderFlags.UseOnlyExternalAliasing;
5009            }
5010            if (flags & SymbolFormatFlags.WriteTypeParametersOrArguments) {
5011                nodeFlags |= NodeBuilderFlags.WriteTypeParametersInQualifiedName;
5012            }
5013            if (flags & SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope) {
5014                nodeFlags |= NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope;
5015            }
5016            if (flags & SymbolFormatFlags.DoNotIncludeSymbolChain) {
5017                nodeFlags |= NodeBuilderFlags.DoNotIncludeSymbolChain;
5018            }
5019            if (flags & SymbolFormatFlags.WriteComputedProps) {
5020                nodeFlags |= NodeBuilderFlags.WriteComputedProps;
5021            }
5022            const builder = flags & SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToNode : nodeBuilder.symbolToEntityName;
5023            return writer ? symbolToStringWorker(writer).getText() : usingSingleLineStringWriter(symbolToStringWorker);
5024
5025            function symbolToStringWorker(writer: EmitTextWriter) {
5026                const entity = builder(symbol, meaning!, enclosingDeclaration, nodeFlags)!; // TODO: GH#18217
5027                // add neverAsciiEscape for GH#39027
5028                const printer = enclosingDeclaration?.kind === SyntaxKind.SourceFile ? createPrinter({ removeComments: true, neverAsciiEscape: true }) : createPrinter({ removeComments: true });
5029                const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
5030                printer.writeNode(EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer);
5031                return writer;
5032            }
5033        }
5034
5035        function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags = TypeFormatFlags.None, kind?: SignatureKind, writer?: EmitTextWriter): string {
5036            return writer ? signatureToStringWorker(writer).getText() : usingSingleLineStringWriter(signatureToStringWorker);
5037
5038            function signatureToStringWorker(writer: EmitTextWriter) {
5039                let sigOutput: SyntaxKind;
5040                if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
5041                    sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructorType : SyntaxKind.FunctionType;
5042                }
5043                else {
5044                    sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructSignature : SyntaxKind.CallSignature;
5045                }
5046                const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName);
5047                const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true });
5048                const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
5049                printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217
5050                return writer;
5051            }
5052        }
5053
5054        function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer: EmitTextWriter = createTextWriter("")): string {
5055            const noTruncation = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation;
5056            const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | (noTruncation ? NodeBuilderFlags.NoTruncation : 0), writer);
5057            if (typeNode === undefined) return Debug.fail("should always get typenode");
5058            // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`.
5059            // Otherwise, we always strip comments out.
5060            const options = { removeComments: type !== unresolvedType };
5061            const printer = createPrinter(options);
5062            const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
5063            printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer);
5064            const result = writer.getText();
5065
5066            const maxLength = noTruncation ? noTruncationMaximumTruncationLength * 2 : defaultMaximumTruncationLength * 2;
5067            if (maxLength && result && result.length >= maxLength) {
5068                return result.substr(0, maxLength - "...".length) + "...";
5069            }
5070            return result;
5071        }
5072
5073        function getTypeNamesForErrorDisplay(left: Type, right: Type): [string, string] {
5074            let leftStr = symbolValueDeclarationIsContextSensitive(left.symbol) ? typeToString(left, left.symbol.valueDeclaration) : typeToString(left);
5075            let rightStr = symbolValueDeclarationIsContextSensitive(right.symbol) ? typeToString(right, right.symbol.valueDeclaration) : typeToString(right);
5076            if (leftStr === rightStr) {
5077                leftStr = getTypeNameForErrorDisplay(left);
5078                rightStr = getTypeNameForErrorDisplay(right);
5079            }
5080            return [leftStr, rightStr];
5081        }
5082
5083        function getTypeNameForErrorDisplay(type: Type) {
5084            return typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
5085        }
5086
5087        function symbolValueDeclarationIsContextSensitive(symbol: Symbol): boolean {
5088            return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !isContextSensitive(symbol.valueDeclaration);
5089        }
5090
5091        function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags {
5092            return flags & TypeFormatFlags.NodeBuilderFlagsMask;
5093        }
5094
5095        function isClassInstanceSide(type: Type) {
5096            return !!type.symbol && !!(type.symbol.flags & SymbolFlags.Class) && (type === getDeclaredTypeOfClassOrInterface(type.symbol) || (!!(type.flags & TypeFlags.Object) && !!(getObjectFlags(type) & ObjectFlags.IsClassInstanceClone)));
5097        }
5098
5099        function createNodeBuilder() {
5100            return {
5101                typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5102                    withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)),
5103                indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5104                    withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined)),
5105                signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5106                    withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)),
5107                symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5108                    withContext(enclosingDeclaration, flags, tracker, context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false)),
5109                symbolToExpression: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5110                    withContext(enclosingDeclaration, flags, tracker, context => symbolToExpression(symbol, context, meaning)),
5111                symbolToTypeParameterDeclarations: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5112                    withContext(enclosingDeclaration, flags, tracker, context => typeParametersToTypeParameterDeclarations(symbol, context)),
5113                symbolToParameterDeclaration: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5114                    withContext(enclosingDeclaration, flags, tracker, context => symbolToParameterDeclaration(symbol, context)),
5115                typeParameterToDeclaration: (parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5116                    withContext(enclosingDeclaration, flags, tracker, context => typeParameterToDeclaration(parameter, context)),
5117                symbolTableToDeclarationStatements: (symbolTable: SymbolTable, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker, bundled?: boolean) =>
5118                    withContext(enclosingDeclaration, flags, tracker, context => symbolTableToDeclarationStatements(symbolTable, context, bundled)),
5119                symbolToNode: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
5120                    withContext(enclosingDeclaration, flags, tracker, context => symbolToNode(symbol, context, meaning)),
5121            };
5122
5123            function symbolToNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) {
5124                if (context.flags & NodeBuilderFlags.WriteComputedProps) {
5125                    if (symbol.valueDeclaration) {
5126                        const name = getNameOfDeclaration(symbol.valueDeclaration);
5127                        if (name && isComputedPropertyName(name)) return name;
5128                    }
5129                    const nameType = getSymbolLinks(symbol).nameType;
5130                    if (nameType && nameType.flags & (TypeFlags.EnumLiteral | TypeFlags.UniqueESSymbol)) {
5131                       context.enclosingDeclaration = nameType.symbol.valueDeclaration;
5132                       return factory.createComputedPropertyName(symbolToExpression(nameType.symbol, context, meaning));
5133                    }
5134                }
5135                return symbolToExpression(symbol, context, meaning);
5136            }
5137
5138            function withContext<T>(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker: SymbolTracker | undefined, cb: (context: NodeBuilderContext) => T): T | undefined {
5139                Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0);
5140                const context: NodeBuilderContext = {
5141                    enclosingDeclaration,
5142                    flags: flags || NodeBuilderFlags.None,
5143                    // If no full tracker is provided, fake up a dummy one with a basic limited-functionality moduleResolverHost
5144                    tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: () => false, moduleResolverHost: flags! & NodeBuilderFlags.DoNotIncludeSymbolChain ? {
5145                        getCommonSourceDirectory: !!(host as Program).getCommonSourceDirectory ? () => (host as Program).getCommonSourceDirectory() : () => "",
5146                        getCurrentDirectory: () => host.getCurrentDirectory(),
5147                        getSymlinkCache: maybeBind(host, host.getSymlinkCache),
5148                        getPackageJsonInfoCache: () => host.getPackageJsonInfoCache?.(),
5149                        useCaseSensitiveFileNames: maybeBind(host, host.useCaseSensitiveFileNames),
5150                        redirectTargetsMap: host.redirectTargetsMap,
5151                        getProjectReferenceRedirect: fileName => host.getProjectReferenceRedirect(fileName),
5152                        isSourceOfProjectReferenceRedirect: fileName => host.isSourceOfProjectReferenceRedirect(fileName),
5153                        fileExists: fileName => host.fileExists(fileName),
5154                        getFileIncludeReasons: () => host.getFileIncludeReasons(),
5155                        readFile: host.readFile ? (fileName => host.readFile!(fileName)) : undefined,
5156                    } : undefined },
5157                    encounteredError: false,
5158                    reportedDiagnostic: false,
5159                    visitedTypes: undefined,
5160                    symbolDepth: undefined,
5161                    inferTypeParameters: undefined,
5162                    approximateLength: 0
5163                };
5164                context.tracker = wrapSymbolTrackerToReportForContext(context, context.tracker);
5165                const resultingNode = cb(context);
5166                if (context.truncating && context.flags & NodeBuilderFlags.NoTruncation) {
5167                    context.tracker?.reportTruncationError?.();
5168                }
5169                return context.encounteredError ? undefined : resultingNode;
5170            }
5171
5172            function wrapSymbolTrackerToReportForContext(context: NodeBuilderContext, tracker: SymbolTracker): SymbolTracker {
5173                const oldTrackSymbol = tracker.trackSymbol;
5174                return {
5175                    ...tracker,
5176                    reportCyclicStructureError: wrapReportedDiagnostic(tracker.reportCyclicStructureError),
5177                    reportInaccessibleThisError: wrapReportedDiagnostic(tracker.reportInaccessibleThisError),
5178                    reportInaccessibleUniqueSymbolError: wrapReportedDiagnostic(tracker.reportInaccessibleUniqueSymbolError),
5179                    reportLikelyUnsafeImportRequiredError: wrapReportedDiagnostic(tracker.reportLikelyUnsafeImportRequiredError),
5180                    reportNonlocalAugmentation: wrapReportedDiagnostic(tracker.reportNonlocalAugmentation),
5181                    reportPrivateInBaseOfClassExpression: wrapReportedDiagnostic(tracker.reportPrivateInBaseOfClassExpression),
5182                    reportNonSerializableProperty: wrapReportedDiagnostic(tracker.reportNonSerializableProperty),
5183                    trackSymbol: oldTrackSymbol && ((...args) => {
5184                        const result = oldTrackSymbol(...args);
5185                        if (result) {
5186                            context.reportedDiagnostic = true;
5187                        }
5188                        return result;
5189                    }),
5190                };
5191
5192                function wrapReportedDiagnostic<T extends (...args: any[]) => any>(method: T | undefined): T | undefined {
5193                    if (!method) {
5194                        return method;
5195                    }
5196                    return (((...args) => {
5197                        context.reportedDiagnostic = true;
5198                        return method(...args);
5199                    }) as T);
5200                }
5201            }
5202
5203            function checkTruncationLength(context: NodeBuilderContext): boolean {
5204                if (context.truncating) return context.truncating;
5205                return context.truncating = context.approximateLength > ((context.flags & NodeBuilderFlags.NoTruncation) ? noTruncationMaximumTruncationLength : defaultMaximumTruncationLength);
5206            }
5207
5208            function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode {
5209                const savedFlags = context.flags;
5210                const typeNode = typeToTypeNodeWorker(type, context);
5211                context.flags = savedFlags;
5212                return typeNode;
5213            }
5214
5215            function typeToTypeNodeWorker(type: Type, context: NodeBuilderContext): TypeNode {
5216                if (cancellationToken && cancellationToken.throwIfCancellationRequested) {
5217                    cancellationToken.throwIfCancellationRequested();
5218                }
5219                const inTypeAlias = context.flags & NodeBuilderFlags.InTypeAlias;
5220                context.flags &= ~NodeBuilderFlags.InTypeAlias;
5221
5222                if (!type) {
5223                    if (!(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) {
5224                        context.encounteredError = true;
5225                        return undefined!; // TODO: GH#18217
5226                    }
5227                    context.approximateLength += 3;
5228                    return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
5229                }
5230
5231                if (!(context.flags & NodeBuilderFlags.NoTypeReduction)) {
5232                    type = getReducedType(type);
5233                }
5234
5235                if (type.flags & TypeFlags.Any) {
5236                    if (type.aliasSymbol) {
5237                        return factory.createTypeReferenceNode(symbolToEntityNameNode(type.aliasSymbol), mapToTypeNodes(type.aliasTypeArguments, context));
5238                    }
5239                    if (type === unresolvedType) {
5240                        return addSyntheticLeadingComment(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), SyntaxKind.MultiLineCommentTrivia, "unresolved");
5241                    }
5242                    context.approximateLength += 3;
5243                    return factory.createKeywordTypeNode(type === intrinsicMarkerType ? SyntaxKind.IntrinsicKeyword : SyntaxKind.AnyKeyword);
5244                }
5245                if (type.flags & TypeFlags.Unknown) {
5246                    return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword);
5247                }
5248                if (type.flags & TypeFlags.String) {
5249                    context.approximateLength += 6;
5250                    return factory.createKeywordTypeNode(SyntaxKind.StringKeyword);
5251                }
5252                if (type.flags & TypeFlags.Number) {
5253                    context.approximateLength += 6;
5254                    return factory.createKeywordTypeNode(SyntaxKind.NumberKeyword);
5255                }
5256                if (type.flags & TypeFlags.BigInt) {
5257                    context.approximateLength += 6;
5258                    return factory.createKeywordTypeNode(SyntaxKind.BigIntKeyword);
5259                }
5260                if (type.flags & TypeFlags.Boolean && !type.aliasSymbol) {
5261                    context.approximateLength += 7;
5262                    return factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword);
5263                }
5264                if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) {
5265                    const parentSymbol = getParentOfSymbol(type.symbol)!;
5266                    const parentName = symbolToTypeNode(parentSymbol, context, SymbolFlags.Type);
5267                    if (getDeclaredTypeOfSymbol(parentSymbol) === type) {
5268                        return parentName;
5269                    }
5270                    const memberName = symbolName(type.symbol);
5271                    if (isIdentifierText(memberName, ScriptTarget.ES3)) {
5272                        return appendReferenceToType(
5273                            parentName as TypeReferenceNode | ImportTypeNode,
5274                            factory.createTypeReferenceNode(memberName, /*typeArguments*/ undefined)
5275                        );
5276                    }
5277                    if (isImportTypeNode(parentName)) {
5278                        (parentName as any).isTypeOf = true; // mutably update, node is freshly manufactured anyhow
5279                        return factory.createIndexedAccessTypeNode(parentName, factory.createLiteralTypeNode(factory.createStringLiteral(memberName)));
5280                    }
5281                    else if (isTypeReferenceNode(parentName)) {
5282                        return factory.createIndexedAccessTypeNode(factory.createTypeQueryNode(parentName.typeName), factory.createLiteralTypeNode(factory.createStringLiteral(memberName)));
5283                    }
5284                    else {
5285                        return Debug.fail("Unhandled type node kind returned from `symbolToTypeNode`.");
5286                    }
5287                }
5288                if (type.flags & TypeFlags.EnumLike) {
5289                    return symbolToTypeNode(type.symbol, context, SymbolFlags.Type);
5290                }
5291                if (type.flags & TypeFlags.StringLiteral) {
5292                    context.approximateLength += ((type as StringLiteralType).value.length + 2);
5293                    return factory.createLiteralTypeNode(setEmitFlags(factory.createStringLiteral((type as StringLiteralType).value, !!(context.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType)), EmitFlags.NoAsciiEscaping));
5294                }
5295                if (type.flags & TypeFlags.NumberLiteral) {
5296                    const value = (type as NumberLiteralType).value;
5297                    context.approximateLength += ("" + value).length;
5298                    return factory.createLiteralTypeNode(value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-value)) : factory.createNumericLiteral(value));
5299                }
5300                if (type.flags & TypeFlags.BigIntLiteral) {
5301                    context.approximateLength += (pseudoBigIntToString((type as BigIntLiteralType).value).length) + 1;
5302                    return factory.createLiteralTypeNode((factory.createBigIntLiteral((type as BigIntLiteralType).value)));
5303                }
5304                if (type.flags & TypeFlags.BooleanLiteral) {
5305                    context.approximateLength += (type as IntrinsicType).intrinsicName.length;
5306                    return factory.createLiteralTypeNode((type as IntrinsicType).intrinsicName === "true" ? factory.createTrue() : factory.createFalse());
5307                }
5308                if (type.flags & TypeFlags.UniqueESSymbol) {
5309                    if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) {
5310                        if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) {
5311                            context.approximateLength += 6;
5312                            return symbolToTypeNode(type.symbol, context, SymbolFlags.Value);
5313                        }
5314                        if (context.tracker.reportInaccessibleUniqueSymbolError) {
5315                            context.tracker.reportInaccessibleUniqueSymbolError();
5316                        }
5317                    }
5318                    context.approximateLength += 13;
5319                    return factory.createTypeOperatorNode(SyntaxKind.UniqueKeyword, factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword));
5320                }
5321                if (type.flags & TypeFlags.Void) {
5322                    context.approximateLength += 4;
5323                    return factory.createKeywordTypeNode(SyntaxKind.VoidKeyword);
5324                }
5325                if (type.flags & TypeFlags.Undefined) {
5326                    context.approximateLength += 9;
5327                    return factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
5328                }
5329                if (type.flags & TypeFlags.Null) {
5330                    context.approximateLength += 4;
5331                    return factory.createLiteralTypeNode(factory.createNull());
5332                }
5333                if (type.flags & TypeFlags.Never) {
5334                    context.approximateLength += 5;
5335                    return factory.createKeywordTypeNode(SyntaxKind.NeverKeyword);
5336                }
5337                if (type.flags & TypeFlags.ESSymbol) {
5338                    context.approximateLength += 6;
5339                    return factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword);
5340                }
5341                if (type.flags & TypeFlags.NonPrimitive) {
5342                    context.approximateLength += 6;
5343                    return factory.createKeywordTypeNode(SyntaxKind.ObjectKeyword);
5344                }
5345                if (isThisTypeParameter(type)) {
5346                    if (context.flags & NodeBuilderFlags.InObjectTypeLiteral) {
5347                        if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) {
5348                            context.encounteredError = true;
5349                        }
5350                        if (context.tracker.reportInaccessibleThisError) {
5351                            context.tracker.reportInaccessibleThisError();
5352                        }
5353                    }
5354                    context.approximateLength += 4;
5355                    return factory.createThisTypeNode();
5356                }
5357
5358                if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) {
5359                    const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context);
5360                    if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class)) return factory.createTypeReferenceNode(factory.createIdentifier(""), typeArgumentNodes);
5361                    if (length(typeArgumentNodes) === 1 && type.aliasSymbol === globalArrayType.symbol) {
5362                        return factory.createArrayTypeNode(typeArgumentNodes![0]);
5363                    }
5364                    return symbolToTypeNode(type.aliasSymbol, context, SymbolFlags.Type, typeArgumentNodes);
5365                }
5366
5367                const objectFlags = getObjectFlags(type);
5368
5369                if (objectFlags & ObjectFlags.Reference) {
5370                    Debug.assert(!!(type.flags & TypeFlags.Object));
5371                    return (type as TypeReference).node ? visitAndTransformType(type, typeReferenceToTypeNode) : typeReferenceToTypeNode(type as TypeReference);
5372                }
5373                if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) {
5374                    if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) {
5375                        context.approximateLength += (symbolName(type.symbol).length + 6);
5376                        let constraintNode: TypeNode | undefined;
5377                        const constraint = getConstraintOfTypeParameter(type as TypeParameter);
5378                        if (constraint) {
5379                            // If the infer type has a constraint that is not the same as the constraint
5380                            // we would have normally inferred based on context, we emit the constraint
5381                            // using `infer T extends ?`. We omit inferred constraints from type references
5382                            // as they may be elided.
5383                            const inferredConstraint = getInferredTypeParameterConstraint(type as TypeParameter, /*omitTypeReferences*/ true);
5384                            if (!(inferredConstraint && isTypeIdenticalTo(constraint, inferredConstraint))) {
5385                                context.approximateLength += 9;
5386                                constraintNode = constraint && typeToTypeNodeHelper(constraint, context);
5387                            }
5388                        }
5389                        return factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, constraintNode));
5390                    }
5391                    if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams &&
5392                        type.flags & TypeFlags.TypeParameter &&
5393                        !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) {
5394                        const name = typeParameterToName(type, context);
5395                        context.approximateLength += idText(name).length;
5396                        return factory.createTypeReferenceNode(factory.createIdentifier(idText(name)), /*typeArguments*/ undefined);
5397                    }
5398                    // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
5399                    if (type.symbol) {
5400                        return symbolToTypeNode(type.symbol, context, SymbolFlags.Type);
5401                    }
5402                    const name = (type === markerSuperTypeForCheck || type === markerSubTypeForCheck) && varianceTypeParameter && varianceTypeParameter.symbol ?
5403                        (type === markerSubTypeForCheck ? "sub-" : "super-") + symbolName(varianceTypeParameter.symbol) : "?";
5404                    return factory.createTypeReferenceNode(factory.createIdentifier(name), /*typeArguments*/ undefined);
5405                }
5406                if (type.flags & TypeFlags.Union && (type as UnionType).origin) {
5407                    type = (type as UnionType).origin!;
5408                }
5409                if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) {
5410                    const types = type.flags & TypeFlags.Union ? formatUnionTypes((type as UnionType).types) : (type as IntersectionType).types;
5411                    if (length(types) === 1) {
5412                        return typeToTypeNodeHelper(types[0], context);
5413                    }
5414                    const typeNodes = mapToTypeNodes(types, context, /*isBareList*/ true);
5415                    if (typeNodes && typeNodes.length > 0) {
5416                        return type.flags & TypeFlags.Union ? factory.createUnionTypeNode(typeNodes) : factory.createIntersectionTypeNode(typeNodes);
5417                    }
5418                    else {
5419                        if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) {
5420                            context.encounteredError = true;
5421                        }
5422                        return undefined!; // TODO: GH#18217
5423                    }
5424                }
5425                if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
5426                    Debug.assert(!!(type.flags & TypeFlags.Object));
5427                    // The type is an object literal type.
5428                    return createAnonymousTypeNode(type as ObjectType);
5429                }
5430                if (type.flags & TypeFlags.Index) {
5431                    const indexedType = (type as IndexType).type;
5432                    context.approximateLength += 6;
5433                    const indexTypeNode = typeToTypeNodeHelper(indexedType, context);
5434                    return factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, indexTypeNode);
5435                }
5436                if (type.flags & TypeFlags.TemplateLiteral) {
5437                    const texts = (type as TemplateLiteralType).texts;
5438                    const types = (type as TemplateLiteralType).types;
5439                    const templateHead = factory.createTemplateHead(texts[0]);
5440                    const templateSpans = factory.createNodeArray(
5441                        map(types, (t, i) => factory.createTemplateLiteralTypeSpan(
5442                            typeToTypeNodeHelper(t, context),
5443                            (i < types.length - 1 ? factory.createTemplateMiddle : factory.createTemplateTail)(texts[i + 1]))));
5444                    context.approximateLength += 2;
5445                    return factory.createTemplateLiteralType(templateHead, templateSpans);
5446                }
5447                if (type.flags & TypeFlags.StringMapping) {
5448                    const typeNode = typeToTypeNodeHelper((type as StringMappingType).type, context);
5449                    return symbolToTypeNode((type as StringMappingType).symbol, context, SymbolFlags.Type, [typeNode]);
5450                }
5451                if (type.flags & TypeFlags.IndexedAccess) {
5452                    const objectTypeNode = typeToTypeNodeHelper((type as IndexedAccessType).objectType, context);
5453                    const indexTypeNode = typeToTypeNodeHelper((type as IndexedAccessType).indexType, context);
5454                    context.approximateLength += 2;
5455                    return factory.createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
5456                }
5457                if (type.flags & TypeFlags.Conditional) {
5458                    return visitAndTransformType(type, type => conditionalTypeToTypeNode(type as ConditionalType));
5459                }
5460                if (type.flags & TypeFlags.Substitution) {
5461                    return typeToTypeNodeHelper((type as SubstitutionType).baseType, context);
5462                }
5463
5464                return Debug.fail("Should be unreachable.");
5465
5466
5467                function conditionalTypeToTypeNode(type: ConditionalType) {
5468                    const checkTypeNode = typeToTypeNodeHelper(type.checkType, context);
5469                    context.approximateLength += 15;
5470                    if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.root.isDistributive && !(type.checkType.flags & TypeFlags.TypeParameter)) {
5471                        const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String));
5472                        const name = typeParameterToName(newParam, context);
5473                        const newTypeVariable = factory.createTypeReferenceNode(name);
5474                        context.approximateLength += 37; // 15 each for two added conditionals, 7 for an added infer type
5475                        const newMapper = prependTypeMapping(type.root.checkType, newParam, type.mapper);
5476                        const saveInferTypeParameters = context.inferTypeParameters;
5477                        context.inferTypeParameters = type.root.inferTypeParameters;
5478                        const extendsTypeNode = typeToTypeNodeHelper(instantiateType(type.root.extendsType, newMapper), context);
5479                        context.inferTypeParameters = saveInferTypeParameters;
5480                        const trueTypeNode = typeToTypeNodeOrCircularityElision(instantiateType(getTypeFromTypeNode(type.root.node.trueType), newMapper));
5481                        const falseTypeNode = typeToTypeNodeOrCircularityElision(instantiateType(getTypeFromTypeNode(type.root.node.falseType), newMapper));
5482
5483
5484                        // outermost conditional makes `T` a type parameter, allowing the inner conditionals to be distributive
5485                        // second conditional makes `T` have `T & checkType` substitution, so it is correctly usable as the checkType
5486                        // inner conditional runs the check the user provided on the check type (distributively) and returns the result
5487                        // checkType extends infer T ? T extends checkType ? T extends extendsType<T> ? trueType<T> : falseType<T> : never : never;
5488                        // this is potentially simplifiable to
5489                        // checkType extends infer T ? T extends checkType & extendsType<T> ? trueType<T> : falseType<T> : never;
5490                        // but that may confuse users who read the output more.
5491                        // On the other hand,
5492                        // checkType extends infer T extends checkType ? T extends extendsType<T> ? trueType<T> : falseType<T> : never;
5493                        // may also work with `infer ... extends ...` in, but would produce declarations only compatible with the latest TS.
5494                        return factory.createConditionalTypeNode(
5495                            checkTypeNode,
5496                            factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable.typeName) as Identifier)),
5497                            factory.createConditionalTypeNode(
5498                                factory.createTypeReferenceNode(factory.cloneNode(name)),
5499                                typeToTypeNodeHelper(type.checkType, context),
5500                                factory.createConditionalTypeNode(newTypeVariable, extendsTypeNode, trueTypeNode, falseTypeNode),
5501                                factory.createKeywordTypeNode(SyntaxKind.NeverKeyword)
5502                            ),
5503                            factory.createKeywordTypeNode(SyntaxKind.NeverKeyword)
5504                        );
5505                    }
5506                    const saveInferTypeParameters = context.inferTypeParameters;
5507                    context.inferTypeParameters = type.root.inferTypeParameters;
5508                    const extendsTypeNode = typeToTypeNodeHelper(type.extendsType, context);
5509                    context.inferTypeParameters = saveInferTypeParameters;
5510                    const trueTypeNode = typeToTypeNodeOrCircularityElision(getTrueTypeFromConditionalType(type));
5511                    const falseTypeNode = typeToTypeNodeOrCircularityElision(getFalseTypeFromConditionalType(type));
5512                    return factory.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
5513                }
5514
5515                function typeToTypeNodeOrCircularityElision(type: Type) {
5516                    if (type.flags & TypeFlags.Union) {
5517                        if (context.visitedTypes?.has(getTypeId(type))) {
5518                            if (!(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) {
5519                                context.encounteredError = true;
5520                                context.tracker?.reportCyclicStructureError?.();
5521                            }
5522                            return createElidedInformationPlaceholder(context);
5523                        }
5524                        return visitAndTransformType(type, type => typeToTypeNodeHelper(type, context));
5525                    }
5526                    return typeToTypeNodeHelper(type, context);
5527                }
5528
5529                function isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type: MappedType) {
5530                    return isMappedTypeWithKeyofConstraintDeclaration(type)
5531                        && !(getModifiersTypeFromMappedType(type).flags & TypeFlags.TypeParameter);
5532                }
5533
5534                function createMappedTypeNodeFromType(type: MappedType) {
5535                    Debug.assert(!!(type.flags & TypeFlags.Object));
5536                    const readonlyToken = type.declaration.readonlyToken ? factory.createToken(type.declaration.readonlyToken.kind) as ReadonlyKeyword | PlusToken | MinusToken : undefined;
5537                    const questionToken = type.declaration.questionToken ? factory.createToken(type.declaration.questionToken.kind) as QuestionToken | PlusToken | MinusToken : undefined;
5538                    let appropriateConstraintTypeNode: TypeNode;
5539                    let newTypeVariable: TypeReferenceNode | undefined;
5540                    if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
5541                        // We have a { [P in keyof T]: X }
5542                        // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType`
5543                        if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) {
5544                            const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String));
5545                            const name = typeParameterToName(newParam, context);
5546                            newTypeVariable = factory.createTypeReferenceNode(name);
5547                        }
5548                        appropriateConstraintTypeNode = factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, newTypeVariable || typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context));
5549                    }
5550                    else {
5551                        appropriateConstraintTypeNode = typeToTypeNodeHelper(getConstraintTypeFromMappedType(type), context);
5552                    }
5553                    const typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode);
5554                    const nameTypeNode = type.declaration.nameType ? typeToTypeNodeHelper(getNameTypeFromMappedType(type)!, context) : undefined;
5555                    const templateTypeNode = typeToTypeNodeHelper(removeMissingType(getTemplateTypeFromMappedType(type), !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), context);
5556                    const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode, /*members*/ undefined);
5557                    context.approximateLength += 10;
5558                    const result = setEmitFlags(mappedTypeNode, EmitFlags.SingleLine);
5559                    if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) {
5560                        // homomorphic mapped type with a non-homomorphic naive inlining
5561                        // wrap it with a conditional like `SomeModifiersType extends infer U ? {..the mapped type...} : never` to ensure the resulting
5562                        // type stays homomorphic
5563                        const originalConstraint = instantiateType(getConstraintOfTypeParameter(getTypeFromTypeNode((type.declaration.typeParameter.constraint! as TypeOperatorNode).type) as TypeParameter) || unknownType, type.mapper);
5564                        return factory.createConditionalTypeNode(
5565                            typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context),
5566                            factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable!.typeName) as Identifier, originalConstraint.flags & TypeFlags.Unknown ? undefined : typeToTypeNodeHelper(originalConstraint, context))),
5567                            result,
5568                            factory.createKeywordTypeNode(SyntaxKind.NeverKeyword)
5569                        );
5570                    }
5571                    return result;
5572                }
5573
5574                function createAnonymousTypeNode(type: ObjectType): TypeNode {
5575                    const typeId = type.id;
5576                    const symbol = type.symbol;
5577                    if (symbol) {
5578                        const isInstanceType = isClassInstanceSide(type) ? SymbolFlags.Type : SymbolFlags.Value;
5579                        if (isJSConstructor(symbol.valueDeclaration)) {
5580                            // Instance and static types share the same symbol; only add 'typeof' for the static side.
5581                            return symbolToTypeNode(symbol, context, isInstanceType);
5582                        }
5583                        // Always use 'typeof T' for type of class, enum, and module objects
5584                        else if (symbol.flags & SymbolFlags.Class
5585                            && !getBaseTypeVariableOfClass(symbol)
5586                            && !(symbol.valueDeclaration && isClassLike(symbol.valueDeclaration) && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && (!isClassDeclaration(symbol.valueDeclaration) || isSymbolAccessible(symbol, context.enclosingDeclaration, isInstanceType, /*computeAliases*/ false).accessibility !== SymbolAccessibility.Accessible)) ||
5587                            symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) ||
5588                            shouldWriteTypeOfFunctionSymbol()) {
5589                            return symbolToTypeNode(symbol, context, isInstanceType);
5590                        }
5591                        else if (context.visitedTypes?.has(typeId)) {
5592                            // If type is an anonymous type literal in a type alias declaration, use type alias name
5593                            const typeAlias = getTypeAliasForTypeLiteral(type);
5594                            if (typeAlias) {
5595                                // The specified symbol flags need to be reinterpreted as type flags
5596                                return symbolToTypeNode(typeAlias, context, SymbolFlags.Type);
5597                            }
5598                            else {
5599                                return createElidedInformationPlaceholder(context);
5600                            }
5601                        }
5602                        else {
5603                            return visitAndTransformType(type, createTypeNodeFromObjectType);
5604                        }
5605                    }
5606                    else {
5607                        // Anonymous types without a symbol are never circular.
5608                        return createTypeNodeFromObjectType(type);
5609                    }
5610                    function shouldWriteTypeOfFunctionSymbol() {
5611                        const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) &&  // typeof static method
5612                            some(symbol.declarations, declaration => isStatic(declaration));
5613                        const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
5614                            (symbol.parent || // is exported function symbol
5615                                forEach(symbol.declarations, declaration =>
5616                                    declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
5617                        if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
5618                            // typeof is allowed only for static/non local functions
5619                            return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedTypes?.has(typeId))) && // it is type of the symbol uses itself recursively
5620                                (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // And the build is going to succeed without visibility error or there is no structural fallback allowed
5621                        }
5622                    }
5623                }
5624
5625                function visitAndTransformType<T extends TypeNode>(type: Type, transform: (type: Type) => T) {
5626                    const typeId = type.id;
5627                    const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class;
5628                    const id = getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).node ? "N" + getNodeId((type as TypeReference).node!) :
5629                        type.flags & TypeFlags.Conditional ? "N" + getNodeId((type as ConditionalType).root.node) :
5630                        type.symbol ? (isConstructorObject ? "+" : "") + getSymbolId(type.symbol) :
5631                        undefined;
5632                    // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
5633                    // of types allows us to catch circular references to instantiations of the same anonymous type
5634                    if (!context.visitedTypes) {
5635                        context.visitedTypes = new Set();
5636                    }
5637                    if (id && !context.symbolDepth) {
5638                        context.symbolDepth = new Map();
5639                    }
5640
5641                    const links = context.enclosingDeclaration && getNodeLinks(context.enclosingDeclaration);
5642                    const key = `${getTypeId(type)}|${context.flags}`;
5643                    if (links) {
5644                        links.serializedTypes ||= new Map();
5645                    }
5646                    const cachedResult = links?.serializedTypes?.get(key);
5647                    if (cachedResult) {
5648                        if (cachedResult.truncating) {
5649                            context.truncating = true;
5650                        }
5651                        context.approximateLength += cachedResult.addedLength;
5652                        return deepCloneOrReuseNode(cachedResult) as TypeNode as T;
5653                    }
5654
5655                    let depth: number | undefined;
5656                    if (id) {
5657                        depth = context.symbolDepth!.get(id) || 0;
5658                        if (depth > 10) {
5659                            return createElidedInformationPlaceholder(context);
5660                        }
5661                        context.symbolDepth!.set(id, depth + 1);
5662                    }
5663                    context.visitedTypes.add(typeId);
5664                    const startLength = context.approximateLength;
5665                    const result = transform(type);
5666                    const addedLength = context.approximateLength - startLength;
5667                    if (!context.reportedDiagnostic && !context.encounteredError) {
5668                        if (context.truncating) {
5669                            (result as any).truncating = true;
5670                        }
5671                        (result as any).addedLength = addedLength;
5672                        links?.serializedTypes?.set(key, result as TypeNode as TypeNode & {truncating?: boolean, addedLength: number});
5673                    }
5674                    context.visitedTypes.delete(typeId);
5675                    if (id) {
5676                        context.symbolDepth!.set(id, depth!);
5677                    }
5678                    return result;
5679
5680                    function deepCloneOrReuseNode(node: Node): Node {
5681                        if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) {
5682                            return node;
5683                        }
5684                        return setTextRange(factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, nullTransformationContext, deepCloneOrReuseNodes)), node);
5685                    }
5686
5687                    function deepCloneOrReuseNodes<T extends Node>(nodes: NodeArray<T>, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
5688                    function deepCloneOrReuseNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined;
5689                    function deepCloneOrReuseNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined {
5690                        if (nodes && nodes.length === 0) {
5691                            // Ensure we explicitly make a copy of an empty array; visitNodes will not do this unless the array has elements,
5692                            // which can lead to us reusing the same empty NodeArray more than once within the same AST during type noding.
5693                            return setTextRange(factory.createNodeArray<T>(/*nodes*/ undefined, nodes.hasTrailingComma), nodes);
5694                        }
5695                        return visitNodes(nodes, visitor, test, start, count);
5696                    }
5697                }
5698
5699                function createTypeNodeFromObjectType(type: ObjectType): TypeNode {
5700                    if (isGenericMappedType(type) || (type as MappedType).containsError) {
5701                        return createMappedTypeNodeFromType(type as MappedType);
5702                    }
5703
5704                    const resolved = resolveStructuredTypeMembers(type);
5705                    if (!resolved.properties.length && !resolved.indexInfos.length) {
5706                        if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
5707                            context.approximateLength += 2;
5708                            return setEmitFlags(factory.createTypeLiteralNode(/*members*/ undefined), EmitFlags.SingleLine);
5709                        }
5710
5711                        if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
5712                            const signature = resolved.callSignatures[0];
5713                            const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType, context) as FunctionTypeNode;
5714                            return signatureNode;
5715
5716                        }
5717
5718                        if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) {
5719                            const signature = resolved.constructSignatures[0];
5720                            const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType, context) as ConstructorTypeNode;
5721                            return signatureNode;
5722                        }
5723                    }
5724
5725                    const abstractSignatures = filter(resolved.constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract));
5726                    if (some(abstractSignatures)) {
5727                        const types = map(abstractSignatures, getOrCreateTypeFromSignature);
5728                        // count the number of type elements excluding abstract constructors
5729                        const typeElementCount =
5730                            resolved.callSignatures.length +
5731                            (resolved.constructSignatures.length - abstractSignatures.length) +
5732                            resolved.indexInfos.length +
5733                            // exclude `prototype` when writing a class expression as a type literal, as per
5734                            // the logic in `createTypeNodesFromResolvedType`.
5735                            (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral ?
5736                                countWhere(resolved.properties, p => !(p.flags & SymbolFlags.Prototype)) :
5737                                length(resolved.properties));
5738                        // don't include an empty object literal if there were no other static-side
5739                        // properties to write, i.e. `abstract class C { }` becomes `abstract new () => {}`
5740                        // and not `(abstract new () => {}) & {}`
5741                        if (typeElementCount) {
5742                            // create a copy of the object type without any abstract construct signatures.
5743                            types.push(getResolvedTypeWithoutAbstractConstructSignatures(resolved));
5744                        }
5745                        return typeToTypeNodeHelper(getIntersectionType(types), context);
5746                    }
5747
5748                    const savedFlags = context.flags;
5749                    context.flags |= NodeBuilderFlags.InObjectTypeLiteral;
5750                    const members = createTypeNodesFromResolvedType(resolved);
5751                    context.flags = savedFlags;
5752                    const typeLiteralNode = factory.createTypeLiteralNode(members);
5753                    context.approximateLength += 2;
5754                    setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine);
5755                    return typeLiteralNode;
5756                }
5757
5758                function typeReferenceToTypeNode(type: TypeReference) {
5759                    let typeArguments: readonly Type[] = getTypeArguments(type);
5760                    if (type.target === globalArrayType || type.target === globalReadonlyArrayType) {
5761                        if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) {
5762                            const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context);
5763                            return factory.createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]);
5764                        }
5765                        const elementType = typeToTypeNodeHelper(typeArguments[0], context);
5766                        const arrayType = factory.createArrayTypeNode(elementType);
5767                        return type.target === globalArrayType ? arrayType : factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType);
5768                    }
5769                    else if (type.target.objectFlags & ObjectFlags.Tuple) {
5770                        typeArguments = sameMap(typeArguments, (t, i) => removeMissingType(t, !!((type.target as TupleType).elementFlags[i] & ElementFlags.Optional)));
5771                        if (typeArguments.length > 0) {
5772                            const arity = getTypeReferenceArity(type);
5773                            const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
5774                            if (tupleConstituentNodes) {
5775                                if ((type.target as TupleType).labeledElementDeclarations) {
5776                                    for (let i = 0; i < tupleConstituentNodes.length; i++) {
5777                                        const flags = (type.target as TupleType).elementFlags[i];
5778                                        tupleConstituentNodes[i] = factory.createNamedTupleMember(
5779                                            flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined,
5780                                            factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))),
5781                                            flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
5782                                            flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) :
5783                                            tupleConstituentNodes[i]
5784                                        );
5785                                    }
5786                                }
5787                                else {
5788                                    for (let i = 0; i < Math.min(arity, tupleConstituentNodes.length); i++) {
5789                                        const flags = (type.target as TupleType).elementFlags[i];
5790                                        tupleConstituentNodes[i] =
5791                                            flags & ElementFlags.Variable ? factory.createRestTypeNode(flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) :
5792                                            flags & ElementFlags.Optional ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) :
5793                                            tupleConstituentNodes[i];
5794                                    }
5795                                }
5796                                const tupleTypeNode = setEmitFlags(factory.createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine);
5797                                return (type.target as TupleType).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode;
5798                            }
5799                        }
5800                        if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) {
5801                            const tupleTypeNode = setEmitFlags(factory.createTupleTypeNode([]), EmitFlags.SingleLine);
5802                            return (type.target as TupleType).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode;
5803                        }
5804                        context.encounteredError = true;
5805                        return undefined!; // TODO: GH#18217
5806                    }
5807                    else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral &&
5808                        type.symbol.valueDeclaration &&
5809                        isClassLike(type.symbol.valueDeclaration) &&
5810                        !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)
5811                    ) {
5812                        return createAnonymousTypeNode(type);
5813                    }
5814                    else {
5815                        const outerTypeParameters = type.target.outerTypeParameters;
5816                        let i = 0;
5817                        let resultType: TypeReferenceNode | ImportTypeNode | undefined;
5818                        if (outerTypeParameters) {
5819                            const length = outerTypeParameters.length;
5820                            while (i < length) {
5821                                // Find group of type arguments for type parameters with the same declaring container.
5822                                const start = i;
5823                                const parent = getParentSymbolOfTypeParameter(outerTypeParameters[i])!;
5824                                do {
5825                                    i++;
5826                                } while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent);
5827                                // When type parameters are their own type arguments for the whole group (i.e. we have
5828                                // the default outer type arguments), we don't show the group.
5829                                if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) {
5830                                    const typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context);
5831                                    const flags = context.flags;
5832                                    context.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences;
5833                                    const ref = symbolToTypeNode(parent, context, SymbolFlags.Type, typeArgumentSlice) as TypeReferenceNode | ImportTypeNode;
5834                                    context.flags = flags;
5835                                    resultType = !resultType ? ref : appendReferenceToType(resultType, ref as TypeReferenceNode);
5836                                }
5837                            }
5838                        }
5839                        let typeArgumentNodes: readonly TypeNode[] | undefined;
5840                        if (typeArguments.length > 0) {
5841                            const typeParameterCount = (type.target.typeParameters || emptyArray).length;
5842                            typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context);
5843                        }
5844                        const flags = context.flags;
5845                        context.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences;
5846                        const finalRef = symbolToTypeNode(type.symbol, context, SymbolFlags.Type, typeArgumentNodes);
5847                        context.flags = flags;
5848                        return !resultType ? finalRef : appendReferenceToType(resultType, finalRef as TypeReferenceNode);
5849                    }
5850                }
5851
5852
5853                function appendReferenceToType(root: TypeReferenceNode | ImportTypeNode, ref: TypeReferenceNode): TypeReferenceNode | ImportTypeNode {
5854                    if (isImportTypeNode(root)) {
5855                        // first shift type arguments
5856                        let typeArguments = root.typeArguments;
5857                        let qualifier = root.qualifier;
5858                        if (qualifier) {
5859                            if (isIdentifier(qualifier)) {
5860                                qualifier = factory.updateIdentifier(qualifier, typeArguments);
5861                            }
5862                            else {
5863                                qualifier = factory.updateQualifiedName(qualifier,
5864                                    qualifier.left,
5865                                    factory.updateIdentifier(qualifier.right, typeArguments));
5866                            }
5867                        }
5868                        typeArguments = ref.typeArguments;
5869                        // then move qualifiers
5870                        const ids = getAccessStack(ref);
5871                        for (const id of ids) {
5872                            qualifier = qualifier ? factory.createQualifiedName(qualifier, id) : id;
5873                        }
5874                        return factory.updateImportTypeNode(
5875                            root,
5876                            root.argument,
5877                            root.assertions,
5878                            qualifier,
5879                            typeArguments,
5880                            root.isTypeOf);
5881                    }
5882                    else {
5883                        // first shift type arguments
5884                        let typeArguments = root.typeArguments;
5885                        let typeName = root.typeName;
5886                        if (isIdentifier(typeName)) {
5887                            typeName = factory.updateIdentifier(typeName, typeArguments);
5888                        }
5889                        else {
5890                            typeName = factory.updateQualifiedName(typeName,
5891                                typeName.left,
5892                                factory.updateIdentifier(typeName.right, typeArguments));
5893                        }
5894                        typeArguments = ref.typeArguments;
5895                        // then move qualifiers
5896                        const ids = getAccessStack(ref);
5897                        for (const id of ids) {
5898                            typeName = factory.createQualifiedName(typeName, id);
5899                        }
5900                        return factory.updateTypeReferenceNode(
5901                            root,
5902                            typeName,
5903                            typeArguments);
5904                    }
5905                }
5906
5907                function getAccessStack(ref: TypeReferenceNode): Identifier[] {
5908                    let state = ref.typeName;
5909                    const ids = [];
5910                    while (!isIdentifier(state)) {
5911                        ids.unshift(state.right);
5912                        state = state.left;
5913                    }
5914                    ids.unshift(state);
5915                    return ids;
5916                }
5917
5918                function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] | undefined {
5919                    if (checkTruncationLength(context)) {
5920                        return [factory.createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined)];
5921                    }
5922                    const typeElements: TypeElement[] = [];
5923                    for (const signature of resolvedType.callSignatures) {
5924                        typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context) as CallSignatureDeclaration);
5925                    }
5926                    for (const signature of resolvedType.constructSignatures) {
5927                        if (signature.flags & SignatureFlags.Abstract) continue;
5928                        typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature, context) as ConstructSignatureDeclaration);
5929                    }
5930                    for (const info of resolvedType.indexInfos) {
5931                        typeElements.push(indexInfoToIndexSignatureDeclarationHelper(info, context, resolvedType.objectFlags & ObjectFlags.ReverseMapped ? createElidedInformationPlaceholder(context) : undefined));
5932                    }
5933
5934                    const properties = resolvedType.properties;
5935                    if (!properties) {
5936                        return typeElements;
5937                    }
5938
5939                    let i = 0;
5940                    for (const propertySymbol of properties) {
5941                        i++;
5942                        if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) {
5943                            if (propertySymbol.flags & SymbolFlags.Prototype) {
5944                                continue;
5945                            }
5946                            if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) {
5947                                context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName));
5948                            }
5949                        }
5950                        if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) {
5951                            typeElements.push(factory.createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined));
5952                            addPropertyToElementList(properties[properties.length - 1], context, typeElements);
5953                            break;
5954                        }
5955                        addPropertyToElementList(propertySymbol, context, typeElements);
5956
5957                    }
5958                    return typeElements.length ? typeElements : undefined;
5959                }
5960            }
5961
5962            function createElidedInformationPlaceholder(context: NodeBuilderContext) {
5963                context.approximateLength += 3;
5964                if (!(context.flags & NodeBuilderFlags.NoTruncation)) {
5965                    return factory.createTypeReferenceNode(factory.createIdentifier("..."), /*typeArguments*/ undefined);
5966                }
5967                return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
5968            }
5969
5970            function shouldUsePlaceholderForProperty(propertySymbol: Symbol, context: NodeBuilderContext) {
5971                // Use placeholders for reverse mapped types we've either already descended into, or which
5972                // are nested reverse mappings within a mapping over a non-anonymous type. The later is a restriction mostly just to
5973                // reduce the blowup in printback size from doing, eg, a deep reverse mapping over `Window`.
5974                // Since anonymous types usually come from expressions, this allows us to preserve the output
5975                // for deep mappings which likely come from expressions, while truncating those parts which
5976                // come from mappings over library functions.
5977                return !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped)
5978                    && (
5979                        contains(context.reverseMappedStack, propertySymbol as ReverseMappedSymbol)
5980                        || (
5981                            context.reverseMappedStack?.[0]
5982                            && !(getObjectFlags(last(context.reverseMappedStack).propertyType) & ObjectFlags.Anonymous)
5983                        )
5984                    );
5985            }
5986
5987            function addPropertyToElementList(propertySymbol: Symbol, context: NodeBuilderContext, typeElements: TypeElement[]) {
5988                const propertyIsReverseMapped = !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped);
5989                const propertyType = shouldUsePlaceholderForProperty(propertySymbol, context) ?
5990                    anyType : getNonMissingTypeOfSymbol(propertySymbol);
5991                const saveEnclosingDeclaration = context.enclosingDeclaration;
5992                context.enclosingDeclaration = undefined;
5993                if (context.tracker.trackSymbol && isLateBoundName(propertySymbol.escapedName)) {
5994                    if (propertySymbol.declarations) {
5995                        const decl = first(propertySymbol.declarations);
5996                        if (hasLateBindableName(decl)) {
5997                            if (isBinaryExpression(decl)) {
5998                                const name = getNameOfDeclaration(decl);
5999                                if (name && isElementAccessExpression(name) && isPropertyAccessEntityNameExpression(name.argumentExpression)) {
6000                                    trackComputedName(name.argumentExpression, saveEnclosingDeclaration, context);
6001                                }
6002                            }
6003                            else {
6004                                trackComputedName(decl.name.expression, saveEnclosingDeclaration, context);
6005                            }
6006                        }
6007                    }
6008                    else if (context.tracker?.reportNonSerializableProperty) {
6009                        context.tracker.reportNonSerializableProperty(symbolToString(propertySymbol));
6010                    }
6011                }
6012                context.enclosingDeclaration = propertySymbol.valueDeclaration || propertySymbol.declarations?.[0] || saveEnclosingDeclaration;
6013                const propertyName = getPropertyNameNodeForSymbol(propertySymbol, context);
6014                context.enclosingDeclaration = saveEnclosingDeclaration;
6015                context.approximateLength += (symbolName(propertySymbol).length + 1);
6016                const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined;
6017                if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length && !isReadonlySymbol(propertySymbol)) {
6018                    const signatures = getSignaturesOfType(filterType(propertyType, t => !(t.flags & TypeFlags.Undefined)), SignatureKind.Call);
6019                    for (const signature of signatures) {
6020                        const methodDeclaration = signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context, { name: propertyName, questionToken: optionalToken }) as MethodSignature;
6021                        typeElements.push(preserveCommentsOn(methodDeclaration));
6022                    }
6023                }
6024                else {
6025                    let propertyTypeNode: TypeNode;
6026                    if (shouldUsePlaceholderForProperty(propertySymbol, context)) {
6027                        propertyTypeNode = createElidedInformationPlaceholder(context);
6028                    }
6029                    else {
6030                        if (propertyIsReverseMapped) {
6031                            context.reverseMappedStack ||= [];
6032                            context.reverseMappedStack.push(propertySymbol as ReverseMappedSymbol);
6033                        }
6034                        propertyTypeNode = propertyType ? serializeTypeForDeclaration(context, propertyType, propertySymbol, saveEnclosingDeclaration) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
6035                        if (propertyIsReverseMapped) {
6036                            context.reverseMappedStack!.pop();
6037                        }
6038                    }
6039
6040                    const modifiers = isReadonlySymbol(propertySymbol) ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined;
6041                    if (modifiers) {
6042                        context.approximateLength += 9;
6043                    }
6044                    const propertySignature = factory.createPropertySignature(
6045                        modifiers,
6046                        propertyName,
6047                        optionalToken,
6048                        propertyTypeNode);
6049
6050                    typeElements.push(preserveCommentsOn(propertySignature));
6051                }
6052
6053                function preserveCommentsOn<T extends Node>(node: T) {
6054                    if (some(propertySymbol.declarations, d => d.kind === SyntaxKind.JSDocPropertyTag)) {
6055                        const d = propertySymbol.declarations?.find(d => d.kind === SyntaxKind.JSDocPropertyTag)! as JSDocPropertyTag;
6056                        const commentText = getTextOfJSDocComment(d.comment);
6057                        if (commentText) {
6058                            setSyntheticLeadingComments(node, [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]);
6059                        }
6060                    }
6061                    else if (propertySymbol.valueDeclaration) {
6062                        // Copy comments to node for declaration emit
6063                        setCommentRange(node, propertySymbol.valueDeclaration);
6064                    }
6065                    return node;
6066                }
6067            }
6068
6069            function mapToTypeNodes(types: readonly Type[] | undefined, context: NodeBuilderContext, isBareList?: boolean): TypeNode[] | undefined {
6070                if (some(types)) {
6071                    if (checkTruncationLength(context)) {
6072                        if (!isBareList) {
6073                            return [factory.createTypeReferenceNode("...", /*typeArguments*/ undefined)];
6074                        }
6075                        else if (types.length > 2) {
6076                            return [
6077                                typeToTypeNodeHelper(types[0], context),
6078                                factory.createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined),
6079                                typeToTypeNodeHelper(types[types.length - 1], context)
6080                            ];
6081                        }
6082                    }
6083                    const mayHaveNameCollisions = !(context.flags & NodeBuilderFlags.UseFullyQualifiedType);
6084                    /** Map from type reference identifier text to [type, index in `result` where the type node is] */
6085                    const seenNames = mayHaveNameCollisions ? createUnderscoreEscapedMultiMap<[Type, number]>() : undefined;
6086                    const result: TypeNode[] = [];
6087                    let i = 0;
6088                    for (const type of types) {
6089                        i++;
6090                        if (checkTruncationLength(context) && (i + 2 < types.length - 1)) {
6091                            result.push(factory.createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined));
6092                            const typeNode = typeToTypeNodeHelper(types[types.length - 1], context);
6093                            if (typeNode) {
6094                                result.push(typeNode);
6095                            }
6096                            break;
6097                        }
6098                        context.approximateLength += 2; // Account for whitespace + separator
6099                        const typeNode = typeToTypeNodeHelper(type, context);
6100                        if (typeNode) {
6101                            result.push(typeNode);
6102                            if (seenNames && isIdentifierTypeReference(typeNode)) {
6103                                seenNames.add(typeNode.typeName.escapedText, [type, result.length - 1]);
6104                            }
6105                        }
6106                    }
6107
6108                    if (seenNames) {
6109                        // To avoid printing types like `[Foo, Foo]` or `Bar & Bar` where
6110                        // occurrences of the same name actually come from different
6111                        // namespaces, go through the single-identifier type reference nodes
6112                        // we just generated, and see if any names were generated more than
6113                        // once while referring to different types. If so, regenerate the
6114                        // type node for each entry by that name with the
6115                        // `UseFullyQualifiedType` flag enabled.
6116                        const saveContextFlags = context.flags;
6117                        context.flags |= NodeBuilderFlags.UseFullyQualifiedType;
6118                        seenNames.forEach(types => {
6119                            if (!arrayIsHomogeneous(types, ([a], [b]) => typesAreSameReference(a, b))) {
6120                                for (const [type, resultIndex] of types) {
6121                                    result[resultIndex] = typeToTypeNodeHelper(type, context);
6122                                }
6123                            }
6124                        });
6125                        context.flags = saveContextFlags;
6126                    }
6127
6128                    return result;
6129                }
6130            }
6131
6132            function typesAreSameReference(a: Type, b: Type): boolean {
6133                return a === b
6134                    || !!a.symbol && a.symbol === b.symbol
6135                    || !!a.aliasSymbol && a.aliasSymbol === b.aliasSymbol;
6136            }
6137
6138            function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, context: NodeBuilderContext, typeNode: TypeNode | undefined): IndexSignatureDeclaration {
6139                const name = getNameFromIndexInfo(indexInfo) || "x";
6140                const indexerTypeNode = typeToTypeNodeHelper(indexInfo.keyType, context);
6141
6142                const indexingParameter = factory.createParameterDeclaration(
6143                    /*modifiers*/ undefined,
6144                    /*dotDotDotToken*/ undefined,
6145                    name,
6146                    /*questionToken*/ undefined,
6147                    indexerTypeNode,
6148                    /*initializer*/ undefined);
6149                if (!typeNode) {
6150                    typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context);
6151                }
6152                if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) {
6153                    context.encounteredError = true;
6154                }
6155                context.approximateLength += (name.length + 4);
6156                return factory.createIndexSignature(
6157                    indexInfo.isReadonly ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined,
6158                    [indexingParameter],
6159                    typeNode);
6160            }
6161
6162            interface SignatureToSignatureDeclarationOptions {
6163                modifiers?: readonly Modifier[];
6164                name?: PropertyName;
6165                questionToken?: QuestionToken;
6166                privateSymbolVisitor?: (s: Symbol) => void;
6167                bundledImports?: boolean;
6168            }
6169
6170            function signatureToSignatureDeclarationHelper(signature: Signature, kind: SignatureDeclaration["kind"], context: NodeBuilderContext, options?: SignatureToSignatureDeclarationOptions): SignatureDeclaration {
6171                const suppressAny = context.flags & NodeBuilderFlags.SuppressAnyReturnType;
6172                if (suppressAny) context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s
6173                context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum
6174                let typeParameters: TypeParameterDeclaration[] | undefined;
6175                let typeArguments: TypeNode[] | undefined;
6176                if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) {
6177                    typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context));
6178                }
6179                else {
6180                    typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context));
6181                }
6182
6183                const expandedParams = getExpandedParameters(signature, /*skipUnionExpanding*/ true)[0];
6184                // If the expanded parameter list had a variadic in a non-trailing position, don't expand it
6185                const parameters = (some(expandedParams, p => p !== expandedParams[expandedParams.length - 1] && !!(getCheckFlags(p) & CheckFlags.RestParameter)) ? signature.parameters : expandedParams).map(parameter => symbolToParameterDeclaration(parameter, context, kind === SyntaxKind.Constructor, options?.privateSymbolVisitor, options?.bundledImports));
6186                const thisParameter = context.flags & NodeBuilderFlags.OmitThisParameter ? undefined : tryGetThisParameterDeclaration(signature, context);
6187                if (thisParameter) {
6188                    parameters.unshift(thisParameter);
6189                }
6190
6191                let returnTypeNode: TypeNode | undefined;
6192                const typePredicate = getTypePredicateOfSignature(signature);
6193                if (typePredicate) {
6194                    const assertsModifier = typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ?
6195                        factory.createToken(SyntaxKind.AssertsKeyword) :
6196                        undefined;
6197                    const parameterName = typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ?
6198                        setEmitFlags(factory.createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) :
6199                        factory.createThisTypeNode();
6200                    const typeNode = typePredicate.type && typeToTypeNodeHelper(typePredicate.type, context);
6201                    returnTypeNode = factory.createTypePredicateNode(assertsModifier, parameterName, typeNode);
6202                }
6203                else {
6204                    const returnType = getReturnTypeOfSignature(signature);
6205                    if (returnType && !(suppressAny && isTypeAny(returnType))) {
6206                        returnTypeNode = serializeReturnTypeForSignature(context, returnType, signature, options?.privateSymbolVisitor, options?.bundledImports);
6207                    }
6208                    else if (!suppressAny) {
6209                        returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
6210                    }
6211                }
6212                let modifiers = options?.modifiers;
6213                if ((kind === SyntaxKind.ConstructorType) && signature.flags & SignatureFlags.Abstract) {
6214                    const flags = modifiersToFlags(modifiers);
6215                    modifiers = factory.createModifiersFromModifierFlags(flags | ModifierFlags.Abstract);
6216                }
6217
6218                const node =
6219                    kind === SyntaxKind.CallSignature ? factory.createCallSignature(typeParameters, parameters, returnTypeNode) :
6220                    kind === SyntaxKind.ConstructSignature ? factory.createConstructSignature(typeParameters, parameters, returnTypeNode) :
6221                    kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) :
6222                    kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
6223                    kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(modifiers, parameters, /*body*/ undefined) :
6224                    kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) :
6225                    kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) :
6226                    kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(modifiers, parameters, returnTypeNode) :
6227                    kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) :
6228                    kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
6229                    kind === SyntaxKind.ConstructorType ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
6230                    kind === SyntaxKind.FunctionDeclaration ? factory.createFunctionDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
6231                    kind === SyntaxKind.FunctionExpression ? factory.createFunctionExpression(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, factory.createBlock([])) :
6232                    kind === SyntaxKind.ArrowFunction ? factory.createArrowFunction(modifiers, typeParameters, parameters, returnTypeNode, /*equalsGreaterThanToken*/ undefined, factory.createBlock([])) :
6233                    Debug.assertNever(kind);
6234
6235                if (typeArguments) {
6236                    node.typeArguments = factory.createNodeArray(typeArguments);
6237                }
6238
6239                return node;
6240            }
6241
6242            function tryGetThisParameterDeclaration(signature: Signature, context: NodeBuilderContext) {
6243                if (signature.thisParameter) {
6244                    return symbolToParameterDeclaration(signature.thisParameter, context);
6245                }
6246                if (signature.declaration) {
6247                    const thisTag = getJSDocThisTag(signature.declaration);
6248                    if (thisTag && thisTag.typeExpression) {
6249                        return factory.createParameterDeclaration(
6250                            /* modifiers */ undefined,
6251                            /* dotDotDotToken */ undefined,
6252                            "this",
6253                            /* questionToken */ undefined,
6254                            typeToTypeNodeHelper(getTypeFromTypeNode(thisTag.typeExpression), context)
6255                        );
6256                    }
6257                }
6258            }
6259
6260            function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration {
6261                const savedContextFlags = context.flags;
6262                context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic
6263                const modifiers = factory.createModifiersFromModifierFlags(getVarianceModifiers(type));
6264                const name = typeParameterToName(type, context);
6265                const defaultParameter = getDefaultFromTypeParameter(type);
6266                const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context);
6267                context.flags = savedContextFlags;
6268                return factory.createTypeParameterDeclaration(modifiers, name, constraintNode, defaultParameterNode);
6269            }
6270
6271            function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintOfTypeParameter(type)): TypeParameterDeclaration {
6272                const constraintNode = constraint && typeToTypeNodeHelper(constraint, context);
6273                return typeParameterToDeclarationWithConstraint(type, context, constraintNode);
6274            }
6275
6276            function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean, privateSymbolVisitor?: (s: Symbol) => void, bundledImports?: boolean): ParameterDeclaration {
6277                let parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
6278                if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) {
6279                    parameterDeclaration = getDeclarationOfKind<JSDocParameterTag>(parameterSymbol, SyntaxKind.JSDocParameterTag);
6280                }
6281
6282                let parameterType = getTypeOfSymbol(parameterSymbol);
6283                if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) {
6284                    parameterType = getOptionalType(parameterType);
6285                }
6286                const parameterTypeNode = serializeTypeForDeclaration(context, parameterType, parameterSymbol, context.enclosingDeclaration, privateSymbolVisitor, bundledImports);
6287
6288                const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && canHaveModifiers(parameterDeclaration) ? map(getModifiers(parameterDeclaration), factory.cloneNode) : undefined;
6289                const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter;
6290                const dotDotDotToken = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined;
6291                const name = parameterDeclaration ? parameterDeclaration.name ?
6292                    parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
6293                    parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) :
6294                    cloneBindingName(parameterDeclaration.name) :
6295                    symbolName(parameterSymbol) :
6296                    symbolName(parameterSymbol);
6297                const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.OptionalParameter;
6298                const questionToken = isOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined;
6299                const parameterNode = factory.createParameterDeclaration(
6300                    modifiers,
6301                    dotDotDotToken,
6302                    name,
6303                    questionToken,
6304                    parameterTypeNode,
6305                    /*initializer*/ undefined);
6306                context.approximateLength += symbolName(parameterSymbol).length + 3;
6307                return parameterNode;
6308
6309                function cloneBindingName(node: BindingName): BindingName {
6310                    return elideInitializerAndSetEmitFlags(node) as BindingName;
6311                    function elideInitializerAndSetEmitFlags(node: Node): Node {
6312                        if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
6313                            trackComputedName(node.expression, context.enclosingDeclaration, context);
6314                        }
6315                        let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!;
6316                        if (isBindingElement(visited)) {
6317                            visited = factory.updateBindingElement(
6318                                visited,
6319                                visited.dotDotDotToken,
6320                                visited.propertyName,
6321                                visited.name,
6322                                /*initializer*/ undefined);
6323                        }
6324                        if (!nodeIsSynthesized(visited)) {
6325                            visited = factory.cloneNode(visited);
6326                        }
6327                        return setEmitFlags(visited, EmitFlags.SingleLine | EmitFlags.NoAsciiEscaping);
6328                    }
6329                }
6330            }
6331
6332            function trackComputedName(accessExpression: EntityNameOrEntityNameExpression, enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
6333                if (!context.tracker.trackSymbol) return;
6334                // get symbol of the first identifier of the entityName
6335                const firstIdentifier = getFirstIdentifier(accessExpression);
6336                const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
6337                if (name) {
6338                    context.tracker.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value);
6339                }
6340            }
6341
6342            function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) {
6343                context.tracker.trackSymbol!(symbol, context.enclosingDeclaration, meaning); // TODO: GH#18217
6344                return lookupSymbolChainWorker(symbol, context, meaning, yieldModuleSymbol);
6345            }
6346
6347            function lookupSymbolChainWorker(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) {
6348                // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration.
6349                let chain: Symbol[];
6350                const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter;
6351                if (!isTypeParameter && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType) && !(context.flags & NodeBuilderFlags.DoNotIncludeSymbolChain)) {
6352                    chain = Debug.checkDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true));
6353                    Debug.assert(chain && chain.length > 0);
6354                }
6355                else {
6356                    chain = [symbol];
6357                }
6358                return chain;
6359
6360                /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */
6361                function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined {
6362                    let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing));
6363                    let parentSpecifiers: (string | undefined)[];
6364                    if (!accessibleSymbolChain ||
6365                        needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
6366
6367                        // Go up and add our parent.
6368                        const parents = getContainersOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol, context.enclosingDeclaration, meaning);
6369                        if (length(parents)) {
6370                            parentSpecifiers = parents!.map(symbol =>
6371                                some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)
6372                                    ? getSpecifierForModuleSymbol(symbol, context)
6373                                    : undefined);
6374                            const indices = parents!.map((_, i) => i);
6375                            indices.sort(sortByBestName);
6376                            const sortedParents = indices.map(i => parents![i]);
6377                            for (const parent of sortedParents) {
6378                                const parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false);
6379                                if (parentChain) {
6380                                    if (parent.exports && parent.exports.get(InternalSymbolName.ExportEquals) &&
6381                                        getSymbolIfSameReference(parent.exports.get(InternalSymbolName.ExportEquals)!, symbol)) {
6382                                        // parentChain root _is_ symbol - symbol is a module export=, so it kinda looks like it's own parent
6383                                        // No need to lookup an alias for the symbol in itself
6384                                        accessibleSymbolChain = parentChain;
6385                                        break;
6386                                    }
6387                                    accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [getAliasForSymbolInContainer(parent, symbol) || symbol]);
6388                                    break;
6389                                }
6390                            }
6391                        }
6392                    }
6393
6394                    if (accessibleSymbolChain) {
6395                        return accessibleSymbolChain;
6396                    }
6397                    if (
6398                        // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols.
6399                        endOfChain ||
6400                        // If a parent symbol is an anonymous type, don't write it.
6401                        !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral))) {
6402                        // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.)
6403                        if (!endOfChain && !yieldModuleSymbol && !!forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) {
6404                            return;
6405                        }
6406                        return [symbol];
6407                    }
6408
6409                    function sortByBestName(a: number, b: number) {
6410                        const specifierA = parentSpecifiers[a];
6411                        const specifierB = parentSpecifiers[b];
6412                        if (specifierA && specifierB) {
6413                            const isBRelative = pathIsRelative(specifierB);
6414                            if (pathIsRelative(specifierA) === isBRelative) {
6415                                // Both relative or both non-relative, sort by number of parts
6416                                return moduleSpecifiers.countPathComponents(specifierA) - moduleSpecifiers.countPathComponents(specifierB);
6417                            }
6418                            if (isBRelative) {
6419                                // A is non-relative, B is relative: prefer A
6420                                return -1;
6421                            }
6422                            // A is relative, B is non-relative: prefer B
6423                            return 1;
6424                        }
6425                        return 0;
6426                    }
6427                }
6428            }
6429
6430            function typeParametersToTypeParameterDeclarations(symbol: Symbol, context: NodeBuilderContext) {
6431                let typeParameterNodes: NodeArray<TypeParameterDeclaration> | undefined;
6432                const targetSymbol = getTargetSymbol(symbol);
6433                if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) {
6434                    typeParameterNodes = factory.createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context)));
6435                }
6436                return typeParameterNodes;
6437            }
6438
6439            function lookupTypeParameterNodes(chain: Symbol[], index: number, context: NodeBuilderContext) {
6440                Debug.assert(chain && 0 <= index && index < chain.length);
6441                const symbol = chain[index];
6442                const symbolId = getSymbolId(symbol);
6443                if (context.typeParameterSymbolList?.has(symbolId)) {
6444                    return undefined;
6445                }
6446                (context.typeParameterSymbolList || (context.typeParameterSymbolList = new Set())).add(symbolId);
6447                let typeParameterNodes: readonly TypeNode[] | readonly TypeParameterDeclaration[] | undefined;
6448                if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) {
6449                    const parentSymbol = symbol;
6450                    const nextSymbol = chain[index + 1];
6451                    if (getCheckFlags(nextSymbol) & CheckFlags.Instantiated) {
6452                        const params = getTypeParametersOfClassOrInterface(
6453                            parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol
6454                        );
6455                        typeParameterNodes = mapToTypeNodes(map(params, t => getMappedType(t, (nextSymbol as TransientSymbol).mapper!)), context);
6456                    }
6457                    else {
6458                        typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context);
6459                    }
6460                }
6461                return typeParameterNodes;
6462            }
6463
6464            /**
6465             * Given A[B][C][D], finds A[B]
6466             */
6467            function getTopmostIndexedAccessType(top: IndexedAccessTypeNode): IndexedAccessTypeNode {
6468                if (isIndexedAccessTypeNode(top.objectType)) {
6469                    return getTopmostIndexedAccessType(top.objectType);
6470                }
6471                return top;
6472            }
6473
6474            function getSpecifierForModuleSymbol(symbol: Symbol, context: NodeBuilderContext, overrideImportMode?: SourceFile["impliedNodeFormat"]) {
6475                let file = getDeclarationOfKind<SourceFile>(symbol, SyntaxKind.SourceFile);
6476                if (!file) {
6477                    const equivalentFileSymbol = firstDefined(symbol.declarations, d => getFileSymbolIfFileSymbolExportEqualsContainer(d, symbol));
6478                    if (equivalentFileSymbol) {
6479                        file = getDeclarationOfKind<SourceFile>(equivalentFileSymbol, SyntaxKind.SourceFile);
6480                    }
6481                }
6482                if (file && file.moduleName !== undefined) {
6483                    // Use the amd name if it is available
6484                    return file.moduleName;
6485                }
6486                if (!file) {
6487                    if (context.tracker.trackReferencedAmbientModule) {
6488                        const ambientDecls = filter(symbol.declarations, isAmbientModule);
6489                        if (length(ambientDecls)) {
6490                            for (const decl of ambientDecls!) {
6491                                context.tracker.trackReferencedAmbientModule(decl, symbol);
6492                            }
6493                        }
6494                    }
6495                    if (ambientModuleSymbolRegex.test(symbol.escapedName as string)) {
6496                        return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
6497                    }
6498                }
6499                if (!context.enclosingDeclaration || !context.tracker.moduleResolverHost) {
6500                    // If there's no context declaration, we can't lookup a non-ambient specifier, so we just use the symbol name
6501                    if (ambientModuleSymbolRegex.test(symbol.escapedName as string)) {
6502                        return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1);
6503                    }
6504                    return getSourceFileOfNode(getNonAugmentationDeclaration(symbol)!).fileName; // A resolver may not be provided for baselines and errors - in those cases we use the fileName in full
6505                }
6506                const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration));
6507                const resolutionMode = overrideImportMode || contextFile?.impliedNodeFormat;
6508                const cacheKey = getSpecifierCacheKey(contextFile.path, resolutionMode);
6509                const links = getSymbolLinks(symbol);
6510                let specifier = links.specifierCache && links.specifierCache.get(cacheKey);
6511                if (!specifier) {
6512                    const isBundle = !!outFile(compilerOptions);
6513                    // For declaration bundles, we need to generate absolute paths relative to the common source dir for imports,
6514                    // just like how the declaration emitter does for the ambient module declarations - we can easily accomplish this
6515                    // using the `baseUrl` compiler option (which we would otherwise never use in declaration emit) and a non-relative
6516                    // specifier preference
6517                    const { moduleResolverHost } = context.tracker;
6518                    const specifierCompilerOptions = isBundle ? { ...compilerOptions, baseUrl: moduleResolverHost.getCommonSourceDirectory() } : compilerOptions;
6519                    specifier = first(moduleSpecifiers.getModuleSpecifiers(
6520                        symbol,
6521                        checker,
6522                        specifierCompilerOptions,
6523                        contextFile,
6524                        moduleResolverHost,
6525                        {
6526                            importModuleSpecifierPreference: isBundle ? "non-relative" : "project-relative",
6527                            importModuleSpecifierEnding: isBundle ? "minimal"
6528                                : resolutionMode === ModuleKind.ESNext ? "js"
6529                                : undefined,
6530                        },
6531                        { overrideImportMode }
6532                    ));
6533                    links.specifierCache ??= new Map();
6534                    links.specifierCache.set(cacheKey, specifier);
6535                }
6536                return specifier;
6537
6538                function getSpecifierCacheKey(path: string, mode: SourceFile["impliedNodeFormat"] | undefined) {
6539                    return mode === undefined ? path : `${mode}|${path}`;
6540                }
6541            }
6542
6543            function symbolToEntityNameNode(symbol: Symbol): EntityName {
6544                const identifier = factory.createIdentifier(unescapeLeadingUnderscores(symbol.escapedName));
6545                return symbol.parent ? factory.createQualifiedName(symbolToEntityNameNode(symbol.parent), identifier) : identifier;
6546            }
6547
6548            function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, overrideTypeArguments?: readonly TypeNode[]): TypeNode {
6549                const chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope)); // If we're using aliases outside the current scope, dont bother with the module
6550
6551                const isTypeOf = meaning === SymbolFlags.Value;
6552                if (some(chain[0].declarations, hasNonGlobalAugmentationExternalModuleSymbol)) {
6553                    // module is root, must use `ImportTypeNode`
6554                    const nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined;
6555                    const typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context);
6556                    const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration));
6557                    const targetFile = getSourceFileOfModule(chain[0]);
6558                    let specifier: string | undefined;
6559                    let assertion: ImportTypeAssertionContainer | undefined;
6560                    if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) {
6561                        // An `import` type directed at an esm format file is only going to resolve in esm mode - set the esm mode assertion
6562                        if (targetFile?.impliedNodeFormat === ModuleKind.ESNext && targetFile.impliedNodeFormat !== contextFile?.impliedNodeFormat) {
6563                            specifier = getSpecifierForModuleSymbol(chain[0], context, ModuleKind.ESNext);
6564                            assertion = factory.createImportTypeAssertionContainer(factory.createAssertClause(factory.createNodeArray([
6565                                factory.createAssertEntry(
6566                                    factory.createStringLiteral("resolution-mode"),
6567                                    factory.createStringLiteral("import")
6568                                )
6569                            ])));
6570                            context.tracker.reportImportTypeNodeResolutionModeOverride?.();
6571                        }
6572                    }
6573                    if (!specifier) {
6574                        specifier = getSpecifierForModuleSymbol(chain[0], context);
6575                    }
6576                    if (!(context.flags & NodeBuilderFlags.AllowNodeModulesRelativePaths) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic &&
6577                        (specifier.indexOf("/node_modules/") >= 0 || isOhpmAndOhModules(compilerOptions.packageManagerType, specifier))) {
6578                        const oldSpecifier = specifier;
6579                        if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) {
6580                            // We might be able to write a portable import type using a mode override; try specifier generation again, but with a different mode set
6581                            const swappedMode = contextFile?.impliedNodeFormat === ModuleKind.ESNext ? ModuleKind.CommonJS : ModuleKind.ESNext;
6582                            specifier = getSpecifierForModuleSymbol(chain[0], context, swappedMode);
6583
6584                            if (specifier.indexOf("/node_modules/") >= 0 || isOHModules(specifier)) {
6585                                // Still unreachable :(
6586                                specifier = oldSpecifier;
6587                            }
6588                            else {
6589                                assertion = factory.createImportTypeAssertionContainer(factory.createAssertClause(factory.createNodeArray([
6590                                    factory.createAssertEntry(
6591                                        factory.createStringLiteral("resolution-mode"),
6592                                        factory.createStringLiteral(swappedMode === ModuleKind.ESNext ? "import" : "require")
6593                                    )
6594                                ])));
6595                                context.tracker.reportImportTypeNodeResolutionModeOverride?.();
6596                            }
6597                        }
6598
6599                        if (!assertion) {
6600                            // If ultimately we can only name the symbol with a reference that dives into a `node_modules` folder, we should error
6601                            // since declaration files with these kinds of references are liable to fail when published :(
6602                            context.encounteredError = true;
6603                            if (context.tracker.reportLikelyUnsafeImportRequiredError) {
6604                                context.tracker.reportLikelyUnsafeImportRequiredError(oldSpecifier);
6605                            }
6606                        }
6607                    }
6608                    // Only for Resource type in openharmony SDK
6609                    if (specifier.endsWith('/openharmony/ets/api/global/resource')) {
6610                      const lastSymbol = chain[chain.length - 1];
6611                      // Create typeReferenceNode if is Resource type
6612                      if (lastSymbol.escapedName === 'Resource') {
6613                        const entityName = createAccessFromSymbolChain([lastSymbol], 0, 0);
6614                        if (isIndexedAccessTypeNode(entityName)) {
6615                          return entityName; // Indexed accesses can never be `typeof`
6616                        }
6617                        return factory.createTypeReferenceNode(entityName);
6618                      }
6619                    }
6620                    const lit = factory.createLiteralTypeNode(factory.createStringLiteral(specifier));
6621                    if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]);
6622                    context.approximateLength += specifier.length + 10; // specifier + import("")
6623                    if (!nonRootParts || isEntityName(nonRootParts)) {
6624                        if (nonRootParts) {
6625                            const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right;
6626                            lastId.typeArguments = undefined;
6627                        }
6628                        return factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf);
6629                    }
6630                    else {
6631                        const splitNode = getTopmostIndexedAccessType(nonRootParts);
6632                        const qualifier = (splitNode.objectType as TypeReferenceNode).typeName;
6633                        return factory.createIndexedAccessTypeNode(factory.createImportTypeNode(lit, assertion, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf), splitNode.indexType);
6634                    }
6635                }
6636
6637                const entityName = createAccessFromSymbolChain(chain, chain.length - 1, 0);
6638                if (isIndexedAccessTypeNode(entityName)) {
6639                    return entityName; // Indexed accesses can never be `typeof`
6640                }
6641                if (isTypeOf) {
6642                    return factory.createTypeQueryNode(entityName);
6643                }
6644                else {
6645                    const lastId = isIdentifier(entityName) ? entityName : entityName.right;
6646                    const lastTypeArgs = lastId.typeArguments;
6647                    lastId.typeArguments = undefined;
6648                    return factory.createTypeReferenceNode(entityName, lastTypeArgs as NodeArray<TypeNode>);
6649                }
6650
6651                function createAccessFromSymbolChain(chain: Symbol[], index: number, stopper: number): EntityName | IndexedAccessTypeNode {
6652                    const typeParameterNodes = index === (chain.length - 1) ? overrideTypeArguments : lookupTypeParameterNodes(chain, index, context);
6653                    const symbol = chain[index];
6654                    const parent = chain[index - 1];
6655
6656                    let symbolName: string | undefined;
6657                    if (index === 0) {
6658                        context.flags |= NodeBuilderFlags.InInitialEntityName;
6659                        symbolName = getNameOfSymbolAsWritten(symbol, context);
6660                        context.approximateLength += (symbolName ? symbolName.length : 0) + 1;
6661                        context.flags ^= NodeBuilderFlags.InInitialEntityName;
6662                    }
6663                    else {
6664                        if (parent && getExportsOfSymbol(parent)) {
6665                            const exports = getExportsOfSymbol(parent);
6666                            forEachEntry(exports, (ex, name) => {
6667                                if (getSymbolIfSameReference(ex, symbol) && !isLateBoundName(name) && name !== InternalSymbolName.ExportEquals) {
6668                                    symbolName = unescapeLeadingUnderscores(name);
6669                                    return true;
6670                                }
6671                            });
6672                        }
6673                    }
6674
6675                    if (symbolName === undefined) {
6676                        const name = firstDefined(symbol.declarations, getNameOfDeclaration);
6677                        if (name && isComputedPropertyName(name) && isEntityName(name.expression)) {
6678                            const LHS = createAccessFromSymbolChain(chain, index - 1, stopper);
6679                            if (isEntityName(LHS)) {
6680                                return factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(LHS)), factory.createTypeQueryNode(name.expression));
6681                            }
6682                            return LHS;
6683                        }
6684                        symbolName = getNameOfSymbolAsWritten(symbol, context);
6685                    }
6686                    context.approximateLength += symbolName.length + 1;
6687
6688                    if (!(context.flags & NodeBuilderFlags.ForbidIndexedAccessSymbolReferences) && parent &&
6689                        getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) &&
6690                        getSymbolIfSameReference(getMembersOfSymbol(parent).get(symbol.escapedName)!, symbol)) {
6691                        // Should use an indexed access
6692                        const LHS = createAccessFromSymbolChain(chain, index - 1, stopper);
6693                        if (isIndexedAccessTypeNode(LHS)) {
6694                            return factory.createIndexedAccessTypeNode(LHS, factory.createLiteralTypeNode(factory.createStringLiteral(symbolName)));
6695                        }
6696                        else {
6697                            return factory.createIndexedAccessTypeNode(factory.createTypeReferenceNode(LHS, typeParameterNodes as readonly TypeNode[]), factory.createLiteralTypeNode(factory.createStringLiteral(symbolName)));
6698                        }
6699                    }
6700
6701                    const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
6702                    identifier.symbol = symbol;
6703
6704                    if (index > stopper) {
6705                        const LHS = createAccessFromSymbolChain(chain, index - 1, stopper);
6706                        if (!isEntityName(LHS)) {
6707                            return Debug.fail("Impossible construct - an export of an indexed access cannot be reachable");
6708                        }
6709                        return factory.createQualifiedName(LHS, identifier);
6710                    }
6711                    return identifier;
6712                }
6713            }
6714
6715            function typeParameterShadowsNameInScope(escapedName: __String, context: NodeBuilderContext, type: TypeParameter) {
6716                const result = resolveName(context.enclosingDeclaration, escapedName, SymbolFlags.Type, /*nameNotFoundArg*/ undefined, escapedName, /*isUse*/ false);
6717                if (result) {
6718                    if (result.flags & SymbolFlags.TypeParameter && result === type.symbol) {
6719                        return false;
6720                    }
6721                    return true;
6722                }
6723                return false;
6724            }
6725
6726            function typeParameterToName(type: TypeParameter, context: NodeBuilderContext) {
6727                if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && context.typeParameterNames) {
6728                    const cached = context.typeParameterNames.get(getTypeId(type));
6729                    if (cached) {
6730                        return cached;
6731                    }
6732                }
6733                let result = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true);
6734                if (!(result.kind & SyntaxKind.Identifier)) {
6735                    return factory.createIdentifier("(Missing type parameter)");
6736                }
6737                if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) {
6738                    const rawtext = result.escapedText as string;
6739                    let i = context.typeParameterNamesByTextNextNameCount?.get(rawtext) || 0;
6740                    let text = rawtext;
6741                    while (context.typeParameterNamesByText?.has(text) || typeParameterShadowsNameInScope(text as __String, context, type)) {
6742                        i++;
6743                        text = `${rawtext}_${i}`;
6744                    }
6745                    if (text !== rawtext) {
6746                        result = factory.createIdentifier(text, result.typeArguments);
6747                    }
6748                    // avoiding iterations of the above loop turns out to be worth it when `i` starts to get large, so we cache the max
6749                    // `i` we've used thus far, to save work later
6750                    (context.typeParameterNamesByTextNextNameCount ||= new Map()).set(rawtext, i);
6751                    (context.typeParameterNames ||= new Map()).set(getTypeId(type), result);
6752                    (context.typeParameterNamesByText ||= new Set()).add(rawtext);
6753                }
6754                return result;
6755            }
6756
6757            function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier;
6758            function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName;
6759            function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName {
6760                const chain = lookupSymbolChain(symbol, context, meaning);
6761
6762                if (expectsIdentifier && chain.length !== 1
6763                    && !context.encounteredError
6764                    && !(context.flags & NodeBuilderFlags.AllowQualifiedNameInPlaceOfIdentifier)) {
6765                    context.encounteredError = true;
6766                }
6767                return createEntityNameFromSymbolChain(chain, chain.length - 1);
6768
6769                function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName {
6770                    const typeParameterNodes = lookupTypeParameterNodes(chain, index, context);
6771                    const symbol = chain[index];
6772
6773                    if (index === 0) {
6774                        context.flags |= NodeBuilderFlags.InInitialEntityName;
6775                    }
6776                    const symbolName = getNameOfSymbolAsWritten(symbol, context);
6777                    if (index === 0) {
6778                        context.flags ^= NodeBuilderFlags.InInitialEntityName;
6779                    }
6780
6781                    const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
6782                    identifier.symbol = symbol;
6783
6784                    return index > 0 ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier;
6785                }
6786            }
6787
6788            function symbolToExpression(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) {
6789                const chain = lookupSymbolChain(symbol, context, meaning);
6790
6791                return createExpressionFromSymbolChain(chain, chain.length - 1);
6792
6793                function createExpressionFromSymbolChain(chain: Symbol[], index: number): Expression {
6794                    const typeParameterNodes = lookupTypeParameterNodes(chain, index, context);
6795                    const symbol = chain[index];
6796
6797                    if (index === 0) {
6798                        context.flags |= NodeBuilderFlags.InInitialEntityName;
6799                    }
6800                    let symbolName = getNameOfSymbolAsWritten(symbol, context);
6801                    if (index === 0) {
6802                        context.flags ^= NodeBuilderFlags.InInitialEntityName;
6803                    }
6804                    let firstChar = symbolName.charCodeAt(0);
6805
6806                    if (isSingleOrDoubleQuote(firstChar) && some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) {
6807                        return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context));
6808                    }
6809                    const canUsePropertyAccess = firstChar === CharacterCodes.hash ?
6810                        symbolName.length > 1 && isIdentifierStart(symbolName.charCodeAt(1), languageVersion) :
6811                        isIdentifierStart(firstChar, languageVersion);
6812                    if (index === 0 || canUsePropertyAccess) {
6813                        const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
6814                        identifier.symbol = symbol;
6815
6816                        return index > 0 ? factory.createPropertyAccessExpression(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier;
6817                    }
6818                    else {
6819                        if (firstChar === CharacterCodes.openBracket) {
6820                            symbolName = symbolName.substring(1, symbolName.length - 1);
6821                            firstChar = symbolName.charCodeAt(0);
6822                        }
6823                        let expression: Expression | undefined;
6824                        if (isSingleOrDoubleQuote(firstChar) && !(symbol.flags & SymbolFlags.EnumMember)) {
6825                           expression = factory.createStringLiteral(stripQuotes(symbolName).replace(/\\./g, s => s.substring(1)), firstChar === CharacterCodes.singleQuote);
6826                        }
6827                        else if (("" + +symbolName) === symbolName) {
6828                            expression = factory.createNumericLiteral(+symbolName);
6829                        }
6830                        if (!expression) {
6831                            expression = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
6832                            expression.symbol = symbol;
6833                        }
6834                        return factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression);
6835                    }
6836                }
6837            }
6838
6839            function isStringNamed(d: Declaration) {
6840                const name = getNameOfDeclaration(d);
6841                return !!name && isStringLiteral(name);
6842            }
6843
6844            function isSingleQuotedStringNamed(d: Declaration) {
6845                const name = getNameOfDeclaration(d);
6846                return !!(name && isStringLiteral(name) && (name.singleQuote || !nodeIsSynthesized(name) && startsWith(getTextOfNode(name, /*includeTrivia*/ false), "'")));
6847            }
6848
6849            function getPropertyNameNodeForSymbol(symbol: Symbol, context: NodeBuilderContext) {
6850                const singleQuote = !!length(symbol.declarations) && every(symbol.declarations, isSingleQuotedStringNamed);
6851                const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context, singleQuote);
6852                if (fromNameType) {
6853                    return fromNameType;
6854                }
6855                const rawName = unescapeLeadingUnderscores(symbol.escapedName);
6856                const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed);
6857                return createPropertyNameNodeForIdentifierOrLiteral(rawName, getEmitScriptTarget(compilerOptions), singleQuote, stringNamed);
6858            }
6859
6860            // See getNameForSymbolFromNameType for a stringy equivalent
6861            function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean) {
6862                const nameType = getSymbolLinks(symbol).nameType;
6863                if (nameType) {
6864                    if (nameType.flags & TypeFlags.StringOrNumberLiteral) {
6865                        const name = "" + (nameType as StringLiteralType | NumberLiteralType).value;
6866                        if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && !isNumericLiteralName(name)) {
6867                            return factory.createStringLiteral(name, !!singleQuote);
6868                        }
6869                        if (isNumericLiteralName(name) && startsWith(name, "-")) {
6870                            return factory.createComputedPropertyName(factory.createNumericLiteral(+name));
6871                        }
6872                        return createPropertyNameNodeForIdentifierOrLiteral(name, getEmitScriptTarget(compilerOptions));
6873                    }
6874                    if (nameType.flags & TypeFlags.UniqueESSymbol) {
6875                        return factory.createComputedPropertyName(symbolToExpression((nameType as UniqueESSymbolType).symbol, context, SymbolFlags.Value));
6876                    }
6877                }
6878            }
6879
6880            function cloneNodeBuilderContext(context: NodeBuilderContext): NodeBuilderContext {
6881                const initial: NodeBuilderContext = { ...context };
6882                // Make type parameters created within this context not consume the name outside this context
6883                // The symbol serializer ends up creating many sibling scopes that all need "separate" contexts when
6884                // it comes to naming things - within a normal `typeToTypeNode` call, the node builder only ever descends
6885                // through the type tree, so the only cases where we could have used distinct sibling scopes was when there
6886                // were multiple generic overloads with similar generated type parameter names
6887                // The effect:
6888                // When we write out
6889                // export const x: <T>(x: T) => T
6890                // export const y: <T>(x: T) => T
6891                // we write it out like that, rather than as
6892                // export const x: <T>(x: T) => T
6893                // export const y: <T_1>(x: T_1) => T_1
6894                if (initial.typeParameterNames) {
6895                    initial.typeParameterNames = new Map(initial.typeParameterNames);
6896                }
6897                if (initial.typeParameterNamesByText) {
6898                    initial.typeParameterNamesByText = new Set(initial.typeParameterNamesByText);
6899                }
6900                if (initial.typeParameterSymbolList) {
6901                    initial.typeParameterSymbolList = new Set(initial.typeParameterSymbolList);
6902                }
6903                initial.tracker = wrapSymbolTrackerToReportForContext(initial, initial.tracker);
6904                return initial;
6905            }
6906
6907
6908            function getDeclarationWithTypeAnnotation(symbol: Symbol, enclosingDeclaration: Node | undefined) {
6909                return symbol.declarations && find(symbol.declarations, s => !!getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration)));
6910            }
6911
6912            function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: TypeNode, type: Type) {
6913                return !(getObjectFlags(type) & ObjectFlags.Reference) || !isTypeReferenceNode(existing) || length(existing.typeArguments) >= getMinTypeArgumentCount((type as TypeReference).target.typeParameters);
6914            }
6915
6916            /**
6917             * Unlike `typeToTypeNodeHelper`, this handles setting up the `AllowUniqueESSymbolType` flag
6918             * so a `unique symbol` is returned when appropriate for the input symbol, rather than `typeof sym`
6919             */
6920            function serializeTypeForDeclaration(context: NodeBuilderContext, type: Type, symbol: Symbol, enclosingDeclaration: Node | undefined, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
6921                if (!isErrorType(type) && enclosingDeclaration) {
6922                    const declWithExistingAnnotation = getDeclarationWithTypeAnnotation(symbol, enclosingDeclaration);
6923                    if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) && !isGetAccessorDeclaration(declWithExistingAnnotation)) {
6924                        // try to reuse the existing annotation
6925                        const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!;
6926                        if (typeNodeIsEquivalentToType(existing, declWithExistingAnnotation, type) && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing, type)) {
6927                            const result = serializeExistingTypeNode(context, existing, includePrivateSymbol, bundled);
6928                            if (result) {
6929                                return result;
6930                            }
6931                        }
6932                    }
6933                }
6934                const oldFlags = context.flags;
6935                if (type.flags & TypeFlags.UniqueESSymbol &&
6936                    type.symbol === symbol && (!context.enclosingDeclaration || some(symbol.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!)))) {
6937                    context.flags |= NodeBuilderFlags.AllowUniqueESSymbolType;
6938                }
6939                const result = typeToTypeNodeHelper(type, context);
6940                context.flags = oldFlags;
6941                return result;
6942            }
6943
6944            function typeNodeIsEquivalentToType(typeNode: TypeNode, annotatedDeclaration: Declaration, type: Type) {
6945                const typeFromTypeNode = getTypeFromTypeNode(typeNode);
6946                if (typeFromTypeNode === type) {
6947                    return true;
6948                }
6949                if (isParameter(annotatedDeclaration) && annotatedDeclaration.questionToken) {
6950                    return getTypeWithFacts(type, TypeFacts.NEUndefined) === typeFromTypeNode;
6951                }
6952                return false;
6953            }
6954
6955            function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
6956                if (!isErrorType(type) && context.enclosingDeclaration) {
6957                    const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration);
6958                    if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation) {
6959                        const annotated = getTypeFromTypeNode(annotation);
6960                        const thisInstantiated = annotated.flags & TypeFlags.TypeParameter && (annotated as TypeParameter).isThisType ? instantiateType(annotated, signature.mapper) : annotated;
6961                        if (thisInstantiated === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(annotation, type)) {
6962                            const result = serializeExistingTypeNode(context, annotation, includePrivateSymbol, bundled);
6963                            if (result) {
6964                                return result;
6965                            }
6966                        }
6967                    }
6968                }
6969                return typeToTypeNodeHelper(type, context);
6970            }
6971
6972            function trackExistingEntityName<T extends EntityNameOrEntityNameExpression>(node: T, context: NodeBuilderContext, includePrivateSymbol?: (s: Symbol) => void) {
6973                let introducesError = false;
6974                const leftmost = getFirstIdentifier(node);
6975                if (isInJSFile(node) && (isExportsIdentifier(leftmost) || isModuleExportsAccessExpression(leftmost.parent) || (isQualifiedName(leftmost.parent) && isModuleIdentifier(leftmost.parent.left) && isExportsIdentifier(leftmost.parent.right)))) {
6976                    introducesError = true;
6977                    return { introducesError, node };
6978                }
6979                const sym = resolveEntityName(leftmost, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveALias*/ true);
6980                if (sym) {
6981                    if (isSymbolAccessible(sym, context.enclosingDeclaration, SymbolFlags.All, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== SymbolAccessibility.Accessible) {
6982                        introducesError = true;
6983                    }
6984                    else {
6985                        context.tracker?.trackSymbol?.(sym, context.enclosingDeclaration, SymbolFlags.All);
6986                        includePrivateSymbol?.(sym);
6987                    }
6988                    if (isIdentifier(node)) {
6989                        const type = getDeclaredTypeOfSymbol(sym);
6990                        const name = sym.flags & SymbolFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) ? typeParameterToName(type, context) : factory.cloneNode(node);
6991                        name.symbol = sym; // for quickinfo, which uses identifier symbol information
6992                        return { introducesError, node: setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping) };
6993                    }
6994                }
6995
6996                return { introducesError, node };
6997            }
6998
6999            function serializeExistingTypeNode(context: NodeBuilderContext, existing: TypeNode, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
7000                if (cancellationToken && cancellationToken.throwIfCancellationRequested) {
7001                    cancellationToken.throwIfCancellationRequested();
7002                }
7003                let hadError = false;
7004                const file = getSourceFileOfNode(existing);
7005                const transformed = visitNode(existing, visitExistingNodeTreeSymbols);
7006                if (hadError) {
7007                    return undefined;
7008                }
7009                return transformed === existing ? setTextRange(factory.cloneNode(existing), existing) : transformed;
7010
7011                function visitExistingNodeTreeSymbols<T extends Node>(node: T): Node {
7012                    // We don't _actually_ support jsdoc namepath types, emit `any` instead
7013                    if (isJSDocAllType(node) || node.kind === SyntaxKind.JSDocNamepathType) {
7014                        return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
7015                    }
7016                    if (isJSDocUnknownType(node)) {
7017                        return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword);
7018                    }
7019                    if (isJSDocNullableType(node)) {
7020                        return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), factory.createLiteralTypeNode(factory.createNull())]);
7021                    }
7022                    if (isJSDocOptionalType(node)) {
7023                        return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]);
7024                    }
7025                    if (isJSDocNonNullableType(node)) {
7026                        return visitNode(node.type, visitExistingNodeTreeSymbols);
7027                    }
7028                    if (isJSDocVariadicType(node)) {
7029                        return factory.createArrayTypeNode(visitNode((node as JSDocVariadicType).type, visitExistingNodeTreeSymbols));
7030                    }
7031                    if (isJSDocTypeLiteral(node)) {
7032                        return factory.createTypeLiteralNode(map(node.jsDocPropertyTags, t => {
7033                            const name = isIdentifier(t.name) ? t.name : t.name.right;
7034                            const typeViaParent = getTypeOfPropertyOfType(getTypeFromTypeNode(node), name.escapedText);
7035                            const overrideTypeNode = typeViaParent && t.typeExpression && getTypeFromTypeNode(t.typeExpression.type) !== typeViaParent ? typeToTypeNodeHelper(typeViaParent, context) : undefined;
7036
7037                            return factory.createPropertySignature(
7038                                /*modifiers*/ undefined,
7039                                name,
7040                                t.isBracketed || t.typeExpression && isJSDocOptionalType(t.typeExpression.type) ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
7041                                overrideTypeNode || (t.typeExpression && visitNode(t.typeExpression.type, visitExistingNodeTreeSymbols)) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
7042                            );
7043                        }));
7044                    }
7045                    if (isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "") {
7046                        return setOriginalNode(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), node);
7047                    }
7048                    if ((isExpressionWithTypeArguments(node) || isTypeReferenceNode(node)) && isJSDocIndexSignature(node)) {
7049                        return factory.createTypeLiteralNode([factory.createIndexSignature(
7050                            /*modifiers*/ undefined,
7051                            [factory.createParameterDeclaration(
7052                                            /*modifiers*/ undefined,
7053                                /*dotdotdotToken*/ undefined,
7054                                "x",
7055                                /*questionToken*/ undefined,
7056                                visitNode(node.typeArguments![0], visitExistingNodeTreeSymbols)
7057                            )],
7058                            visitNode(node.typeArguments![1], visitExistingNodeTreeSymbols)
7059                        )]);
7060                    }
7061                    if (isJSDocFunctionType(node)) {
7062                        if (isJSDocConstructSignature(node)) {
7063                            let newTypeNode: TypeNode | undefined;
7064                            return factory.createConstructorTypeNode(
7065                                /*modifiers*/ undefined,
7066                                visitNodes(node.typeParameters, visitExistingNodeTreeSymbols),
7067                                mapDefined(node.parameters, (p, i) => p.name && isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : factory.createParameterDeclaration(
7068                                    /*modifiers*/ undefined,
7069                                    getEffectiveDotDotDotForParameter(p),
7070                                    getNameForJSDocFunctionParameter(p, i),
7071                                    p.questionToken,
7072                                    visitNode(p.type, visitExistingNodeTreeSymbols),
7073                                    /*initializer*/ undefined
7074                                )),
7075                                visitNode(newTypeNode || node.type, visitExistingNodeTreeSymbols) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
7076                            );
7077                        }
7078                        else {
7079                            return factory.createFunctionTypeNode(
7080                                visitNodes(node.typeParameters, visitExistingNodeTreeSymbols),
7081                                map(node.parameters, (p, i) => factory.createParameterDeclaration(
7082                                    /*modifiers*/ undefined,
7083                                    getEffectiveDotDotDotForParameter(p),
7084                                    getNameForJSDocFunctionParameter(p, i),
7085                                    p.questionToken,
7086                                    visitNode(p.type, visitExistingNodeTreeSymbols),
7087                                    /*initializer*/ undefined
7088                                )),
7089                                visitNode(node.type, visitExistingNodeTreeSymbols) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
7090                            );
7091                        }
7092                    }
7093                    if (isTypeReferenceNode(node) && isInJSDoc(node) && (!existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(node, getTypeFromTypeNode(node)) || getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(node, SymbolFlags.Type, /*ignoreErrors*/ true))) {
7094                        return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node);
7095                    }
7096                    if (isLiteralImportTypeNode(node)) {
7097                        const nodeSymbol = getNodeLinks(node).resolvedSymbol;
7098                        if (isInJSDoc(node) &&
7099                            nodeSymbol &&
7100                            (
7101                                // The import type resolved using jsdoc fallback logic
7102                                (!node.isTypeOf && !(nodeSymbol.flags & SymbolFlags.Type)) ||
7103                                // The import type had type arguments autofilled by js fallback logic
7104                                !(length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nodeSymbol)))
7105                            )
7106                        ) {
7107                            return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node);
7108                        }
7109                        return factory.updateImportTypeNode(
7110                            node,
7111                            factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)),
7112                            node.assertions,
7113                            node.qualifier,
7114                            visitNodes(node.typeArguments, visitExistingNodeTreeSymbols, isTypeNode),
7115                            node.isTypeOf
7116                        );
7117                    }
7118
7119                    if (isEntityName(node) || isEntityNameExpression(node)) {
7120                        const { introducesError, node: result } = trackExistingEntityName(node, context, includePrivateSymbol);
7121                        hadError = hadError || introducesError;
7122                        if (result !== node) {
7123                            return result;
7124                        }
7125                    }
7126
7127                    if (file && isTupleTypeNode(node) && (getLineAndCharacterOfPosition(file, node.pos).line === getLineAndCharacterOfPosition(file, node.end).line)) {
7128                        setEmitFlags(node, EmitFlags.SingleLine);
7129                    }
7130
7131                    return visitEachChild(node, visitExistingNodeTreeSymbols, nullTransformationContext);
7132
7133                    function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) {
7134                        return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined);
7135                    }
7136
7137                    /** Note that `new:T` parameters are not handled, but should be before calling this function. */
7138                    function getNameForJSDocFunctionParameter(p: ParameterDeclaration, index: number) {
7139                        return p.name && isIdentifier(p.name) && p.name.escapedText === "this" ? "this"
7140                            : getEffectiveDotDotDotForParameter(p) ? `args`
7141                            : `arg${index}`;
7142                    }
7143
7144                    function rewriteModuleSpecifier(parent: ImportTypeNode, lit: StringLiteral) {
7145                        if (bundled) {
7146                            if (context.tracker && context.tracker.moduleResolverHost) {
7147                                const targetFile = getExternalModuleFileFromDeclaration(parent);
7148                                if (targetFile) {
7149                                    const getCanonicalFileName = createGetCanonicalFileName(!!host.useCaseSensitiveFileNames);
7150                                    const resolverHost = {
7151                                        getCanonicalFileName,
7152                                        getCurrentDirectory: () => context.tracker.moduleResolverHost!.getCurrentDirectory(),
7153                                        getCommonSourceDirectory: () => context.tracker.moduleResolverHost!.getCommonSourceDirectory()
7154                                    };
7155                                    const newName = getResolvedExternalModuleName(resolverHost, targetFile);
7156                                    return factory.createStringLiteral(newName);
7157                                }
7158                            }
7159                        }
7160                        else {
7161                            if (context.tracker && context.tracker.trackExternalModuleSymbolOfImportTypeNode) {
7162                                const moduleSym = resolveExternalModuleNameWorker(lit, lit, /*moduleNotFoundError*/ undefined);
7163                                if (moduleSym) {
7164                                    context.tracker.trackExternalModuleSymbolOfImportTypeNode(moduleSym);
7165                                }
7166                            }
7167                        }
7168                        return lit;
7169                    }
7170                }
7171            }
7172
7173            function symbolTableToDeclarationStatements(symbolTable: SymbolTable, context: NodeBuilderContext, bundled?: boolean): Statement[] {
7174                const serializePropertySymbolForClass = makeSerializePropertySymbol<ClassElement>(factory.createPropertyDeclaration, SyntaxKind.MethodDeclaration, /*useAcessors*/ true);
7175                const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol<TypeElement>((mods, name, question, type) => factory.createPropertySignature(mods, name, question, type), SyntaxKind.MethodSignature, /*useAcessors*/ false);
7176
7177                // TODO: Use `setOriginalNode` on original declaration names where possible so these declarations see some kind of
7178                // declaration mapping
7179
7180                // We save the enclosing declaration off here so it's not adjusted by well-meaning declaration
7181                // emit codepaths which want to apply more specific contexts (so we can still refer to the root real declaration
7182                // we're trying to emit from later on)
7183                const enclosingDeclaration = context.enclosingDeclaration!;
7184                let results: Statement[] = [];
7185                const visitedSymbols = new Set<number>();
7186                const deferredPrivatesStack: ESMap<SymbolId, Symbol>[] = [];
7187                const oldcontext = context;
7188                context = {
7189                    ...oldcontext,
7190                    usedSymbolNames: new Set(oldcontext.usedSymbolNames),
7191                    remappedSymbolNames: new Map(),
7192                    tracker: {
7193                        ...oldcontext.tracker,
7194                        trackSymbol: (sym, decl, meaning) => {
7195                            const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*computeAliases*/ false);
7196                            if (accessibleResult.accessibility === SymbolAccessibility.Accessible) {
7197                                // Lookup the root symbol of the chain of refs we'll use to access it and serialize it
7198                                const chain = lookupSymbolChainWorker(sym, context, meaning);
7199                                if (!(sym.flags & SymbolFlags.Property)) {
7200                                    includePrivateSymbol(chain[0]);
7201                                }
7202                            }
7203                            else if (oldcontext.tracker && oldcontext.tracker.trackSymbol) {
7204                                return oldcontext.tracker.trackSymbol(sym, decl, meaning);
7205                            }
7206                            return false;
7207                        },
7208                    },
7209                };
7210                context.tracker = wrapSymbolTrackerToReportForContext(context, context.tracker);
7211                forEachEntry(symbolTable, (symbol, name) => {
7212                    const baseName = unescapeLeadingUnderscores(name);
7213                    void getInternalSymbolName(symbol, baseName); // Called to cache values into `usedSymbolNames` and `remappedSymbolNames`
7214                });
7215                let addingDeclare = !bundled;
7216                const exportEquals = symbolTable.get(InternalSymbolName.ExportEquals);
7217                if (exportEquals && symbolTable.size > 1 && exportEquals.flags & SymbolFlags.Alias) {
7218                    symbolTable = createSymbolTable();
7219                    // Remove extraneous elements from root symbol table (they'll be mixed back in when the target of the `export=` is looked up)
7220                    symbolTable.set(InternalSymbolName.ExportEquals, exportEquals);
7221                }
7222
7223                visitSymbolTable(symbolTable);
7224                return mergeRedundantStatements(results);
7225
7226                function isIdentifierAndNotUndefined(node: Node | undefined): node is Identifier {
7227                    return !!node && node.kind === SyntaxKind.Identifier;
7228                }
7229
7230                function getNamesOfDeclaration(statement: Statement): Identifier[] {
7231                    if (isVariableStatement(statement)) {
7232                        return filter(map(statement.declarationList.declarations, getNameOfDeclaration), isIdentifierAndNotUndefined);
7233                    }
7234                    return filter([getNameOfDeclaration(statement as DeclarationStatement)], isIdentifierAndNotUndefined);
7235                }
7236
7237                function flattenExportAssignedNamespace(statements: Statement[]) {
7238                    const exportAssignment = find(statements, isExportAssignment);
7239                    const nsIndex = findIndex(statements, isModuleDeclaration);
7240                    let ns = nsIndex !== -1 ? statements[nsIndex] as ModuleDeclaration : undefined;
7241                    if (ns && exportAssignment && exportAssignment.isExportEquals &&
7242                        isIdentifier(exportAssignment.expression) && isIdentifier(ns.name) && idText(ns.name) === idText(exportAssignment.expression) &&
7243                        ns.body && isModuleBlock(ns.body)) {
7244                        // Pass 0: Correct situations where a module has both an `export = ns` and multiple top-level exports by stripping the export modifiers from
7245                        //  the top-level exports and exporting them in the targeted ns, as can occur when a js file has both typedefs and `module.export` assignments
7246                        const excessExports = filter(statements, s => !!(getEffectiveModifierFlags(s) & ModifierFlags.Export));
7247                        const name = ns.name;
7248                        let body = ns.body;
7249                        if (length(excessExports)) {
7250                            ns = factory.updateModuleDeclaration(
7251                                ns,
7252                                ns.modifiers,
7253                                ns.name,
7254                                body = factory.updateModuleBlock(
7255                                    body,
7256                                    factory.createNodeArray([...ns.body.statements, factory.createExportDeclaration(
7257                                        /*modifiers*/ undefined,
7258                                        /*isTypeOnly*/ false,
7259                                        factory.createNamedExports(map(flatMap(excessExports, e => getNamesOfDeclaration(e)), id => factory.createExportSpecifier(/*isTypeOnly*/ false, /*alias*/ undefined, id))),
7260                                        /*moduleSpecifier*/ undefined
7261                                    )])
7262                                )
7263                            );
7264                            statements = [...statements.slice(0, nsIndex), ns, ...statements.slice(nsIndex + 1)];
7265                        }
7266
7267                        // Pass 1: Flatten `export namespace _exports {} export = _exports;` so long as the `export=` only points at a single namespace declaration
7268                        if (!find(statements, s => s !== ns && nodeHasName(s, name))) {
7269                            results = [];
7270                            // If the namespace contains no export assignments or declarations, and no declarations flagged with `export`, then _everything_ is exported -
7271                            // to respect this as the top level, we need to add an `export` modifier to everything
7272                            const mixinExportFlag = !some(body.statements, s => hasSyntacticModifier(s, ModifierFlags.Export) || isExportAssignment(s) || isExportDeclaration(s));
7273                            forEach(body.statements, s => {
7274                                addResult(s, mixinExportFlag ? ModifierFlags.Export : ModifierFlags.None); // Recalculates the ambient (and export, if applicable from above) flag
7275                            });
7276                            statements = [...filter(statements, s => s !== ns && s !== exportAssignment), ...results];
7277                        }
7278                    }
7279                    return statements;
7280                }
7281
7282                function mergeExportDeclarations(statements: Statement[]) {
7283                    // Pass 2: Combine all `export {}` declarations
7284                    const exports = filter(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)) as ExportDeclaration[];
7285                    if (length(exports) > 1) {
7286                        const nonExports = filter(statements, d => !isExportDeclaration(d) || !!d.moduleSpecifier || !d.exportClause);
7287                        statements = [...nonExports, factory.createExportDeclaration(
7288                            /*modifiers*/ undefined,
7289                            /*isTypeOnly*/ false,
7290                            factory.createNamedExports(flatMap(exports, e => cast(e.exportClause, isNamedExports).elements)),
7291                            /*moduleSpecifier*/ undefined
7292                        )];
7293                    }
7294                    // Pass 2b: Also combine all `export {} from "..."` declarations as needed
7295                    const reexports = filter(statements, d => isExportDeclaration(d) && !!d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)) as ExportDeclaration[];
7296                    if (length(reexports) > 1) {
7297                        const groups = group(reexports, decl => isStringLiteral(decl.moduleSpecifier!) ? ">" + decl.moduleSpecifier.text : ">");
7298                        if (groups.length !== reexports.length) {
7299                            for (const group of groups) {
7300                                if (group.length > 1) {
7301                                    // remove group members from statements and then merge group members and add back to statements
7302                                    statements = [
7303                                        ...filter(statements, s => group.indexOf(s as ExportDeclaration) === -1),
7304                                        factory.createExportDeclaration(
7305                                            /*modifiers*/ undefined,
7306                                            /*isTypeOnly*/ false,
7307                                            factory.createNamedExports(flatMap(group, e => cast(e.exportClause, isNamedExports).elements)),
7308                                            group[0].moduleSpecifier
7309                                        )
7310                                    ];
7311                                }
7312                            }
7313                        }
7314                    }
7315                    return statements;
7316                }
7317
7318                function inlineExportModifiers(statements: Statement[]) {
7319                    // Pass 3: Move all `export {}`'s to `export` modifiers where possible
7320                    const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause && isNamedExports(d.exportClause));
7321                    if (index >= 0) {
7322                        const exportDecl = statements[index] as ExportDeclaration & { readonly exportClause: NamedExports };
7323                        const replacements = mapDefined(exportDecl.exportClause.elements, e => {
7324                            if (!e.propertyName) {
7325                                // export {name} - look thru `statements` for `name`, and if all results can take an `export` modifier, do so and filter it
7326                                const indices = indicesOf(statements);
7327                                const associatedIndices = filter(indices, i => nodeHasName(statements[i], e.name));
7328                                if (length(associatedIndices) && every(associatedIndices, i => canHaveExportModifier(statements[i]))) {
7329                                    for (const index of associatedIndices) {
7330                                        statements[index] = addExportModifier(statements[index] as Extract<HasModifiers, Statement>);
7331                                    }
7332                                    return undefined;
7333                                }
7334                            }
7335                            return e;
7336                        });
7337                        if (!length(replacements)) {
7338                            // all clauses removed, remove the export declaration
7339                            orderedRemoveItemAt(statements, index);
7340                        }
7341                        else {
7342                            // some items filtered, others not - update the export declaration
7343                            statements[index] = factory.updateExportDeclaration(
7344                                exportDecl,
7345                                exportDecl.modifiers,
7346                                exportDecl.isTypeOnly,
7347                                factory.updateNamedExports(
7348                                    exportDecl.exportClause,
7349                                    replacements
7350                                ),
7351                                exportDecl.moduleSpecifier,
7352                                exportDecl.assertClause
7353                            );
7354                        }
7355                    }
7356                    return statements;
7357                }
7358
7359                function mergeRedundantStatements(statements: Statement[]) {
7360                    statements = flattenExportAssignedNamespace(statements);
7361                    statements = mergeExportDeclarations(statements);
7362                    statements = inlineExportModifiers(statements);
7363
7364                    // Not a cleanup, but as a final step: If there is a mix of `export` and non-`export` declarations, but no `export =` or `export {}` add a `export {};` so
7365                    // declaration privacy is respected.
7366                    if (enclosingDeclaration &&
7367                        ((isSourceFile(enclosingDeclaration) && isExternalOrCommonJsModule(enclosingDeclaration)) || isModuleDeclaration(enclosingDeclaration)) &&
7368                        (!some(statements, isExternalModuleIndicator) || (!hasScopeMarker(statements) && some(statements, needsScopeMarker)))) {
7369                        statements.push(createEmptyExports(factory));
7370                    }
7371                    return statements;
7372                }
7373
7374                function addExportModifier(node: Extract<HasModifiers, Statement>) {
7375                    const flags = (getEffectiveModifierFlags(node) | ModifierFlags.Export) & ~ModifierFlags.Ambient;
7376                    return factory.updateModifiers(node, flags);
7377                }
7378
7379                function removeExportModifier(node: Extract<HasModifiers, Statement>) {
7380                    const flags = getEffectiveModifierFlags(node) & ~ModifierFlags.Export;
7381                    return factory.updateModifiers(node, flags);
7382                }
7383
7384                function visitSymbolTable(symbolTable: SymbolTable, suppressNewPrivateContext?: boolean, propertyAsAlias?: boolean) {
7385                    if (!suppressNewPrivateContext) {
7386                        deferredPrivatesStack.push(new Map());
7387                    }
7388                    symbolTable.forEach((symbol: Symbol) => {
7389                        serializeSymbol(symbol, /*isPrivate*/ false, !!propertyAsAlias);
7390                    });
7391                    if (!suppressNewPrivateContext) {
7392                        // deferredPrivates will be filled up by visiting the symbol table
7393                        // And will continue to iterate as elements are added while visited `deferredPrivates`
7394                        // (As that's how a map iterator is defined to work)
7395                        deferredPrivatesStack[deferredPrivatesStack.length - 1].forEach((symbol: Symbol) => {
7396                            serializeSymbol(symbol, /*isPrivate*/ true, !!propertyAsAlias);
7397                        });
7398                        deferredPrivatesStack.pop();
7399                    }
7400                }
7401
7402                function serializeSymbol(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean): void {
7403                    // cache visited list based on merged symbol, since we want to use the unmerged top-level symbol, but
7404                    // still skip reserializing it if we encounter the merged product later on
7405                    const visitedSym = getMergedSymbol(symbol);
7406                    if (visitedSymbols.has(getSymbolId(visitedSym))) {
7407                        return; // Already printed
7408                    }
7409                    visitedSymbols.add(getSymbolId(visitedSym));
7410                    // Only actually serialize symbols within the correct enclosing declaration, otherwise do nothing with the out-of-context symbol
7411                    const skipMembershipCheck = !isPrivate; // We only call this on exported symbols when we know they're in the correct scope
7412                    if (skipMembershipCheck || (!!length(symbol.declarations) && some(symbol.declarations, d => !!findAncestor(d, n => n === enclosingDeclaration)))) {
7413                        const oldContext = context;
7414                        context = cloneNodeBuilderContext(context);
7415                        serializeSymbolWorker(symbol, isPrivate, propertyAsAlias);
7416                        if (context.reportedDiagnostic) {
7417                            oldcontext.reportedDiagnostic = context.reportedDiagnostic; // hoist diagnostic result into outer context
7418                        }
7419                        context = oldContext;
7420                    }
7421                }
7422
7423
7424                // Synthesize declarations for a symbol - might be an Interface, a Class, a Namespace, a Type, a Variable (const, let, or var), an Alias
7425                // or a merge of some number of those.
7426                // An interesting challenge is ensuring that when classes merge with namespaces and interfaces, is keeping
7427                // each symbol in only one of the representations
7428                // Also, synthesizing a default export of some kind
7429                // If it's an alias: emit `export default ref`
7430                // If it's a property: emit `export default _default` with a `_default` prop
7431                // If it's a class/interface/function: emit a class/interface/function with a `default` modifier
7432                // These forms can merge, eg (`export default 12; export default interface A {}`)
7433                function serializeSymbolWorker(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean): void {
7434                    const symbolName = unescapeLeadingUnderscores(symbol.escapedName);
7435                    const isDefault = symbol.escapedName === InternalSymbolName.Default;
7436                    if (isPrivate && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier) && isStringANonContextualKeyword(symbolName) && !isDefault) {
7437                        // Oh no. We cannot use this symbol's name as it's name... It's likely some jsdoc had an invalid name like `export` or `default` :(
7438                        context.encounteredError = true;
7439                        // TODO: Issue error via symbol tracker?
7440                        return; // If we need to emit a private with a keyword name, we're done for, since something else will try to refer to it by that name
7441                    }
7442                    let needsPostExportDefault = isDefault && !!(
7443                           symbol.flags & SymbolFlags.ExportDoesNotSupportDefaultModifier
7444                        || (symbol.flags & SymbolFlags.Function && length(getPropertiesOfType(getTypeOfSymbol(symbol))))
7445                    ) && !(symbol.flags & SymbolFlags.Alias); // An alias symbol should preclude needing to make an alias ourselves
7446                    let needsExportDeclaration = !needsPostExportDefault && !isPrivate && isStringANonContextualKeyword(symbolName) && !isDefault;
7447                    // `serializeVariableOrProperty` will handle adding the export declaration if it is run (since `getInternalSymbolName` will create the name mapping), so we need to ensuer we unset `needsExportDeclaration` if it is
7448                    if (needsPostExportDefault || needsExportDeclaration) {
7449                        isPrivate = true;
7450                    }
7451                    const modifierFlags = (!isPrivate ? ModifierFlags.Export : 0) | (isDefault && !needsPostExportDefault ? ModifierFlags.Default : 0);
7452                    const isConstMergedWithNS = symbol.flags & SymbolFlags.Module &&
7453                        symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) &&
7454                        symbol.escapedName !== InternalSymbolName.ExportEquals;
7455                    const isConstMergedWithNSPrintableAsSignatureMerge = isConstMergedWithNS && isTypeRepresentableAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol);
7456                    if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) || isConstMergedWithNSPrintableAsSignatureMerge) {
7457                        serializeAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
7458                    }
7459                    if (symbol.flags & SymbolFlags.TypeAlias) {
7460                        serializeTypeAlias(symbol, symbolName, modifierFlags);
7461                    }
7462                    // Need to skip over export= symbols below - json source files get a single `Property` flagged
7463                    // symbol of name `export=` which needs to be handled like an alias. It's not great, but it is what it is.
7464                    if (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property)
7465                        && symbol.escapedName !== InternalSymbolName.ExportEquals
7466                        && !(symbol.flags & SymbolFlags.Prototype)
7467                        && !(symbol.flags & SymbolFlags.Class)
7468                        && !(symbol.flags & SymbolFlags.Method)
7469                        && !isConstMergedWithNSPrintableAsSignatureMerge) {
7470                        if (propertyAsAlias) {
7471                            const createdExport = serializeMaybeAliasAssignment(symbol);
7472                            if (createdExport) {
7473                                needsExportDeclaration = false;
7474                                needsPostExportDefault = false;
7475                            }
7476                        }
7477                        else {
7478                            const type = getTypeOfSymbol(symbol);
7479                            const localName = getInternalSymbolName(symbol, symbolName);
7480                            if (!(symbol.flags & SymbolFlags.Function) && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol)) {
7481                                // If the type looks like a function declaration + ns could represent it, and it's type is sourced locally, rewrite it into a function declaration + ns
7482                                serializeAsFunctionNamespaceMerge(type, symbol, localName, modifierFlags);
7483                            }
7484                            else {
7485                                // A Class + Property merge is made for a `module.exports.Member = class {}`, and it doesn't serialize well as either a class _or_ a property symbol - in fact, _it behaves like an alias!_
7486                                // `var` is `FunctionScopedVariable`, `const` and `let` are `BlockScopedVariable`, and `module.exports.thing =` is `Property`
7487                                const flags = !(symbol.flags & SymbolFlags.BlockScopedVariable)
7488                                    ? symbol.parent?.valueDeclaration && isSourceFile(symbol.parent?.valueDeclaration)
7489                                        ? NodeFlags.Const // exports are immutable in es6, which is what we emulate and check; so it's safe to mark all exports as `const` (there's no difference to consumers, but it allows unique symbol type declarations)
7490                                        : undefined
7491                                    : isConstVariable(symbol)
7492                                        ? NodeFlags.Const
7493                                        : NodeFlags.Let;
7494                                const name = (needsPostExportDefault || !(symbol.flags & SymbolFlags.Property)) ? localName : getUnusedName(localName, symbol);
7495                                let textRange: Node | undefined = symbol.declarations && find(symbol.declarations, d => isVariableDeclaration(d));
7496                                if (textRange && isVariableDeclarationList(textRange.parent) && textRange.parent.declarations.length === 1) {
7497                                    textRange = textRange.parent.parent;
7498                                }
7499                                const propertyAccessRequire = symbol.declarations?.find(isPropertyAccessExpression);
7500                                if (propertyAccessRequire && isBinaryExpression(propertyAccessRequire.parent) && isIdentifier(propertyAccessRequire.parent.right)
7501                                    && type.symbol?.valueDeclaration && isSourceFile(type.symbol.valueDeclaration)) {
7502                                    const alias = localName === propertyAccessRequire.parent.right.escapedText ? undefined : propertyAccessRequire.parent.right;
7503                                    addResult(
7504                                        factory.createExportDeclaration(
7505                                            /*modifiers*/ undefined,
7506                                            /*isTypeOnly*/ false,
7507                                            factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, alias, localName)])
7508                                        ),
7509                                        ModifierFlags.None
7510                                    );
7511                                    context.tracker.trackSymbol!(type.symbol, context.enclosingDeclaration, SymbolFlags.Value);
7512                                }
7513                                else {
7514                                    const statement = setTextRange(factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([
7515                                        factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration, includePrivateSymbol, bundled))
7516                                    ], flags)), textRange);
7517                                    addResult(statement, name !== localName ? modifierFlags & ~ModifierFlags.Export : modifierFlags);
7518                                    if (name !== localName && !isPrivate) {
7519                                        // We rename the variable declaration we generate for Property symbols since they may have a name which
7520                                        // conflicts with a local declaration. For example, given input:
7521                                        // ```
7522                                        // function g() {}
7523                                        // module.exports.g = g
7524                                        // ```
7525                                        // In such a situation, we have a local variable named `g`, and a separate exported variable named `g`.
7526                                        // Naively, we would emit
7527                                        // ```
7528                                        // function g() {}
7529                                        // export const g: typeof g;
7530                                        // ```
7531                                        // That's obviously incorrect - the `g` in the type annotation needs to refer to the local `g`, but
7532                                        // the export declaration shadows it.
7533                                        // To work around that, we instead write
7534                                        // ```
7535                                        // function g() {}
7536                                        // const g_1: typeof g;
7537                                        // export { g_1 as g };
7538                                        // ```
7539                                        // To create an export named `g` that does _not_ shadow the local `g`
7540                                        addResult(
7541                                            factory.createExportDeclaration(
7542                                                /*modifiers*/ undefined,
7543                                                /*isTypeOnly*/ false,
7544                                                factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, name, localName)])
7545                                            ),
7546                                            ModifierFlags.None
7547                                        );
7548                                        needsExportDeclaration = false;
7549                                        needsPostExportDefault = false;
7550                                    }
7551                                }
7552                            }
7553                        }
7554                    }
7555                    if (symbol.flags & SymbolFlags.Enum) {
7556                        serializeEnum(symbol, symbolName, modifierFlags);
7557                    }
7558                    if (symbol.flags & SymbolFlags.Class) {
7559                        if (symbol.flags & SymbolFlags.Property
7560                            && symbol.valueDeclaration
7561                            && isBinaryExpression(symbol.valueDeclaration.parent)
7562                            && isClassExpression(symbol.valueDeclaration.parent.right)) {
7563                            // Looks like a `module.exports.Sub = class {}` - if we serialize `symbol` as a class, the result will have no members,
7564                            // since the classiness is actually from the target of the effective alias the symbol is. yes. A BlockScopedVariable|Class|Property
7565                            // _really_ acts like an Alias, and none of a BlockScopedVariable, Class, or Property. This is the travesty of JS binding today.
7566                            serializeAsAlias(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
7567                        }
7568                        else {
7569                            serializeAsClass(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
7570                        }
7571                    }
7572                    if ((symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) || isConstMergedWithNSPrintableAsSignatureMerge) {
7573                        serializeModule(symbol, symbolName, modifierFlags);
7574                    }
7575                    // The class meaning serialization should handle serializing all interface members
7576                    if (symbol.flags & SymbolFlags.Interface && !(symbol.flags & SymbolFlags.Class)) {
7577                        serializeInterface(symbol, symbolName, modifierFlags);
7578                    }
7579                    if (symbol.flags & SymbolFlags.Alias) {
7580                        serializeAsAlias(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
7581                    }
7582                    if (symbol.flags & SymbolFlags.Property && symbol.escapedName === InternalSymbolName.ExportEquals) {
7583                        serializeMaybeAliasAssignment(symbol);
7584                    }
7585                    if (symbol.flags & SymbolFlags.ExportStar) {
7586                        // synthesize export * from "moduleReference"
7587                        // Straightforward - only one thing to do - make an export declaration
7588                        if (symbol.declarations) {
7589                            for (const node of symbol.declarations) {
7590                                const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!);
7591                                if (!resolvedModule) continue;
7592                                addResult(factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None);
7593                            }
7594                        }
7595                    }
7596                    if (needsPostExportDefault) {
7597                        addResult(factory.createExportAssignment(/*modifiers*/ undefined, /*isExportAssignment*/ false, factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ModifierFlags.None);
7598                    }
7599                    else if (needsExportDeclaration) {
7600                        addResult(factory.createExportDeclaration(
7601                            /*modifiers*/ undefined,
7602                            /*isTypeOnly*/ false,
7603                            factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, getInternalSymbolName(symbol, symbolName), symbolName)])
7604                        ), ModifierFlags.None);
7605                    }
7606                }
7607
7608                function includePrivateSymbol(symbol: Symbol) {
7609                    if (some(symbol.declarations, isParameterDeclaration)) return;
7610                    Debug.assertIsDefined(deferredPrivatesStack[deferredPrivatesStack.length - 1]);
7611                    getUnusedName(unescapeLeadingUnderscores(symbol.escapedName), symbol); // Call to cache unique name for symbol
7612                    // Blanket moving (import) aliases into the root private context should work, since imports are not valid within namespaces
7613                    // (so they must have been in the root to begin with if they were real imports) cjs `require` aliases (an upcoming feature)
7614                    // will throw a wrench in this, since those may have been nested, but we'll need to synthesize them in the outer scope
7615                    // anyway, as that's the only place the import they translate to is valid. In such a case, we might need to use a unique name
7616                    // for the moved import; which hopefully the above `getUnusedName` call should produce.
7617                    const isExternalImportAlias = !!(symbol.flags & SymbolFlags.Alias) && !some(symbol.declarations, d =>
7618                        !!findAncestor(d, isExportDeclaration) ||
7619                        isNamespaceExport(d) ||
7620                        (isImportEqualsDeclaration(d) && !isExternalModuleReference(d.moduleReference))
7621                    );
7622                    deferredPrivatesStack[isExternalImportAlias ? 0 : (deferredPrivatesStack.length - 1)].set(getSymbolId(symbol), symbol);
7623                }
7624
7625                function isExportingScope(enclosingDeclaration: Node) {
7626                    return ((isSourceFile(enclosingDeclaration) && (isExternalOrCommonJsModule(enclosingDeclaration) || isJsonSourceFile(enclosingDeclaration))) ||
7627                        (isAmbientModule(enclosingDeclaration) && !isGlobalScopeAugmentation(enclosingDeclaration)));
7628                }
7629
7630                // Prepends a `declare` and/or `export` modifier if the context requires it, and then adds `node` to `result` and returns `node`
7631                function addResult(node: Statement, additionalModifierFlags: ModifierFlags) {
7632                    if (canHaveModifiers(node)) {
7633                        let newModifierFlags: ModifierFlags = ModifierFlags.None;
7634                        const enclosingDeclaration = context.enclosingDeclaration &&
7635                            (isJSDocTypeAlias(context.enclosingDeclaration) ? getSourceFileOfNode(context.enclosingDeclaration) : context.enclosingDeclaration);
7636                        if (additionalModifierFlags & ModifierFlags.Export &&
7637                            enclosingDeclaration && (isExportingScope(enclosingDeclaration) || isModuleDeclaration(enclosingDeclaration)) &&
7638                            canHaveExportModifier(node)
7639                        ) {
7640                            // Classes, namespaces, variables, functions, interfaces, and types should all be `export`ed in a module context if not private
7641                            newModifierFlags |= ModifierFlags.Export;
7642                        }
7643                        if (addingDeclare && !(newModifierFlags & ModifierFlags.Export) &&
7644                            (!enclosingDeclaration || !(enclosingDeclaration.flags & NodeFlags.Ambient)) &&
7645                            (isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) || isClassDeclaration(node) || isModuleDeclaration(node))) {
7646                            // Classes, namespaces, variables, enums, and functions all need `declare` modifiers to be valid in a declaration file top-level scope
7647                            newModifierFlags |= ModifierFlags.Ambient;
7648                        }
7649                        if ((additionalModifierFlags & ModifierFlags.Default) && (isClassDeclaration(node) || isInterfaceDeclaration(node) || isFunctionDeclaration(node))) {
7650                            newModifierFlags |= ModifierFlags.Default;
7651                        }
7652                        if (newModifierFlags) {
7653                            node = factory.updateModifiers(node, newModifierFlags | getEffectiveModifierFlags(node));
7654                        }
7655                    }
7656                    results.push(node);
7657                }
7658
7659                function serializeTypeAlias(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) {
7660                    const aliasType = getDeclaredTypeOfTypeAlias(symbol);
7661                    const typeParams = getSymbolLinks(symbol).typeParameters;
7662                    const typeParamDecls = map(typeParams, p => typeParameterToDeclaration(p, context));
7663                    const jsdocAliasDecl = symbol.declarations?.find(isJSDocTypeAlias);
7664                    const commentText = getTextOfJSDocComment(jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined);
7665                    const oldFlags = context.flags;
7666                    context.flags |= NodeBuilderFlags.InTypeAlias;
7667                    const oldEnclosingDecl = context.enclosingDeclaration;
7668                    context.enclosingDeclaration = jsdocAliasDecl;
7669                    const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression
7670                        && isJSDocTypeExpression(jsdocAliasDecl.typeExpression)
7671                        && serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled)
7672                        || typeToTypeNodeHelper(aliasType, context);
7673                    addResult(setSyntheticLeadingComments(
7674                        factory.createTypeAliasDeclaration(/*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeNode),
7675                        !commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]
7676                    ), modifierFlags);
7677                    context.flags = oldFlags;
7678                    context.enclosingDeclaration = oldEnclosingDecl;
7679                }
7680
7681                function serializeInterface(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) {
7682                    const interfaceType = getDeclaredTypeOfClassOrInterface(symbol);
7683                    const localParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
7684                    const typeParamDecls = map(localParams, p => typeParameterToDeclaration(p, context));
7685                    const baseTypes = getBaseTypes(interfaceType);
7686                    const baseType = length(baseTypes) ? getIntersectionType(baseTypes) : undefined;
7687                    const members = flatMap<Symbol, TypeElement>(getPropertiesOfType(interfaceType), p => serializePropertySymbolForInterface(p, baseType));
7688                    const callSignatures = serializeSignatures(SignatureKind.Call, interfaceType, baseType, SyntaxKind.CallSignature) as CallSignatureDeclaration[];
7689                    const constructSignatures = serializeSignatures(SignatureKind.Construct, interfaceType, baseType, SyntaxKind.ConstructSignature) as ConstructSignatureDeclaration[];
7690                    const indexSignatures = serializeIndexSignatures(interfaceType, baseType);
7691
7692                    const heritageClauses = !length(baseTypes) ? undefined : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, mapDefined(baseTypes, b => trySerializeAsTypeReference(b, SymbolFlags.Value)))];
7693                    addResult(factory.createInterfaceDeclaration(
7694                        /*modifiers*/ undefined,
7695                        getInternalSymbolName(symbol, symbolName),
7696                        typeParamDecls,
7697                        heritageClauses,
7698                        [...indexSignatures, ...constructSignatures, ...callSignatures, ...members]
7699                    ), modifierFlags);
7700                }
7701
7702                function getNamespaceMembersForSerialization(symbol: Symbol) {
7703                    return !symbol.exports ? [] : filter(arrayFrom(symbol.exports.values()), isNamespaceMember);
7704                }
7705
7706                function isTypeOnlyNamespace(symbol: Symbol) {
7707                    return every(getNamespaceMembersForSerialization(symbol), m => !(getAllSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value));
7708                }
7709
7710                function serializeModule(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) {
7711                    const members = getNamespaceMembersForSerialization(symbol);
7712                    // Split NS members up by declaration - members whose parent symbol is the ns symbol vs those whose is not (but were added in later via merging)
7713                    const locationMap = arrayToMultiMap(members, m => m.parent && m.parent === symbol ? "real" : "merged");
7714                    const realMembers = locationMap.get("real") || emptyArray;
7715                    const mergedMembers = locationMap.get("merged") || emptyArray;
7716                    // TODO: `suppressNewPrivateContext` is questionable -we need to simply be emitting privates in whatever scope they were declared in, rather
7717                    // than whatever scope we traverse to them in. That's a bit of a complex rewrite, since we're not _actually_ tracking privates at all in advance,
7718                    // so we don't even have placeholders to fill in.
7719                    if (length(realMembers)) {
7720                        const localName = getInternalSymbolName(symbol, symbolName);
7721                        serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment)));
7722                    }
7723                    if (length(mergedMembers)) {
7724                        const containingFile = getSourceFileOfNode(context.enclosingDeclaration);
7725                        const localName = getInternalSymbolName(symbol, symbolName);
7726                        const nsBody = factory.createModuleBlock([factory.createExportDeclaration(
7727                            /*modifiers*/ undefined,
7728                            /*isTypeOnly*/ false,
7729                            factory.createNamedExports(mapDefined(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => {
7730                                const name = unescapeLeadingUnderscores(s.escapedName);
7731                                const localName = getInternalSymbolName(s, name);
7732                                const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s);
7733                                if (containingFile && (aliasDecl ? containingFile !== getSourceFileOfNode(aliasDecl) : !some(s.declarations, d => getSourceFileOfNode(d) === containingFile))) {
7734                                    context.tracker?.reportNonlocalAugmentation?.(containingFile, symbol, s);
7735                                    return undefined;
7736                                }
7737                                const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true);
7738                                includePrivateSymbol(target || s);
7739                                const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName;
7740                                return factory.createExportSpecifier(/*isTypeOnly*/ false, name === targetName ? undefined : targetName, name);
7741                            }))
7742                        )]);
7743                        addResult(factory.createModuleDeclaration(
7744                            /*modifiers*/ undefined,
7745                            factory.createIdentifier(localName),
7746                            nsBody,
7747                            NodeFlags.Namespace
7748                        ), ModifierFlags.None);
7749                    }
7750                }
7751
7752                function serializeEnum(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) {
7753                    addResult(factory.createEnumDeclaration(
7754                        factory.createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ModifierFlags.Const : 0),
7755                        getInternalSymbolName(symbol, symbolName),
7756                        map(filter(getPropertiesOfType(getTypeOfSymbol(symbol)), p => !!(p.flags & SymbolFlags.EnumMember)), p => {
7757                            // TODO: Handle computed names
7758                            // I hate that to get the initialized value we need to walk back to the declarations here; but there's no
7759                            // other way to get the possible const value of an enum member that I'm aware of, as the value is cached
7760                            // _on the declaration_, not on the declaration's symbol...
7761                            const initializedValue = p.declarations && p.declarations[0] && isEnumMember(p.declarations[0]) ? getConstantValue(p.declarations[0]) : undefined;
7762                            return factory.createEnumMember(unescapeLeadingUnderscores(p.escapedName), initializedValue === undefined ? undefined :
7763                                typeof initializedValue === "string" ? factory.createStringLiteral(initializedValue) :
7764                                factory.createNumericLiteral(initializedValue));
7765                        })
7766                    ), modifierFlags);
7767                }
7768
7769                function serializeAsFunctionNamespaceMerge(type: Type, symbol: Symbol, localName: string, modifierFlags: ModifierFlags) {
7770                    const signatures = getSignaturesOfType(type, SignatureKind.Call);
7771                    for (const sig of signatures) {
7772                        // Each overload becomes a separate function declaration, in order
7773                        const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context, { name: factory.createIdentifier(localName), privateSymbolVisitor: includePrivateSymbol, bundledImports: bundled }) as FunctionDeclaration;
7774                        addResult(setTextRange(decl, getSignatureTextRangeLocation(sig)), modifierFlags);
7775                    }
7776                    // Module symbol emit will take care of module-y members, provided it has exports
7777                    if (!(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) {
7778                        const props = filter(getPropertiesOfType(type), isNamespaceMember);
7779                        serializeAsNamespaceDeclaration(props, localName, modifierFlags, /*suppressNewPrivateContext*/ true);
7780                    }
7781                }
7782
7783                function getSignatureTextRangeLocation(signature: Signature) {
7784                    if (signature.declaration && signature.declaration.parent) {
7785                        if (isBinaryExpression(signature.declaration.parent) && getAssignmentDeclarationKind(signature.declaration.parent) === AssignmentDeclarationKind.Property) {
7786                            return signature.declaration.parent;
7787                        }
7788                        // for expressions assigned to `var`s, use the `var` as the text range
7789                        if (isVariableDeclaration(signature.declaration.parent) && signature.declaration.parent.parent) {
7790                            return signature.declaration.parent.parent;
7791                        }
7792                    }
7793                    return signature.declaration;
7794                }
7795
7796                function serializeAsNamespaceDeclaration(props: readonly Symbol[], localName: string, modifierFlags: ModifierFlags, suppressNewPrivateContext: boolean) {
7797                    if (length(props)) {
7798                        const localVsRemoteMap = arrayToMultiMap(props, p =>
7799                            !length(p.declarations) || some(p.declarations, d =>
7800                                getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!)
7801                            ) ? "local" : "remote"
7802                        );
7803                        const localProps = localVsRemoteMap.get("local") || emptyArray;
7804                        // handle remote props first - we need to make an `import` declaration that points at the module containing each remote
7805                        // prop in the outermost scope (TODO: a namespace within a namespace would need to be appropriately handled by this)
7806                        // Example:
7807                        // import Foo_1 = require("./exporter");
7808                        // export namespace ns {
7809                        //     import Foo = Foo_1.Foo;
7810                        //     export { Foo };
7811                        //     export const c: number;
7812                        // }
7813                        // This is needed because in JS, statements like `const x = require("./f")` support both type and value lookup, even if they're
7814                        // normally just value lookup (so it functions kinda like an alias even when it's not an alias)
7815                        // _Usually_, we'll simply print the top-level as an alias instead of a `var` in such situations, however is is theoretically
7816                        // possible to encounter a situation where a type has members from both the current file and other files - in those situations,
7817                        // emit akin to the above would be needed.
7818
7819                        // Add a namespace
7820                        // Create namespace as non-synthetic so it is usable as an enclosing declaration
7821                        let fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, factory.createIdentifier(localName), factory.createModuleBlock([]), NodeFlags.Namespace);
7822                        setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration);
7823                        fakespace.locals = createSymbolTable(props);
7824                        fakespace.symbol = props[0].parent!;
7825
7826                        const oldResults = results;
7827                        results = [];
7828                        const oldAddingDeclare = addingDeclare;
7829                        addingDeclare = false;
7830                        const subcontext = { ...context, enclosingDeclaration: fakespace };
7831                        const oldContext = context;
7832                        context = subcontext;
7833                        // TODO: implement handling for the localVsRemoteMap.get("remote") - should be difficult to trigger (see comment above), as only interesting cross-file js merges should make this possible
7834                        visitSymbolTable(createSymbolTable(localProps), suppressNewPrivateContext, /*propertyAsAlias*/ true);
7835                        context = oldContext;
7836                        addingDeclare = oldAddingDeclare;
7837                        const declarations = results;
7838                        results = oldResults;
7839                        // replace namespace with synthetic version
7840                        const defaultReplaced = map(declarations, d => isExportAssignment(d) && !d.isExportEquals && isIdentifier(d.expression) ? factory.createExportDeclaration(
7841                            /*modifiers*/ undefined,
7842                            /*isTypeOnly*/ false,
7843                            factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, d.expression, factory.createIdentifier(InternalSymbolName.Default))])
7844                        ) : d);
7845                        const exportModifierStripped = every(defaultReplaced, d => hasSyntacticModifier(d, ModifierFlags.Export)) ? map(defaultReplaced, removeExportModifier) : defaultReplaced;
7846                        fakespace = factory.updateModuleDeclaration(
7847                            fakespace,
7848                            fakespace.modifiers,
7849                            fakespace.name,
7850                            factory.createModuleBlock(exportModifierStripped));
7851                        addResult(fakespace, modifierFlags); // namespaces can never be default exported
7852                    }
7853                }
7854
7855                function isNamespaceMember(p: Symbol) {
7856                    return !!(p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias)) ||
7857                        !(p.flags & SymbolFlags.Prototype || p.escapedName === "prototype" || p.valueDeclaration && isStatic(p.valueDeclaration) && isClassLike(p.valueDeclaration.parent));
7858                }
7859
7860                function sanitizeJSDocImplements(clauses: readonly ExpressionWithTypeArguments[]): ExpressionWithTypeArguments[] | undefined {
7861                    const result = mapDefined(clauses, e => {
7862                        const oldEnclosing = context.enclosingDeclaration;
7863                        context.enclosingDeclaration = e;
7864                        let expr = e.expression;
7865                        if (isEntityNameExpression(expr)) {
7866                            if (isIdentifier(expr) && idText(expr) === "") {
7867                                return cleanup(/*result*/ undefined); // Empty heritage clause, should be an error, but prefer emitting no heritage clauses to reemitting the empty one
7868                            }
7869                            let introducesError: boolean;
7870                            ({ introducesError, node: expr } = trackExistingEntityName(expr, context, includePrivateSymbol));
7871                            if (introducesError) {
7872                                return cleanup(/*result*/ undefined);
7873                            }
7874                        }
7875                        return cleanup(factory.createExpressionWithTypeArguments(expr,
7876                            map(e.typeArguments, a =>
7877                                serializeExistingTypeNode(context, a, includePrivateSymbol, bundled)
7878                                || typeToTypeNodeHelper(getTypeFromTypeNode(a), context)
7879                            )
7880                        ));
7881
7882                        function cleanup<T>(result: T): T {
7883                            context.enclosingDeclaration = oldEnclosing;
7884                            return result;
7885                        }
7886                    });
7887                    if (result.length === clauses.length) {
7888                        return result;
7889                    }
7890                    return undefined;
7891                }
7892
7893                function serializeAsClass(symbol: Symbol, localName: string, modifierFlags: ModifierFlags) {
7894                    const originalDecl = symbol.declarations?.find(isClassLike);
7895                    const oldEnclosing = context.enclosingDeclaration;
7896                    context.enclosingDeclaration = originalDecl || oldEnclosing;
7897                    const localParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
7898                    const typeParamDecls = map(localParams, p => typeParameterToDeclaration(p, context));
7899                    const classType = getDeclaredTypeOfClassOrInterface(symbol);
7900                    const baseTypes = getBaseTypes(classType);
7901                    const originalImplements = originalDecl && getEffectiveImplementsTypeNodes(originalDecl);
7902                    const implementsExpressions = originalImplements && sanitizeJSDocImplements(originalImplements)
7903                        || mapDefined(getImplementsTypes(classType), serializeImplementedType);
7904                    const staticType = getTypeOfSymbol(symbol);
7905                    const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration);
7906                    const staticBaseType = isClass
7907                        ? getBaseConstructorTypeOfClass(staticType as InterfaceType)
7908                        : anyType;
7909                    const heritageClauses = [
7910                        ...!length(baseTypes) ? [] : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))],
7911                        ...!length(implementsExpressions) ? [] : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)]
7912                    ];
7913                    const symbolProps = getNonInheritedProperties(classType, baseTypes, getPropertiesOfType(classType));
7914                    const publicSymbolProps = filter(symbolProps, s => {
7915                        // `valueDeclaration` could be undefined if inherited from
7916                        // a union/intersection base type, but inherited properties
7917                        // don't matter here.
7918                        const valueDecl = s.valueDeclaration;
7919                        return !!valueDecl && !(isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name));
7920                    });
7921                    const hasPrivateIdentifier = some(symbolProps, s => {
7922                        // `valueDeclaration` could be undefined if inherited from
7923                        // a union/intersection base type, but inherited properties
7924                        // don't matter here.
7925                        const valueDecl = s.valueDeclaration;
7926                        return !!valueDecl && isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name);
7927                    });
7928                    // Boil down all private properties into a single one.
7929                    const privateProperties = hasPrivateIdentifier ?
7930                        [factory.createPropertyDeclaration(
7931                            /*modifiers*/ undefined,
7932                            factory.createPrivateIdentifier("#private"),
7933                            /*questionOrExclamationToken*/ undefined,
7934                            /*type*/ undefined,
7935                            /*initializer*/ undefined,
7936                        )] :
7937                        emptyArray;
7938                    const publicProperties = flatMap<Symbol, ClassElement>(publicSymbolProps, p => serializePropertySymbolForClass(p, /*isStatic*/ false, baseTypes[0]));
7939                    // Consider static members empty if symbol also has function or module meaning - function namespacey emit will handle statics
7940                    const staticMembers = flatMap(
7941                        filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)),
7942                        p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType));
7943                    // When we encounter an `X.prototype.y` assignment in a JS file, we bind `X` as a class regardless as to whether
7944                    // the value is ever initialized with a class or function-like value. For cases where `X` could never be
7945                    // created via `new`, we will inject a `private constructor()` declaration to indicate it is not createable.
7946                    const isNonConstructableClassLikeInJsFile =
7947                        !isClass &&
7948                        !!symbol.valueDeclaration &&
7949                        isInJSFile(symbol.valueDeclaration) &&
7950                        !some(getSignaturesOfType(staticType, SignatureKind.Construct));
7951                    const constructors = isNonConstructableClassLikeInJsFile ?
7952                        [factory.createConstructorDeclaration(factory.createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] :
7953                        serializeSignatures(SignatureKind.Construct, staticType, staticBaseType, SyntaxKind.Constructor) as ConstructorDeclaration[];
7954                    const indexSignatures = serializeIndexSignatures(classType, baseTypes[0]);
7955                    context.enclosingDeclaration = oldEnclosing;
7956                    addResult(setTextRange(factory.createClassDeclaration(
7957                        /*modifiers*/ undefined,
7958                        localName,
7959                        typeParamDecls,
7960                        heritageClauses,
7961                        [...indexSignatures, ...staticMembers, ...constructors, ...publicProperties, ...privateProperties]
7962                    ), symbol.declarations && filter(symbol.declarations, d => isClassDeclaration(d) || isClassExpression(d))[0]), modifierFlags);
7963                }
7964
7965                function getSomeTargetNameFromDeclarations(declarations: Declaration[] | undefined) {
7966                    return firstDefined(declarations, d => {
7967                        if (isImportSpecifier(d) || isExportSpecifier(d)) {
7968                            return idText(d.propertyName || d.name);
7969                        }
7970                        if (isBinaryExpression(d) || isExportAssignment(d)) {
7971                            const expression = isExportAssignment(d) ? d.expression : d.right;
7972                            if (isPropertyAccessExpression(expression)) {
7973                                return idText(expression.name);
7974                            }
7975                        }
7976                        if (isAliasSymbolDeclaration(d)) {
7977                            // This is... heuristic, at best. But it's probably better than always printing the name of the shorthand ambient module.
7978                            const name = getNameOfDeclaration(d);
7979                            if (name && isIdentifier(name)) {
7980                                return idText(name);
7981                            }
7982                        }
7983                        return undefined;
7984                    });
7985                }
7986
7987                function serializeAsAlias(symbol: Symbol, localName: string, modifierFlags: ModifierFlags) {
7988                    // synthesize an alias, eg `export { symbolName as Name }`
7989                    // need to mark the alias `symbol` points at
7990                    // as something we need to serialize as a private declaration as well
7991                    const node = getDeclarationOfAliasSymbol(symbol);
7992                    if (!node) return Debug.fail();
7993                    const target = getMergedSymbol(getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true));
7994                    if (!target) {
7995                        return;
7996                    }
7997                    // If `target` refers to a shorthand module symbol, the name we're trying to pull out isn;t recoverable from the target symbol
7998                    // In such a scenario, we must fall back to looking for an alias declaration on `symbol` and pulling the target name from that
7999                    let verbatimTargetName = isShorthandAmbientModuleSymbol(target) && getSomeTargetNameFromDeclarations(symbol.declarations) || unescapeLeadingUnderscores(target.escapedName);
8000                    if (verbatimTargetName === InternalSymbolName.ExportEquals && (getESModuleInterop(compilerOptions) || compilerOptions.allowSyntheticDefaultImports)) {
8001                        // target refers to an `export=` symbol that was hoisted into a synthetic default - rename here to match
8002                        verbatimTargetName = InternalSymbolName.Default;
8003                    }
8004                    const targetName = getInternalSymbolName(target, verbatimTargetName);
8005                    includePrivateSymbol(target); // the target may be within the same scope - attempt to serialize it first
8006                    switch (node.kind) {
8007                        case SyntaxKind.BindingElement:
8008                            if (node.parent?.parent?.kind === SyntaxKind.VariableDeclaration) {
8009                                // const { SomeClass } = require('./lib');
8010                                const specifier = getSpecifierForModuleSymbol(target.parent || target, context); // './lib'
8011                                const { propertyName } = node as BindingElement;
8012                                addResult(factory.createImportDeclaration(
8013                                    /*modifiers*/ undefined,
8014                                    factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamedImports([factory.createImportSpecifier(
8015                                        /*isTypeOnly*/ false,
8016                                        propertyName && isIdentifier(propertyName) ? factory.createIdentifier(idText(propertyName)) : undefined,
8017                                        factory.createIdentifier(localName)
8018                                    )])),
8019                                    factory.createStringLiteral(specifier),
8020                                    /*importClause*/ undefined
8021                                ), ModifierFlags.None);
8022                                break;
8023                            }
8024                            // We don't know how to serialize this (nested?) binding element
8025                            Debug.failBadSyntaxKind(node.parent?.parent || node, "Unhandled binding element grandparent kind in declaration serialization");
8026                        case SyntaxKind.ShorthandPropertyAssignment:
8027                            if (node.parent?.parent?.kind === SyntaxKind.BinaryExpression) {
8028                                // module.exports = { SomeClass }
8029                                serializeExportSpecifier(
8030                                    unescapeLeadingUnderscores(symbol.escapedName),
8031                                    targetName
8032                                );
8033                            }
8034                            break;
8035                        case SyntaxKind.VariableDeclaration:
8036                            // commonjs require: const x = require('y')
8037                            if (isPropertyAccessExpression((node as VariableDeclaration).initializer!)) {
8038                                // const x = require('y').z
8039                                const initializer = (node as VariableDeclaration).initializer! as PropertyAccessExpression; // require('y').z
8040                                const uniqueName = factory.createUniqueName(localName); // _x
8041                                const specifier = getSpecifierForModuleSymbol(target.parent || target, context); // 'y'
8042                                // import _x = require('y');
8043                                addResult(factory.createImportEqualsDeclaration(
8044                                    /*modifiers*/ undefined,
8045                                    /*isTypeOnly*/ false,
8046                                    uniqueName,
8047                                    factory.createExternalModuleReference(factory.createStringLiteral(specifier))
8048                                ), ModifierFlags.None);
8049                                // import x = _x.z
8050                                addResult(factory.createImportEqualsDeclaration(
8051                                    /*modifiers*/ undefined,
8052                                    /*isTypeOnly*/ false,
8053                                    factory.createIdentifier(localName),
8054                                    factory.createQualifiedName(uniqueName, initializer.name as Identifier),
8055                                ), modifierFlags);
8056                                break;
8057                            }
8058                            // else fall through and treat commonjs require just like import=
8059                        case SyntaxKind.ImportEqualsDeclaration:
8060                            // This _specifically_ only exists to handle json declarations - where we make aliases, but since
8061                            // we emit no declarations for the json document, must not refer to it in the declarations
8062                            if (target.escapedName === InternalSymbolName.ExportEquals && some(target.declarations, isJsonSourceFile)) {
8063                                serializeMaybeAliasAssignment(symbol);
8064                                break;
8065                            }
8066                            // Could be a local `import localName = ns.member` or
8067                            // an external `import localName = require("whatever")`
8068                            const isLocalImport = !(target.flags & SymbolFlags.ValueModule) && !isVariableDeclaration(node);
8069                            addResult(factory.createImportEqualsDeclaration(
8070                                /*modifiers*/ undefined,
8071                                /*isTypeOnly*/ false,
8072                                factory.createIdentifier(localName),
8073                                isLocalImport
8074                                    ? symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false)
8075                                    : factory.createExternalModuleReference(factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)))
8076                            ), isLocalImport ? modifierFlags : ModifierFlags.None);
8077                            break;
8078                        case SyntaxKind.NamespaceExportDeclaration:
8079                            // export as namespace foo
8080                            // TODO: Not part of a file's local or export symbol tables
8081                            // Is bound into file.symbol.globalExports instead, which we don't currently traverse
8082                            addResult(factory.createNamespaceExportDeclaration(idText((node as NamespaceExportDeclaration).name)), ModifierFlags.None);
8083                            break;
8084                        case SyntaxKind.ImportClause:
8085                            addResult(factory.createImportDeclaration(
8086                                /*modifiers*/ undefined,
8087                                factory.createImportClause(/*isTypeOnly*/ false, factory.createIdentifier(localName), /*namedBindings*/ undefined),
8088                                // We use `target.parent || target` below as `target.parent` is unset when the target is a module which has been export assigned
8089                                // And then made into a default by the `esModuleInterop` or `allowSyntheticDefaultImports` flag
8090                                // In such cases, the `target` refers to the module itself already
8091                                factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)),
8092                                 /*assertClause*/ undefined
8093                            ), ModifierFlags.None);
8094                            break;
8095                        case SyntaxKind.NamespaceImport:
8096                            addResult(factory.createImportDeclaration(
8097                                /*modifiers*/ undefined,
8098                                factory.createImportClause(/*isTypeOnly*/ false, /*importClause*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))),
8099                                factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)),
8100                                 /*assertClause*/ undefined
8101                            ), ModifierFlags.None);
8102                            break;
8103                        case SyntaxKind.NamespaceExport:
8104                            addResult(factory.createExportDeclaration(
8105                                /*modifiers*/ undefined,
8106                                /*isTypeOnly*/ false,
8107                                factory.createNamespaceExport(factory.createIdentifier(localName)),
8108                                factory.createStringLiteral(getSpecifierForModuleSymbol(target, context))
8109                            ), ModifierFlags.None);
8110                            break;
8111                        case SyntaxKind.ImportSpecifier:
8112                            addResult(factory.createImportDeclaration(
8113                                /*modifiers*/ undefined,
8114                                factory.createImportClause(
8115                                    /*isTypeOnly*/ false,
8116                                    /*importClause*/ undefined,
8117                                    factory.createNamedImports([
8118                                        factory.createImportSpecifier(
8119                                            /*isTypeOnly*/ false,
8120                                            localName !== verbatimTargetName ? factory.createIdentifier(verbatimTargetName) : undefined,
8121                                            factory.createIdentifier(localName)
8122                                        )
8123                                    ])),
8124                                factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)),
8125                                 /*assertClause*/ undefined
8126                            ), ModifierFlags.None);
8127                            break;
8128                        case SyntaxKind.ExportSpecifier:
8129                            // does not use localName because the symbol name in this case refers to the name in the exports table,
8130                            // which we must exactly preserve
8131                            const specifier = (node.parent.parent as ExportDeclaration).moduleSpecifier;
8132                            // targetName is only used when the target is local, as otherwise the target is an alias that points at
8133                            // another file
8134                            serializeExportSpecifier(
8135                                unescapeLeadingUnderscores(symbol.escapedName),
8136                                specifier ? verbatimTargetName : targetName,
8137                                specifier && isStringLiteralLike(specifier) ? factory.createStringLiteral(specifier.text) : undefined
8138                            );
8139                            break;
8140                        case SyntaxKind.ExportAssignment:
8141                            serializeMaybeAliasAssignment(symbol);
8142                            break;
8143                        case SyntaxKind.BinaryExpression:
8144                        case SyntaxKind.PropertyAccessExpression:
8145                        case SyntaxKind.ElementAccessExpression:
8146                            // Could be best encoded as though an export specifier or as though an export assignment
8147                            // If name is default or export=, do an export assignment
8148                            // Otherwise do an export specifier
8149                            if (symbol.escapedName === InternalSymbolName.Default || symbol.escapedName === InternalSymbolName.ExportEquals) {
8150                                serializeMaybeAliasAssignment(symbol);
8151                            }
8152                            else {
8153                                serializeExportSpecifier(localName, targetName);
8154                            }
8155                            break;
8156                        default:
8157                            return Debug.failBadSyntaxKind(node, "Unhandled alias declaration kind in symbol serializer!");
8158                    }
8159                }
8160
8161                function serializeExportSpecifier(localName: string, targetName: string, specifier?: Expression) {
8162                    addResult(factory.createExportDeclaration(
8163                        /*modifiers*/ undefined,
8164                        /*isTypeOnly*/ false,
8165                        factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, localName !== targetName ? targetName : undefined, localName)]),
8166                        specifier
8167                    ), ModifierFlags.None);
8168                }
8169
8170                /**
8171                 * Returns `true` if an export assignment or declaration was produced for the symbol
8172                 */
8173                function serializeMaybeAliasAssignment(symbol: Symbol): boolean {
8174                    if (symbol.flags & SymbolFlags.Prototype) {
8175                        return false;
8176                    }
8177                    const name = unescapeLeadingUnderscores(symbol.escapedName);
8178                    const isExportEquals = name === InternalSymbolName.ExportEquals;
8179                    const isDefault = name === InternalSymbolName.Default;
8180                    const isExportAssignmentCompatibleSymbolName = isExportEquals || isDefault;
8181                    // synthesize export = ref
8182                    // ref should refer to either be a locally scoped symbol which we need to emit, or
8183                    // a reference to another namespace/module which we may need to emit an `import` statement for
8184                    const aliasDecl = symbol.declarations && getDeclarationOfAliasSymbol(symbol);
8185                    // serialize what the alias points to, preserve the declaration's initializer
8186                    const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true);
8187                    // If the target resolves and resolves to a thing defined in this file, emit as an alias, otherwise emit as a const
8188                    if (target && length(target.declarations) && some(target.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(enclosingDeclaration))) {
8189                        // In case `target` refers to a namespace member, look at the declaration and serialize the leftmost symbol in it
8190                        // eg, `namespace A { export class B {} }; exports = A.B;`
8191                        // Technically, this is all that's required in the case where the assignment is an entity name expression
8192                        const expr = aliasDecl && ((isExportAssignment(aliasDecl) || isBinaryExpression(aliasDecl)) ? getExportAssignmentExpression(aliasDecl) : getPropertyAssignmentAliasLikeExpression(aliasDecl as ShorthandPropertyAssignment | PropertyAssignment | PropertyAccessExpression));
8193                        const first = expr && isEntityNameExpression(expr) ? getFirstNonModuleExportsIdentifier(expr) : undefined;
8194                        const referenced = first && resolveEntityName(first, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, enclosingDeclaration);
8195                        if (referenced || target) {
8196                            includePrivateSymbol(referenced || target);
8197                        }
8198
8199                        // We disable the context's symbol tracker for the duration of this name serialization
8200                        // as, by virtue of being here, the name is required to print something, and we don't want to
8201                        // issue a visibility error on it. Only anonymous classes that an alias points at _would_ issue
8202                        // a visibility error here (as they're not visible within any scope), but we want to hoist them
8203                        // into the containing scope anyway, so we want to skip the visibility checks.
8204                        const oldTrack = context.tracker.trackSymbol;
8205                        context.tracker.trackSymbol = () => false;
8206                        if (isExportAssignmentCompatibleSymbolName) {
8207                            results.push(factory.createExportAssignment(
8208                                /*modifiers*/ undefined,
8209                                isExportEquals,
8210                                symbolToExpression(target, context, SymbolFlags.All)
8211                            ));
8212                        }
8213                        else {
8214                            if (first === expr && first) {
8215                                // serialize as `export {target as name}`
8216                                serializeExportSpecifier(name, idText(first));
8217                            }
8218                            else if (expr && isClassExpression(expr)) {
8219                                serializeExportSpecifier(name, getInternalSymbolName(target, symbolName(target)));
8220                            }
8221                            else {
8222                                // serialize as `import _Ref = t.arg.et; export { _Ref as name }`
8223                                const varName = getUnusedName(name, symbol);
8224                                addResult(factory.createImportEqualsDeclaration(
8225                                    /*modifiers*/ undefined,
8226                                    /*isTypeOnly*/ false,
8227                                    factory.createIdentifier(varName),
8228                                    symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false)
8229                                ), ModifierFlags.None);
8230                                serializeExportSpecifier(name, varName);
8231                            }
8232                        }
8233                        context.tracker.trackSymbol = oldTrack;
8234                        return true;
8235                    }
8236                    else {
8237                        // serialize as an anonymous property declaration
8238                        const varName = getUnusedName(name, symbol);
8239                        // We have to use `getWidenedType` here since the object within a json file is unwidened within the file
8240                        // (Unwidened types can only exist in expression contexts and should never be serialized)
8241                        const typeToSerialize = getWidenedType(getTypeOfSymbol(getMergedSymbol(symbol)));
8242                        if (isTypeRepresentableAsFunctionNamespaceMerge(typeToSerialize, symbol)) {
8243                            // If there are no index signatures and `typeToSerialize` is an object type, emit as a namespace instead of a const
8244                            serializeAsFunctionNamespaceMerge(typeToSerialize, symbol, varName, isExportAssignmentCompatibleSymbolName ? ModifierFlags.None : ModifierFlags.Export);
8245                        }
8246                        else {
8247                            const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([
8248                                factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, typeToSerialize, symbol, enclosingDeclaration, includePrivateSymbol, bundled))
8249                            ], NodeFlags.Const));
8250                            // Inlined JSON types exported with [module.]exports= will already emit an export=, so should use `declare`.
8251                            // Otherwise, the type itself should be exported.
8252                            addResult(statement,
8253                                target && target.flags & SymbolFlags.Property && target.escapedName === InternalSymbolName.ExportEquals ? ModifierFlags.Ambient
8254                                : name === varName ? ModifierFlags.Export
8255                                : ModifierFlags.None);
8256                        }
8257                        if (isExportAssignmentCompatibleSymbolName) {
8258                            results.push(factory.createExportAssignment(
8259                                /*modifiers*/ undefined,
8260                                isExportEquals,
8261                                factory.createIdentifier(varName)
8262                            ));
8263                            return true;
8264                        }
8265                        else if (name !== varName) {
8266                            serializeExportSpecifier(name, varName);
8267                            return true;
8268                        }
8269                        return false;
8270                    }
8271                }
8272
8273                function isTypeRepresentableAsFunctionNamespaceMerge(typeToSerialize: Type, hostSymbol: Symbol) {
8274                    // Only object types which are not constructable, or indexable, whose members all come from the
8275                    // context source file, and whose property names are all valid identifiers and not late-bound, _and_
8276                    // whose input is not type annotated (if the input symbol has an annotation we can reuse, we should prefer it)
8277                    const ctxSrc = getSourceFileOfNode(context.enclosingDeclaration);
8278                    return getObjectFlags(typeToSerialize) & (ObjectFlags.Anonymous | ObjectFlags.Mapped) &&
8279                    !length(getIndexInfosOfType(typeToSerialize)) &&
8280                    !isClassInstanceSide(typeToSerialize) && // While a class instance is potentially representable as a NS, prefer printing a reference to the instance type and serializing the class
8281                    !!(length(filter(getPropertiesOfType(typeToSerialize), isNamespaceMember)) || length(getSignaturesOfType(typeToSerialize, SignatureKind.Call))) &&
8282                    !length(getSignaturesOfType(typeToSerialize, SignatureKind.Construct)) && // TODO: could probably serialize as function + ns + class, now that that's OK
8283                    !getDeclarationWithTypeAnnotation(hostSymbol, enclosingDeclaration) &&
8284                    !(typeToSerialize.symbol && some(typeToSerialize.symbol.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) &&
8285                    !some(getPropertiesOfType(typeToSerialize), p => isLateBoundName(p.escapedName)) &&
8286                    !some(getPropertiesOfType(typeToSerialize), p => some(p.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) &&
8287                    every(getPropertiesOfType(typeToSerialize), p => isIdentifierText(symbolName(p), languageVersion));
8288                }
8289
8290                function makeSerializePropertySymbol<T extends Node>(createProperty: (
8291                    modifiers: readonly Modifier[] | undefined,
8292                    name: string | PropertyName,
8293                    questionOrExclamationToken: QuestionToken | undefined,
8294                    type: TypeNode | undefined,
8295                    initializer: Expression | undefined
8296                ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: true): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]);
8297                function makeSerializePropertySymbol<T extends Node>(createProperty: (
8298                    modifiers: readonly Modifier[] | undefined,
8299                    name: string | PropertyName,
8300                    questionOrExclamationToken: QuestionToken | undefined,
8301                    type: TypeNode | undefined,
8302                    initializer: Expression | undefined
8303                ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: false): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | T[]);
8304                function makeSerializePropertySymbol<T extends Node>(createProperty: (
8305                    modifiers: readonly Modifier[] | undefined,
8306                    name: string | PropertyName,
8307                    questionOrExclamationToken: QuestionToken | undefined,
8308                    type: TypeNode | undefined,
8309                    initializer: Expression | undefined
8310                ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) {
8311                    return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined): (T | AccessorDeclaration | (T | AccessorDeclaration)[]) {
8312                        const modifierFlags = getDeclarationModifierFlagsFromSymbol(p);
8313                        const isPrivate = !!(modifierFlags & ModifierFlags.Private);
8314                        if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) {
8315                            // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols
8316                            // need to be merged namespace members
8317                            return [];
8318                        }
8319                        if (p.flags & SymbolFlags.Prototype ||
8320                            (baseType && getPropertyOfType(baseType, p.escapedName)
8321                             && isReadonlySymbol(getPropertyOfType(baseType, p.escapedName)!) === isReadonlySymbol(p)
8322                             && (p.flags & SymbolFlags.Optional) === (getPropertyOfType(baseType, p.escapedName)!.flags & SymbolFlags.Optional)
8323                             && isTypeIdenticalTo(getTypeOfSymbol(p), getTypeOfPropertyOfType(baseType, p.escapedName)!))) {
8324                            return [];
8325                        }
8326                        const flag = (modifierFlags & ~ModifierFlags.Async) | (isStatic ? ModifierFlags.Static : 0);
8327                        const name = getPropertyNameNodeForSymbol(p, context);
8328                        const firstPropertyLikeDecl = p.declarations?.find(or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression));
8329                        if (p.flags & SymbolFlags.Accessor && useAccessors) {
8330                            const result: AccessorDeclaration[] = [];
8331                            if (p.flags & SymbolFlags.SetAccessor) {
8332                                result.push(setTextRange(factory.createSetAccessorDeclaration(
8333                                    factory.createModifiersFromModifierFlags(flag),
8334                                    name,
8335                                    [factory.createParameterDeclaration(
8336                                        /*modifiers*/ undefined,
8337                                        /*dotDotDotToken*/ undefined,
8338                                        "arg",
8339                                        /*questionToken*/ undefined,
8340                                        isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled)
8341                                    )],
8342                                    /*body*/ undefined
8343                                ), p.declarations?.find(isSetAccessor) || firstPropertyLikeDecl));
8344                            }
8345                            if (p.flags & SymbolFlags.GetAccessor) {
8346                                const isPrivate = modifierFlags & ModifierFlags.Private;
8347                                result.push(setTextRange(factory.createGetAccessorDeclaration(
8348                                    factory.createModifiersFromModifierFlags(flag),
8349                                    name,
8350                                    [],
8351                                    isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled),
8352                                    /*body*/ undefined
8353                                ), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl));
8354                            }
8355                            return result;
8356                        }
8357                        // This is an else/if as accessors and properties can't merge in TS, but might in JS
8358                        // If this happens, we assume the accessor takes priority, as it imposes more constraints
8359                        else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable | SymbolFlags.Accessor)) {
8360                            return setTextRange(createProperty(
8361                                factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag),
8362                                name,
8363                                p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
8364                                isPrivate ? undefined : serializeTypeForDeclaration(context, getWriteTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled),
8365                                // TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357
8366                                // interface members can't have initializers, however class members _can_
8367                                /*initializer*/ undefined
8368                            ), p.declarations?.find(or(isPropertyDeclaration, isVariableDeclaration)) || firstPropertyLikeDecl);
8369                        }
8370                        if (p.flags & (SymbolFlags.Method | SymbolFlags.Function)) {
8371                            const type = getTypeOfSymbol(p);
8372                            const signatures = getSignaturesOfType(type, SignatureKind.Call);
8373                            if (flag & ModifierFlags.Private) {
8374                                return setTextRange(createProperty(
8375                                    factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag),
8376                                    name,
8377                                    p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
8378                                    /*type*/ undefined,
8379                                    /*initializer*/ undefined
8380                                ), p.declarations?.find(isFunctionLikeDeclaration) || signatures[0] && signatures[0].declaration || p.declarations && p.declarations[0]);
8381                            }
8382
8383                            const results = [];
8384                            for (const sig of signatures) {
8385                                // Each overload becomes a separate method declaration, in order
8386                                const decl = signatureToSignatureDeclarationHelper(
8387                                    sig,
8388                                    methodKind,
8389                                    context,
8390                                    {
8391                                        name,
8392                                        questionToken: p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
8393                                        modifiers: flag ? factory.createModifiersFromModifierFlags(flag) : undefined
8394                                    }
8395                                );
8396                                const location = sig.declaration && isPrototypePropertyAssignment(sig.declaration.parent) ? sig.declaration.parent : sig.declaration;
8397                                results.push(setTextRange(decl, location));
8398                            }
8399                            return results as unknown as T[];
8400                        }
8401                        // The `Constructor`'s symbol isn't in the class's properties lists, obviously, since it's a signature on the static
8402                        return Debug.fail(`Unhandled class member kind! ${(p as any).__debugFlags || p.flags}`);
8403                    };
8404                }
8405
8406                function serializePropertySymbolForInterface(p: Symbol, baseType: Type | undefined) {
8407                    return serializePropertySymbolForInterfaceWorker(p, /*isStatic*/ false, baseType);
8408                }
8409
8410                function serializeSignatures(kind: SignatureKind, input: Type, baseType: Type | undefined, outputKind: SignatureDeclaration["kind"]) {
8411                    const signatures = getSignaturesOfType(input, kind);
8412                    if (kind === SignatureKind.Construct) {
8413                        if (!baseType && every(signatures, s => length(s.parameters) === 0)) {
8414                            return []; // No base type, every constructor is empty - elide the extraneous `constructor()`
8415                        }
8416                        if (baseType) {
8417                            // If there is a base type, if every signature in the class is identical to a signature in the baseType, elide all the declarations
8418                            const baseSigs = getSignaturesOfType(baseType, SignatureKind.Construct);
8419                            if (!length(baseSigs) && every(signatures, s => length(s.parameters) === 0)) {
8420                                return []; // Base had no explicit signatures, if all our signatures are also implicit, return an empty list
8421                            }
8422                            if (baseSigs.length === signatures.length) {
8423                                let failed = false;
8424                                for (let i = 0; i < baseSigs.length; i++) {
8425                                    if (!compareSignaturesIdentical(signatures[i], baseSigs[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) {
8426                                        failed = true;
8427                                        break;
8428                                    }
8429                                }
8430                                if (!failed) {
8431                                    return []; // Every signature was identical - elide constructor list as it is inherited
8432                                }
8433                            }
8434                        }
8435                        let privateProtected: ModifierFlags = 0;
8436                        for (const s of signatures) {
8437                            if (s.declaration) {
8438                                privateProtected |= getSelectedEffectiveModifierFlags(s.declaration, ModifierFlags.Private | ModifierFlags.Protected);
8439                            }
8440                        }
8441                        if (privateProtected) {
8442                            return [setTextRange(factory.createConstructorDeclaration(
8443                                factory.createModifiersFromModifierFlags(privateProtected),
8444                                /*parameters*/ [],
8445                                /*body*/ undefined,
8446                            ), signatures[0].declaration)];
8447                        }
8448                    }
8449
8450                    const results = [];
8451                    for (const sig of signatures) {
8452                        // Each overload becomes a separate constructor declaration, in order
8453                        const decl = signatureToSignatureDeclarationHelper(sig, outputKind, context);
8454                        results.push(setTextRange(decl, sig.declaration));
8455                    }
8456                    return results;
8457                }
8458
8459                function serializeIndexSignatures(input: Type, baseType: Type | undefined) {
8460                    const results: IndexSignatureDeclaration[] = [];
8461                    for (const info of getIndexInfosOfType(input)) {
8462                        if (baseType) {
8463                            const baseInfo = getIndexInfoOfType(baseType, info.keyType);
8464                            if (baseInfo) {
8465                                if (isTypeIdenticalTo(info.type, baseInfo.type)) {
8466                                    continue; // elide identical index signatures
8467                                }
8468                            }
8469                        }
8470                        results.push(indexInfoToIndexSignatureDeclarationHelper(info, context, /*typeNode*/ undefined));
8471                    }
8472                    return results;
8473                }
8474
8475                function serializeBaseType(t: Type, staticType: Type, rootName: string) {
8476                    const ref = trySerializeAsTypeReference(t, SymbolFlags.Value);
8477                    if (ref) {
8478                        return ref;
8479                    }
8480                    const tempName = getUnusedName(`${rootName}_base`);
8481                    const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([
8482                        factory.createVariableDeclaration(tempName, /*exclamationToken*/ undefined, typeToTypeNodeHelper(staticType, context))
8483                    ], NodeFlags.Const));
8484                    addResult(statement, ModifierFlags.None);
8485                    return factory.createExpressionWithTypeArguments(factory.createIdentifier(tempName), /*typeArgs*/ undefined);
8486                }
8487
8488                function trySerializeAsTypeReference(t: Type, flags: SymbolFlags) {
8489                    let typeArgs: TypeNode[] | undefined;
8490                    let reference: Expression | undefined;
8491
8492                    // We don't use `isValueSymbolAccessible` below. since that considers alternative containers (like modules)
8493                    // which we can't write out in a syntactically valid way as an expression
8494                    if ((t as TypeReference).target && isSymbolAccessibleByFlags((t as TypeReference).target.symbol, enclosingDeclaration, flags)) {
8495                        typeArgs = map(getTypeArguments(t as TypeReference), t => typeToTypeNodeHelper(t, context));
8496                        reference = symbolToExpression((t as TypeReference).target.symbol, context, SymbolFlags.Type);
8497                    }
8498                    else if (t.symbol && isSymbolAccessibleByFlags(t.symbol, enclosingDeclaration, flags)) {
8499                        reference = symbolToExpression(t.symbol, context, SymbolFlags.Type);
8500                    }
8501                    if (reference) {
8502                        return factory.createExpressionWithTypeArguments(reference, typeArgs);
8503                    }
8504                }
8505
8506                function serializeImplementedType(t: Type) {
8507                    const ref = trySerializeAsTypeReference(t, SymbolFlags.Type);
8508                    if (ref) {
8509                        return ref;
8510                    }
8511                    if (t.symbol) {
8512                        return factory.createExpressionWithTypeArguments(symbolToExpression(t.symbol, context, SymbolFlags.Type), /*typeArgs*/ undefined);
8513                    }
8514                }
8515
8516                function getUnusedName(input: string, symbol?: Symbol): string {
8517                    const id = symbol ? getSymbolId(symbol) : undefined;
8518                    if (id) {
8519                        if (context.remappedSymbolNames!.has(id)) {
8520                            return context.remappedSymbolNames!.get(id)!;
8521                        }
8522                    }
8523                    if (symbol) {
8524                        input = getNameCandidateWorker(symbol, input);
8525                    }
8526                    let i = 0;
8527                    const original = input;
8528                    while (context.usedSymbolNames?.has(input)) {
8529                        i++;
8530                        input = `${original}_${i}`;
8531                    }
8532                    context.usedSymbolNames?.add(input);
8533                    if (id) {
8534                        context.remappedSymbolNames!.set(id, input);
8535                    }
8536                    return input;
8537                }
8538
8539                function getNameCandidateWorker(symbol: Symbol, localName: string) {
8540                    if (localName === InternalSymbolName.Default || localName === InternalSymbolName.Class || localName === InternalSymbolName.Function) {
8541                        const flags = context.flags;
8542                        context.flags |= NodeBuilderFlags.InInitialEntityName;
8543                        const nameCandidate = getNameOfSymbolAsWritten(symbol, context);
8544                        context.flags = flags;
8545                        localName = nameCandidate.length > 0 && isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) ? stripQuotes(nameCandidate) : nameCandidate;
8546                    }
8547                    if (localName === InternalSymbolName.Default) {
8548                        localName = "_default";
8549                    }
8550                    else if (localName === InternalSymbolName.ExportEquals) {
8551                        localName = "_exports";
8552                    }
8553                    localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_");
8554                    return localName;
8555                }
8556
8557                function getInternalSymbolName(symbol: Symbol, localName: string) {
8558                    const id = getSymbolId(symbol);
8559                    if (context.remappedSymbolNames!.has(id)) {
8560                        return context.remappedSymbolNames!.get(id)!;
8561                    }
8562                    localName = getNameCandidateWorker(symbol, localName);
8563                    // The result of this is going to be used as the symbol's name - lock it in, so `getUnusedName` will also pick it up
8564                    context.remappedSymbolNames!.set(id, localName);
8565                    return localName;
8566                }
8567            }
8568        }
8569
8570        function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer?: EmitTextWriter): string {
8571            return writer ? typePredicateToStringWorker(writer).getText() : usingSingleLineStringWriter(typePredicateToStringWorker);
8572
8573            function typePredicateToStringWorker(writer: EmitTextWriter) {
8574                const predicate = factory.createTypePredicateNode(
8575                    typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createToken(SyntaxKind.AssertsKeyword) : undefined,
8576                    typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(),
8577                    typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217
8578                );
8579                const printer = createPrinter({ removeComments: true });
8580                const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
8581                printer.writeNode(EmitHint.Unspecified, predicate, /*sourceFile*/ sourceFile, writer);
8582                return writer;
8583            }
8584        }
8585
8586        function formatUnionTypes(types: readonly Type[]): Type[] {
8587            const result: Type[] = [];
8588            let flags: TypeFlags = 0;
8589            for (let i = 0; i < types.length; i++) {
8590                const t = types[i];
8591                flags |= t.flags;
8592                if (!(t.flags & TypeFlags.Nullable)) {
8593                    if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLiteral)) {
8594                        const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(t as LiteralType);
8595                        if (baseType.flags & TypeFlags.Union) {
8596                            const count = (baseType as UnionType).types.length;
8597                            if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((baseType as UnionType).types[count - 1])) {
8598                                result.push(baseType);
8599                                i += count - 1;
8600                                continue;
8601                            }
8602                        }
8603                    }
8604                    result.push(t);
8605                }
8606            }
8607            if (flags & TypeFlags.Null) result.push(nullType);
8608            if (flags & TypeFlags.Undefined) result.push(undefinedType);
8609            return result || types;
8610        }
8611
8612        function visibilityToString(flags: ModifierFlags): string | undefined {
8613            if (flags === ModifierFlags.Private) {
8614                return "private";
8615            }
8616            if (flags === ModifierFlags.Protected) {
8617                return "protected";
8618            }
8619            return "public";
8620        }
8621
8622        function getTypeAliasForTypeLiteral(type: Type): Symbol | undefined {
8623            if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && type.symbol.declarations) {
8624                const node = walkUpParenthesizedTypes(type.symbol.declarations[0].parent);
8625                if (node.kind === SyntaxKind.TypeAliasDeclaration) {
8626                    return getSymbolOfNode(node);
8627                }
8628            }
8629            return undefined;
8630        }
8631
8632        function isTopLevelInExternalModuleAugmentation(node: Node): boolean {
8633            return node && node.parent &&
8634                node.parent.kind === SyntaxKind.ModuleBlock &&
8635                isExternalModuleAugmentation(node.parent.parent);
8636        }
8637
8638        interface NodeBuilderContext {
8639            enclosingDeclaration: Node | undefined;
8640            flags: NodeBuilderFlags;
8641            tracker: SymbolTracker;
8642
8643            // State
8644            encounteredError: boolean;
8645            reportedDiagnostic: boolean;
8646            visitedTypes: Set<number> | undefined;
8647            symbolDepth: ESMap<string, number> | undefined;
8648            inferTypeParameters: TypeParameter[] | undefined;
8649            approximateLength: number;
8650            truncating?: boolean;
8651            typeParameterSymbolList?: Set<number>;
8652            typeParameterNames?: ESMap<TypeId, Identifier>;
8653            typeParameterNamesByText?: Set<string>;
8654            typeParameterNamesByTextNextNameCount?: ESMap<string, number>;
8655            usedSymbolNames?: Set<string>;
8656            remappedSymbolNames?: ESMap<SymbolId, string>;
8657            reverseMappedStack?: ReverseMappedSymbol[];
8658        }
8659
8660        function isDefaultBindingContext(location: Node) {
8661            return location.kind === SyntaxKind.SourceFile || isAmbientModule(location);
8662        }
8663
8664        function getNameOfSymbolFromNameType(symbol: Symbol, context?: NodeBuilderContext) {
8665            const nameType = getSymbolLinks(symbol).nameType;
8666            if (nameType) {
8667                if (nameType.flags & TypeFlags.StringOrNumberLiteral) {
8668                    const name = "" + (nameType as StringLiteralType | NumberLiteralType).value;
8669                    if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && !isNumericLiteralName(name)) {
8670                        return `"${escapeString(name, CharacterCodes.doubleQuote)}"`;
8671                    }
8672                    if (isNumericLiteralName(name) && startsWith(name, "-")) {
8673                        return `[${name}]`;
8674                    }
8675                    return name;
8676                }
8677                if (nameType.flags & TypeFlags.UniqueESSymbol) {
8678                    return `[${getNameOfSymbolAsWritten((nameType as UniqueESSymbolType).symbol, context)}]`;
8679                }
8680            }
8681        }
8682
8683        /**
8684         * Gets a human-readable name for a symbol.
8685         * Should *not* be used for the right-hand side of a `.` -- use `symbolName(symbol)` for that instead.
8686         *
8687         * Unlike `symbolName(symbol)`, this will include quotes if the name is from a string literal.
8688         * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`.
8689         */
8690        function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string {
8691            if (context && symbol.escapedName === InternalSymbolName.Default && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) &&
8692                // If it's not the first part of an entity name, it must print as `default`
8693                (!(context.flags & NodeBuilderFlags.InInitialEntityName) ||
8694                // if the symbol is synthesized, it will only be referenced externally it must print as `default`
8695                !symbol.declarations ||
8696                // if not in the same binding context (source file, module declaration), it must print as `default`
8697                (context.enclosingDeclaration && findAncestor(symbol.declarations[0], isDefaultBindingContext) !== findAncestor(context.enclosingDeclaration, isDefaultBindingContext)))) {
8698                return "default";
8699            }
8700            if (symbol.declarations && symbol.declarations.length) {
8701                let declaration = firstDefined(symbol.declarations, d => getNameOfDeclaration(d) ? d : undefined); // Try using a declaration with a name, first
8702                const name = declaration && getNameOfDeclaration(declaration);
8703                if (declaration && name) {
8704                    if (isCallExpression(declaration) && isBindableObjectDefinePropertyCall(declaration)) {
8705                        return symbolName(symbol);
8706                    }
8707                    if (isComputedPropertyName(name) && !(getCheckFlags(symbol) & CheckFlags.Late)) {
8708                        const nameType = getSymbolLinks(symbol).nameType;
8709                        if (nameType && nameType.flags & TypeFlags.StringOrNumberLiteral) {
8710                            // Computed property name isn't late bound, but has a well-known name type - use name type to generate a symbol name
8711                            const result = getNameOfSymbolFromNameType(symbol, context);
8712                            if (result !== undefined) {
8713                                return result;
8714                            }
8715                        }
8716                    }
8717                    return declarationNameToString(name);
8718                }
8719                if (!declaration) {
8720                    declaration = symbol.declarations[0]; // Declaration may be nameless, but we'll try anyway
8721                }
8722                if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
8723                    return declarationNameToString((declaration.parent as VariableDeclaration).name);
8724                }
8725                switch (declaration.kind) {
8726                    case SyntaxKind.ClassExpression:
8727                    case SyntaxKind.FunctionExpression:
8728                    case SyntaxKind.ArrowFunction:
8729                        if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) {
8730                            context.encounteredError = true;
8731                        }
8732                        return declaration.kind === SyntaxKind.ClassExpression ? "(Anonymous class)" : "(Anonymous function)";
8733                }
8734            }
8735            const name = getNameOfSymbolFromNameType(symbol, context);
8736            return name !== undefined ? name : symbolName(symbol);
8737        }
8738
8739        function isDeclarationVisible(node: Node): boolean {
8740            if (node) {
8741                const links = getNodeLinks(node);
8742                if (links.isVisible === undefined) {
8743                    links.isVisible = !!determineIfDeclarationIsVisible();
8744                }
8745                return links.isVisible;
8746            }
8747
8748            return false;
8749
8750            function determineIfDeclarationIsVisible() {
8751                switch (node.kind) {
8752                    case SyntaxKind.JSDocCallbackTag:
8753                    case SyntaxKind.JSDocTypedefTag:
8754                    case SyntaxKind.JSDocEnumTag:
8755                        // Top-level jsdoc type aliases are considered exported
8756                        // First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file
8757                        return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent));
8758                    case SyntaxKind.BindingElement:
8759                        return isDeclarationVisible(node.parent.parent);
8760                    case SyntaxKind.VariableDeclaration:
8761                        if (isBindingPattern((node as VariableDeclaration).name) &&
8762                            !((node as VariableDeclaration).name as BindingPattern).elements.length) {
8763                            // If the binding pattern is empty, this variable declaration is not visible
8764                            return false;
8765                        }
8766                        // falls through
8767                    case SyntaxKind.ModuleDeclaration:
8768                    case SyntaxKind.ClassDeclaration:
8769                    case SyntaxKind.StructDeclaration:
8770                    case SyntaxKind.InterfaceDeclaration:
8771                    case SyntaxKind.TypeAliasDeclaration:
8772                    case SyntaxKind.FunctionDeclaration:
8773                    case SyntaxKind.EnumDeclaration:
8774                    case SyntaxKind.ImportEqualsDeclaration:
8775                        // external module augmentation is always visible
8776                        if (isExternalModuleAugmentation(node)) {
8777                            return true;
8778                        }
8779                        const parent = getDeclarationContainer(node);
8780                        // If the node is not exported or it is not ambient module element (except import declaration)
8781                        if (!(getCombinedModifierFlags(node as Declaration) & ModifierFlags.Export) &&
8782                            !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && parent.flags & NodeFlags.Ambient)) {
8783                            return isGlobalSourceFile(parent);
8784                        }
8785                        // Exported members/ambient module elements (exception import declaration) are visible if parent is visible
8786                        return isDeclarationVisible(parent);
8787
8788                    case SyntaxKind.PropertyDeclaration:
8789                    case SyntaxKind.PropertySignature:
8790                    case SyntaxKind.GetAccessor:
8791                    case SyntaxKind.SetAccessor:
8792                    case SyntaxKind.MethodDeclaration:
8793                    case SyntaxKind.MethodSignature:
8794                        if (hasEffectiveModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) {
8795                            // Private/protected properties/methods are not visible
8796                            return false;
8797                        }
8798                        // Public properties/methods are visible if its parents are visible, so:
8799                        // falls through
8800
8801                    case SyntaxKind.Constructor:
8802                    case SyntaxKind.ConstructSignature:
8803                    case SyntaxKind.CallSignature:
8804                    case SyntaxKind.IndexSignature:
8805                    case SyntaxKind.Parameter:
8806                    case SyntaxKind.ModuleBlock:
8807                    case SyntaxKind.FunctionType:
8808                    case SyntaxKind.ConstructorType:
8809                    case SyntaxKind.TypeLiteral:
8810                    case SyntaxKind.TypeReference:
8811                    case SyntaxKind.ArrayType:
8812                    case SyntaxKind.TupleType:
8813                    case SyntaxKind.UnionType:
8814                    case SyntaxKind.IntersectionType:
8815                    case SyntaxKind.ParenthesizedType:
8816                    case SyntaxKind.NamedTupleMember:
8817                        return isDeclarationVisible(node.parent);
8818
8819                    // Default binding, import specifier and namespace import is visible
8820                    // only on demand so by default it is not visible
8821                    case SyntaxKind.ImportClause:
8822                    case SyntaxKind.NamespaceImport:
8823                    case SyntaxKind.ImportSpecifier:
8824                        return false;
8825
8826                    // Type parameters are always visible
8827                    case SyntaxKind.TypeParameter:
8828
8829                    // Source file and namespace export are always visible
8830                    // falls through
8831                    case SyntaxKind.SourceFile:
8832                    case SyntaxKind.NamespaceExportDeclaration:
8833                        return true;
8834
8835                    // Export assignments do not create name bindings outside the module
8836                    case SyntaxKind.ExportAssignment:
8837                        return false;
8838
8839                    default:
8840                        return false;
8841                }
8842            }
8843        }
8844
8845        function collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined {
8846            let exportSymbol: Symbol | undefined;
8847            if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) {
8848                exportSymbol = resolveName(node, node.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false);
8849            }
8850            else if (node.parent.kind === SyntaxKind.ExportSpecifier) {
8851                exportSymbol = getTargetOfExportSpecifier(node.parent as ExportSpecifier, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
8852            }
8853            let result: Node[] | undefined;
8854            let visited: Set<number> | undefined;
8855            if (exportSymbol) {
8856                visited = new Set();
8857                visited.add(getSymbolId(exportSymbol));
8858                buildVisibleNodeList(exportSymbol.declarations);
8859            }
8860            return result;
8861
8862            function buildVisibleNodeList(declarations: Declaration[] | undefined) {
8863                forEach(declarations, declaration => {
8864                    const resultNode = getAnyImportSyntax(declaration) || declaration;
8865                    if (setVisibility) {
8866                        getNodeLinks(declaration).isVisible = true;
8867                    }
8868                    else {
8869                        result = result || [];
8870                        pushIfUnique(result, resultNode);
8871                    }
8872
8873                    if (isInternalModuleImportEqualsDeclaration(declaration)) {
8874                        // Add the referenced top container visible
8875                        const internalModuleReference = declaration.moduleReference as Identifier | QualifiedName;
8876                        const firstIdentifier = getFirstIdentifier(internalModuleReference);
8877                        const importSymbol = resolveName(declaration, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace,
8878                            undefined, undefined, /*isUse*/ false);
8879                        if (importSymbol && visited) {
8880                            if (tryAddToSet(visited, getSymbolId(importSymbol))) {
8881                                buildVisibleNodeList(importSymbol.declarations);
8882                            }
8883                        }
8884                    }
8885                });
8886            }
8887        }
8888
8889        /**
8890         * Push an entry on the type resolution stack. If an entry with the given target and the given property name
8891         * is already on the stack, and no entries in between already have a type, then a circularity has occurred.
8892         * In this case, the result values of the existing entry and all entries pushed after it are changed to false,
8893         * and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned.
8894         * In order to see if the same query has already been done before, the target object and the propertyName both
8895         * must match the one passed in.
8896         *
8897         * @param target The symbol, type, or signature whose type is being queried
8898         * @param propertyName The property name that should be used to query the target for its type
8899         */
8900        function pushTypeResolution(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
8901            const resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName);
8902            if (resolutionCycleStartIndex >= 0) {
8903                // A cycle was found
8904                const { length } = resolutionTargets;
8905                for (let i = resolutionCycleStartIndex; i < length; i++) {
8906                    resolutionResults[i] = false;
8907                }
8908                return false;
8909            }
8910            resolutionTargets.push(target);
8911            resolutionResults.push(/*items*/ true);
8912            resolutionPropertyNames.push(propertyName);
8913            return true;
8914        }
8915
8916        function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number {
8917            for (let i = resolutionTargets.length - 1; i >= 0; i--) {
8918                if (hasType(resolutionTargets[i], resolutionPropertyNames[i])) {
8919                    return -1;
8920                }
8921                if (resolutionTargets[i] === target && resolutionPropertyNames[i] === propertyName) {
8922                    return i;
8923                }
8924            }
8925            return -1;
8926        }
8927
8928        function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
8929            switch (propertyName) {
8930                case TypeSystemPropertyName.Type:
8931                    return !!getSymbolLinks(target as Symbol).type;
8932                case TypeSystemPropertyName.EnumTagType:
8933                    return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType);
8934                case TypeSystemPropertyName.DeclaredType:
8935                    return !!getSymbolLinks(target as Symbol).declaredType;
8936                case TypeSystemPropertyName.ResolvedBaseConstructorType:
8937                    return !!(target as InterfaceType).resolvedBaseConstructorType;
8938                case TypeSystemPropertyName.ResolvedReturnType:
8939                    return !!(target as Signature).resolvedReturnType;
8940                case TypeSystemPropertyName.ImmediateBaseConstraint:
8941                    return !!(target as Type).immediateBaseConstraint;
8942                case TypeSystemPropertyName.ResolvedTypeArguments:
8943                    return !!(target as TypeReference).resolvedTypeArguments;
8944                case TypeSystemPropertyName.ResolvedBaseTypes:
8945                    return !!(target as InterfaceType).baseTypesResolved;
8946                case TypeSystemPropertyName.WriteType:
8947                    return !!getSymbolLinks(target as Symbol).writeType;
8948            }
8949        }
8950
8951        /**
8952         * Pop an entry from the type resolution stack and return its associated result value. The result value will
8953         * be true if no circularities were detected, or false if a circularity was found.
8954         */
8955        function popTypeResolution(): boolean {
8956            resolutionTargets.pop();
8957            resolutionPropertyNames.pop();
8958            return resolutionResults.pop()!;
8959        }
8960
8961        function getDeclarationContainer(node: Node): Node {
8962            return findAncestor(getRootDeclaration(node), node => {
8963                switch (node.kind) {
8964                    case SyntaxKind.VariableDeclaration:
8965                    case SyntaxKind.VariableDeclarationList:
8966                    case SyntaxKind.ImportSpecifier:
8967                    case SyntaxKind.NamedImports:
8968                    case SyntaxKind.NamespaceImport:
8969                    case SyntaxKind.ImportClause:
8970                        return false;
8971                    default:
8972                        return true;
8973                }
8974            })!.parent;
8975        }
8976
8977        function getTypeOfPrototypeProperty(prototype: Symbol): Type {
8978            // TypeScript 1.0 spec (April 2014): 8.4
8979            // Every class automatically contains a static property member named 'prototype',
8980            // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
8981            // It is an error to explicitly declare a static property member with the name 'prototype'.
8982            const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)!) as InterfaceType;
8983            return classType.typeParameters ? createTypeReference(classType as GenericType, map(classType.typeParameters, _ => anyType)) : classType;
8984        }
8985
8986        // Return the type of the given property in the given type, or undefined if no such property exists
8987        function getTypeOfPropertyOfType(type: Type, name: __String): Type | undefined {
8988            const prop = getPropertyOfType(type, name);
8989            return prop ? getTypeOfSymbol(prop) : undefined;
8990        }
8991
8992        function getTypeOfPropertyOrIndexSignature(type: Type, name: __String): Type {
8993            return getTypeOfPropertyOfType(type, name) || getApplicableIndexInfoForName(type, name)?.type || unknownType;
8994        }
8995
8996        function isTypeAny(type: Type | undefined) {
8997            return type && (type.flags & TypeFlags.Any) !== 0;
8998        }
8999
9000        function isErrorType(type: Type) {
9001            // The only 'any' types that have alias symbols are those manufactured by getTypeFromTypeAliasReference for
9002            // a reference to an unresolved symbol. We want those to behave like the errorType.
9003            return type === errorType || !!(type.flags & TypeFlags.Any && type.aliasSymbol);
9004        }
9005
9006        // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been
9007        // assigned by contextual typing.
9008        function getTypeForBindingElementParent(node: BindingElementGrandparent, checkMode: CheckMode) {
9009            if (checkMode !== CheckMode.Normal) {
9010                return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode);
9011            }
9012            const symbol = getSymbolOfNode(node);
9013            return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode);
9014        }
9015
9016        function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type {
9017            source = filterType(source, t => !(t.flags & TypeFlags.Nullable));
9018            if (source.flags & TypeFlags.Never) {
9019                return emptyObjectType;
9020            }
9021            if (source.flags & TypeFlags.Union) {
9022                return mapType(source, t => getRestType(t, properties, symbol));
9023            }
9024
9025            let omitKeyType = getUnionType(map(properties, getLiteralTypeFromPropertyName));
9026
9027            const spreadableProperties: Symbol[] = [];
9028            const unspreadableToRestKeys: Type[] = [];
9029
9030            for (const prop of getPropertiesOfType(source)) {
9031                const literalTypeFromProperty = getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique);
9032                if (!isTypeAssignableTo(literalTypeFromProperty, omitKeyType)
9033                    && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))
9034                    && isSpreadableProperty(prop)) {
9035                    spreadableProperties.push(prop);
9036                }
9037                else {
9038                    unspreadableToRestKeys.push(literalTypeFromProperty);
9039                }
9040            }
9041
9042            if (isGenericObjectType(source) || isGenericIndexType(omitKeyType)) {
9043                if (unspreadableToRestKeys.length) {
9044                    // If the type we're spreading from has properties that cannot
9045                    // be spread into the rest type (e.g. getters, methods), ensure
9046                    // they are explicitly omitted, as they would in the non-generic case.
9047                    omitKeyType = getUnionType([omitKeyType, ...unspreadableToRestKeys]);
9048                }
9049
9050                if (omitKeyType.flags & TypeFlags.Never) {
9051                    return source;
9052                }
9053
9054                const omitTypeAlias = getGlobalOmitSymbol();
9055                if (!omitTypeAlias) {
9056                    return errorType;
9057                }
9058                return getTypeAliasInstantiation(omitTypeAlias, [source, omitKeyType]);
9059            }
9060            const members = createSymbolTable();
9061            for (const prop of spreadableProperties) {
9062                members.set(prop.escapedName, getSpreadSymbol(prop, /*readonly*/ false));
9063            }
9064            const result = createAnonymousType(symbol, members, emptyArray, emptyArray, getIndexInfosOfType(source));
9065            result.objectFlags |= ObjectFlags.ObjectRestType;
9066            return result;
9067        }
9068
9069        function isGenericTypeWithUndefinedConstraint(type: Type) {
9070            return !!(type.flags & TypeFlags.Instantiable) && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Undefined);
9071        }
9072
9073        function getNonUndefinedType(type: Type) {
9074            const typeOrConstraint = someType(type, isGenericTypeWithUndefinedConstraint) ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type;
9075            return getTypeWithFacts(typeOrConstraint, TypeFacts.NEUndefined);
9076        }
9077
9078        // Determine the control flow type associated with a destructuring declaration or assignment. The following
9079        // forms of destructuring are possible:
9080        //   let { x } = obj;  // BindingElement
9081        //   let [ x ] = obj;  // BindingElement
9082        //   { x } = obj;      // ShorthandPropertyAssignment
9083        //   { x: v } = obj;   // PropertyAssignment
9084        //   [ x ] = obj;      // Expression
9085        // We construct a synthetic element access expression corresponding to 'obj.x' such that the control
9086        // flow analyzer doesn't have to handle all the different syntactic forms.
9087        function getFlowTypeOfDestructuring(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, declaredType: Type) {
9088            const reference = getSyntheticElementAccess(node);
9089            return reference ? getFlowTypeOfReference(reference, declaredType) : declaredType;
9090        }
9091
9092        function getSyntheticElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression): ElementAccessExpression | undefined {
9093            const parentAccess = getParentElementAccess(node);
9094            if (parentAccess && parentAccess.flowNode) {
9095                const propName = getDestructuringPropertyName(node);
9096                if (propName) {
9097                    const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node);
9098                    const lhsExpr = isLeftHandSideExpression(parentAccess) ? parentAccess : parseNodeFactory.createParenthesizedExpression(parentAccess);
9099                    const result = setTextRange(parseNodeFactory.createElementAccessExpression(lhsExpr, literal), node);
9100                    setParent(literal, result);
9101                    setParent(result, node);
9102                    if (lhsExpr !== parentAccess) {
9103                        setParent(lhsExpr, result);
9104                    }
9105                    result.flowNode = parentAccess.flowNode;
9106                    return result;
9107                }
9108            }
9109        }
9110
9111        function getParentElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) {
9112            const ancestor = node.parent.parent;
9113            switch (ancestor.kind) {
9114                case SyntaxKind.BindingElement:
9115                case SyntaxKind.PropertyAssignment:
9116                    return getSyntheticElementAccess(ancestor as BindingElement | PropertyAssignment);
9117                case SyntaxKind.ArrayLiteralExpression:
9118                    return getSyntheticElementAccess(node.parent as Expression);
9119                case SyntaxKind.VariableDeclaration:
9120                    return (ancestor as VariableDeclaration).initializer;
9121                case SyntaxKind.BinaryExpression:
9122                    return (ancestor as BinaryExpression).right;
9123            }
9124        }
9125
9126        function getDestructuringPropertyName(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) {
9127            const parent = node.parent;
9128            if (node.kind === SyntaxKind.BindingElement && parent.kind === SyntaxKind.ObjectBindingPattern) {
9129                return getLiteralPropertyNameText((node as BindingElement).propertyName || (node as BindingElement).name as Identifier);
9130            }
9131            if (node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) {
9132                return getLiteralPropertyNameText((node as PropertyAssignment | ShorthandPropertyAssignment).name);
9133            }
9134            return "" + ((parent as BindingPattern | ArrayLiteralExpression).elements as NodeArray<Node>).indexOf(node);
9135        }
9136
9137        function getLiteralPropertyNameText(name: PropertyName) {
9138            const type = getLiteralTypeFromPropertyName(name);
9139            return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ? "" + (type as StringLiteralType | NumberLiteralType).value : undefined;
9140        }
9141
9142        /** Return the inferred type for a binding element */
9143        function getTypeForBindingElement(declaration: BindingElement): Type | undefined {
9144            const checkMode = declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal;
9145            const parentType = getTypeForBindingElementParent(declaration.parent.parent, checkMode);
9146            return parentType && getBindingElementTypeFromParentType(declaration, parentType);
9147        }
9148
9149        function getBindingElementTypeFromParentType(declaration: BindingElement, parentType: Type): Type {
9150            // If an any type was inferred for parent, infer that for the binding element
9151            if (isTypeAny(parentType)) {
9152                return parentType;
9153            }
9154            const pattern = declaration.parent;
9155            // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation
9156            if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
9157                parentType = getNonNullableType(parentType);
9158            }
9159            // Filter `undefined` from the type we check against if the parent has an initializer and that initializer is not possibly `undefined`
9160            else if (strictNullChecks && pattern.parent.initializer && !(getTypeFacts(getTypeOfInitializer(pattern.parent.initializer)) & TypeFacts.EQUndefined)) {
9161                parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined);
9162            }
9163
9164            let type: Type | undefined;
9165            if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
9166                if (declaration.dotDotDotToken) {
9167                    parentType = getReducedType(parentType);
9168                    if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType)) {
9169                        error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
9170                        return errorType;
9171                    }
9172                    const literalMembers: PropertyName[] = [];
9173                    for (const element of pattern.elements) {
9174                        if (!element.dotDotDotToken) {
9175                            literalMembers.push(element.propertyName || element.name as Identifier);
9176                        }
9177                    }
9178                    type = getRestType(parentType, literalMembers, declaration.symbol);
9179                }
9180                else {
9181                    // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
9182                    const name = declaration.propertyName || declaration.name as Identifier;
9183                    const indexType = getLiteralTypeFromPropertyName(name);
9184                    const declaredType = getIndexedAccessType(parentType, indexType, AccessFlags.ExpressionPosition, name);
9185                    type = getFlowTypeOfDestructuring(declaration, declaredType);
9186                }
9187            }
9188            else {
9189                // This elementType will be used if the specific property corresponding to this index is not
9190                // present (aka the tuple element property). This call also checks that the parentType is in
9191                // fact an iterable or array (depending on target language).
9192                const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring | (declaration.dotDotDotToken ? 0 : IterationUse.PossiblyOutOfBounds), parentType, undefinedType, pattern);
9193                const index = pattern.elements.indexOf(declaration);
9194                if (declaration.dotDotDotToken) {
9195                    // If the parent is a tuple type, the rest element has a tuple type of the
9196                    // remaining tuple element types. Otherwise, the rest element has an array type with same
9197                    // element type as the parent type.
9198                    type = everyType(parentType, isTupleType) ?
9199                        mapType(parentType, t => sliceTupleType(t as TupleTypeReference, index)) :
9200                        createArrayType(elementType);
9201                }
9202                else if (isArrayLikeType(parentType)) {
9203                    const indexType = getNumberLiteralType(index);
9204                    const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(declaration) ? AccessFlags.NoTupleBoundsCheck : 0);
9205                    const declaredType = getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.name) || errorType;
9206                    type = getFlowTypeOfDestructuring(declaration, declaredType);
9207                }
9208                else {
9209                    type = elementType;
9210                }
9211            }
9212            if (!declaration.initializer) {
9213                return type;
9214            }
9215            if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) {
9216                // In strict null checking mode, if a default value of a non-undefined type is specified, remove
9217                // undefined from the final type.
9218                return strictNullChecks && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined) ? getNonUndefinedType(type) : type;
9219            }
9220            return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype));
9221        }
9222
9223        function getTypeForDeclarationFromJSDocComment(declaration: Node) {
9224            const jsdocType = getJSDocType(declaration);
9225            if (jsdocType) {
9226                return getTypeFromTypeNode(jsdocType);
9227            }
9228            return undefined;
9229        }
9230
9231        function isNullOrUndefined(node: Expression) {
9232            const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
9233            return expr.kind === SyntaxKind.NullKeyword || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(expr as Identifier) === undefinedSymbol;
9234        }
9235
9236        function isEmptyArrayLiteral(node: Expression) {
9237            const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
9238            return expr.kind === SyntaxKind.ArrayLiteralExpression && (expr as ArrayLiteralExpression).elements.length === 0;
9239        }
9240
9241        function addOptionality(type: Type, isProperty = false, isOptional = true): Type {
9242            return strictNullChecks && isOptional ? getOptionalType(type, isProperty) : type;
9243        }
9244
9245        // Return the inferred type for a variable, parameter, or property declaration
9246        function getTypeForVariableLikeDeclaration(
9247            declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | AnnotationPropertyDeclaration | VariableDeclaration | BindingElement | JSDocPropertyLikeTag,
9248            includeOptionality: boolean,
9249            checkMode: CheckMode,
9250        ): Type | undefined {
9251            // A variable declared in a for..in statement is of type string, or of type keyof T when the
9252            // right hand expression is of a type parameter type.
9253            if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
9254                const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode)));
9255                return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? getExtractStringType(indexType) : stringType;
9256            }
9257
9258            if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
9259                // checkRightHandSideOfForOf will return undefined if the for-of expression type was
9260                // missing properties/signatures required to get its iteratedType (like
9261                // [Symbol.iterator] or next). This may be because we accessed properties from anyType,
9262                // or it may have led to an error inside getElementTypeOfIterable.
9263                const forOfStatement = declaration.parent.parent;
9264                return checkRightHandSideOfForOf(forOfStatement) || anyType;
9265            }
9266
9267            if (isBindingPattern(declaration.parent)) {
9268                return getTypeForBindingElement(declaration as BindingElement);
9269            }
9270
9271            const isProperty = isPropertyDeclaration(declaration) && !hasAccessorModifier(declaration) || isPropertySignature(declaration);
9272            const isOptional = includeOptionality && (
9273                isProperty && !!declaration.questionToken ||
9274                isParameter(declaration) && (!!declaration.questionToken || isJSDocOptionalParameter(declaration)) ||
9275                isOptionalJSDocPropertyLikeTag(declaration));
9276
9277            // Use type from type annotation if one is present
9278            const declaredType = tryGetTypeFromEffectiveTypeNode(declaration);
9279            if (declaredType) {
9280                return addOptionality(declaredType, isProperty, isOptional);
9281            }
9282
9283            if ((noImplicitAny || isInJSFile(declaration)) &&
9284                isVariableDeclaration(declaration) && !isBindingPattern(declaration.name) &&
9285                !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !(declaration.flags & NodeFlags.Ambient)) {
9286                // If --noImplicitAny is on or the declaration is in a Javascript file,
9287                // use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no
9288                // initializer or a 'null' or 'undefined' initializer.
9289                if (!(getCombinedNodeFlags(declaration) & NodeFlags.Const) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) {
9290                    return autoType;
9291                }
9292                // Use control flow tracked 'any[]' type for non-ambient, non-exported variables with an empty array
9293                // literal initializer.
9294                if (declaration.initializer && isEmptyArrayLiteral(declaration.initializer)) {
9295                    return autoArrayType;
9296                }
9297            }
9298
9299            if (isParameter(declaration)) {
9300                const func = declaration.parent as FunctionLikeDeclaration;
9301                // For a parameter of a set accessor, use the type of the get accessor if one is present
9302                if (func.kind === SyntaxKind.SetAccessor && hasBindableName(func)) {
9303                    const getter = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(declaration.parent), SyntaxKind.GetAccessor);
9304                    if (getter) {
9305                        const getterSignature = getSignatureFromDeclaration(getter);
9306                        const thisParameter = getAccessorThisParameter(func as AccessorDeclaration);
9307                        if (thisParameter && declaration === thisParameter) {
9308                            // Use the type from the *getter*
9309                            Debug.assert(!thisParameter.type);
9310                            return getTypeOfSymbol(getterSignature.thisParameter!);
9311                        }
9312                        return getReturnTypeOfSignature(getterSignature);
9313                    }
9314                }
9315                const parameterTypeOfTypeTag = getParameterTypeOfTypeTag(func, declaration);
9316                if (parameterTypeOfTypeTag) return parameterTypeOfTypeTag;
9317                // Use contextual parameter type if one is available
9318                const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration);
9319                if (type) {
9320                    return addOptionality(type, /*isProperty*/ false, isOptional);
9321                }
9322            }
9323
9324            // Use the type of the initializer expression if one is present and the declaration is
9325            // not a parameter of a contextually typed function
9326            if (hasOnlyExpressionInitializer(declaration) && !!declaration.initializer) {
9327                if (isInJSFile(declaration) && !isParameter(declaration)) {
9328                    const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfNode(declaration), getDeclaredExpandoInitializer(declaration));
9329                    if (containerObjectType) {
9330                        return containerObjectType;
9331                    }
9332                }
9333                const type = widenTypeInferredFromInitializer(declaration, checkDeclarationInitializer(declaration, checkMode));
9334                return addOptionality(type, isProperty, isOptional);
9335            }
9336
9337            if (isPropertyDeclaration(declaration) && (noImplicitAny || isInJSFile(declaration))) {
9338                // We have a property declaration with no type annotation or initializer, in noImplicitAny mode or a .js file.
9339                // Use control flow analysis of this.xxx assignments in the constructor or static block to determine the type of the property.
9340                if (!hasStaticModifier(declaration)) {
9341                    const constructor = findConstructorDeclaration(declaration.parent);
9342                    const type = constructor ? getFlowTypeInConstructor(declaration.symbol, constructor) :
9343                        getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) :
9344                        undefined;
9345                    return type && addOptionality(type, /*isProperty*/ true, isOptional);
9346                }
9347                else {
9348                    const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration);
9349                    const type = staticBlocks.length ? getFlowTypeInStaticBlocks(declaration.symbol, staticBlocks) :
9350                        getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) :
9351                        undefined;
9352                    return type && addOptionality(type, /*isProperty*/ true, isOptional);
9353                }
9354            }
9355
9356            if (isJsxAttribute(declaration)) {
9357                // if JSX attribute doesn't have initializer, by default the attribute will have boolean value of true.
9358                // I.e <Elem attr /> is sugar for <Elem attr={true} />
9359                return trueType;
9360            }
9361
9362            // If the declaration specifies a binding pattern and is not a parameter of a contextually
9363            // typed function, use the type implied by the binding pattern
9364            if (isBindingPattern(declaration.name)) {
9365                return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ false, /*reportErrors*/ true);
9366            }
9367
9368            // No type specified and nothing can be inferred
9369            return undefined;
9370        }
9371
9372        function isConstructorDeclaredProperty(symbol: Symbol) {
9373            // A property is considered a constructor declared property when all declaration sites are this.xxx assignments,
9374            // when no declaration sites have JSDoc type annotations, and when at least one declaration site is in the body of
9375            // a class constructor.
9376            if (symbol.valueDeclaration && isBinaryExpression(symbol.valueDeclaration)) {
9377                const links = getSymbolLinks(symbol);
9378                if (links.isConstructorDeclaredProperty === undefined) {
9379                    links.isConstructorDeclaredProperty = false;
9380                    links.isConstructorDeclaredProperty = !!getDeclaringConstructor(symbol) && every(symbol.declarations, declaration =>
9381                        isBinaryExpression(declaration) &&
9382                        isPossiblyAliasedThisProperty(declaration) &&
9383                        (declaration.left.kind !== SyntaxKind.ElementAccessExpression || isStringOrNumericLiteralLike((declaration.left as ElementAccessExpression).argumentExpression)) &&
9384                        !getAnnotatedTypeForAssignmentDeclaration(/*declaredType*/ undefined, declaration, symbol, declaration));
9385                }
9386                return links.isConstructorDeclaredProperty;
9387            }
9388            return false;
9389        }
9390
9391        function isAutoTypedProperty(symbol: Symbol) {
9392            // A property is auto-typed when its declaration has no type annotation or initializer and we're in
9393            // noImplicitAny mode or a .js file.
9394            const declaration = symbol.valueDeclaration;
9395            return declaration && isPropertyDeclaration(declaration) && !getEffectiveTypeAnnotationNode(declaration) &&
9396                !declaration.initializer && (noImplicitAny || isInJSFile(declaration));
9397        }
9398
9399        function getDeclaringConstructor(symbol: Symbol) {
9400            if (!symbol.declarations) {
9401                return;
9402            }
9403            for (const declaration of symbol.declarations) {
9404                const container = getThisContainer(declaration, /*includeArrowFunctions*/ false);
9405                if (container && (container.kind === SyntaxKind.Constructor || isJSConstructor(container))) {
9406                    return container as ConstructorDeclaration;
9407                }
9408            }
9409        }
9410
9411        /** Create a synthetic property access flow node after the last statement of the file */
9412        function getFlowTypeFromCommonJSExport(symbol: Symbol) {
9413            const file = getSourceFileOfNode(symbol.declarations![0]);
9414            const accessName = unescapeLeadingUnderscores(symbol.escapedName);
9415            const areAllModuleExports = symbol.declarations!.every(d => isInJSFile(d) && isAccessExpression(d) && isModuleExportsAccessExpression(d.expression));
9416            const reference = areAllModuleExports
9417                ? factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(factory.createIdentifier("module"), factory.createIdentifier("exports")), accessName)
9418                : factory.createPropertyAccessExpression(factory.createIdentifier("exports"), accessName);
9419            if (areAllModuleExports) {
9420                setParent((reference.expression as PropertyAccessExpression).expression, reference.expression);
9421            }
9422            setParent(reference.expression, reference);
9423            setParent(reference, file);
9424            reference.flowNode = file.endFlowNode;
9425            return getFlowTypeOfReference(reference, autoType, undefinedType);
9426        }
9427
9428        function getFlowTypeInStaticBlocks(symbol: Symbol, staticBlocks: readonly ClassStaticBlockDeclaration[]) {
9429            const accessName = startsWith(symbol.escapedName as string, "__#")
9430                ? factory.createPrivateIdentifier((symbol.escapedName as string).split("@")[1])
9431                : unescapeLeadingUnderscores(symbol.escapedName);
9432            for (const staticBlock of staticBlocks) {
9433                const reference = factory.createPropertyAccessExpression(factory.createThis(), accessName);
9434                setParent(reference.expression, reference);
9435                setParent(reference, staticBlock);
9436                reference.flowNode = staticBlock.returnFlowNode;
9437                const flowType = getFlowTypeOfProperty(reference, symbol);
9438                if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) {
9439                    error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
9440                }
9441                // We don't infer a type if assignments are only null or undefined.
9442                if (everyType(flowType, isNullableType)) {
9443                    continue;
9444                }
9445                return convertAutoToAny(flowType);
9446            }
9447        }
9448
9449        function getFlowTypeInConstructor(symbol: Symbol, constructor: ConstructorDeclaration) {
9450            const accessName = startsWith(symbol.escapedName as string, "__#")
9451                ? factory.createPrivateIdentifier((symbol.escapedName as string).split("@")[1])
9452                : unescapeLeadingUnderscores(symbol.escapedName);
9453            const reference = factory.createPropertyAccessExpression(factory.createThis(), accessName);
9454            setParent(reference.expression, reference);
9455            setParent(reference, constructor);
9456            reference.flowNode = constructor.returnFlowNode;
9457            const flowType = getFlowTypeOfProperty(reference, symbol);
9458            if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) {
9459                error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
9460            }
9461            // We don't infer a type if assignments are only null or undefined.
9462            return everyType(flowType, isNullableType) ? undefined : convertAutoToAny(flowType);
9463        }
9464
9465        function getFlowTypeOfProperty(reference: Node, prop: Symbol | undefined) {
9466            const initialType = prop?.valueDeclaration
9467                && (!isAutoTypedProperty(prop) || getEffectiveModifierFlags(prop.valueDeclaration) & ModifierFlags.Ambient)
9468                && getTypeOfPropertyInBaseClass(prop)
9469                || undefinedType;
9470            return getFlowTypeOfReference(reference, autoType, initialType);
9471        }
9472
9473        function getWidenedTypeForAssignmentDeclaration(symbol: Symbol, resolvedSymbol?: Symbol) {
9474            // function/class/{} initializers are themselves containers, so they won't merge in the same way as other initializers
9475            const container = getAssignedExpandoInitializer(symbol.valueDeclaration);
9476            if (container) {
9477                const tag = getJSDocTypeTag(container);
9478                if (tag && tag.typeExpression) {
9479                    return getTypeFromTypeNode(tag.typeExpression);
9480                }
9481                const containerObjectType = symbol.valueDeclaration && getJSContainerObjectType(symbol.valueDeclaration, symbol, container);
9482                return containerObjectType || getWidenedLiteralType(checkExpressionCached(container));
9483            }
9484            let type;
9485            let definedInConstructor = false;
9486            let definedInMethod = false;
9487            // We use control flow analysis to determine the type of the property if the property qualifies as a constructor
9488            // declared property and the resulting control flow type isn't just undefined or null.
9489            if (isConstructorDeclaredProperty(symbol)) {
9490                type = getFlowTypeInConstructor(symbol, getDeclaringConstructor(symbol)!);
9491            }
9492            if (!type) {
9493                let types: Type[] | undefined;
9494                if (symbol.declarations) {
9495                    let jsdocType: Type | undefined;
9496                    for (const declaration of symbol.declarations) {
9497                        const expression = (isBinaryExpression(declaration) || isCallExpression(declaration)) ? declaration :
9498                            isAccessExpression(declaration) ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration :
9499                            undefined;
9500                        if (!expression) {
9501                            continue; // Non-assignment declaration merged in (eg, an Identifier to mark the thing as a namespace) - skip over it and pull type info from elsewhere
9502                        }
9503
9504                        const kind = isAccessExpression(expression)
9505                            ? getAssignmentDeclarationPropertyAccessKind(expression)
9506                            : getAssignmentDeclarationKind(expression);
9507                        if (kind === AssignmentDeclarationKind.ThisProperty || isBinaryExpression(expression) && isPossiblyAliasedThisProperty(expression, kind)) {
9508                            if (isDeclarationInConstructor(expression)) {
9509                                definedInConstructor = true;
9510                            }
9511                            else {
9512                                definedInMethod = true;
9513                            }
9514                        }
9515                        if (!isCallExpression(expression)) {
9516                            jsdocType = getAnnotatedTypeForAssignmentDeclaration(jsdocType, expression, symbol, declaration);
9517                        }
9518                        if (!jsdocType) {
9519                            (types || (types = [])).push((isBinaryExpression(expression) || isCallExpression(expression)) ? getInitializerTypeFromAssignmentDeclaration(symbol, resolvedSymbol, expression, kind) : neverType);
9520                        }
9521                    }
9522                    type = jsdocType;
9523                }
9524                if (!type) {
9525                    if (!length(types)) {
9526                        return errorType; // No types from any declarations :(
9527                    }
9528                    let constructorTypes = definedInConstructor && symbol.declarations ? getConstructorDefinedThisAssignmentTypes(types!, symbol.declarations) : undefined;
9529                    // use only the constructor types unless they were only assigned null | undefined (including widening variants)
9530                    if (definedInMethod) {
9531                        const propType = getTypeOfPropertyInBaseClass(symbol);
9532                        if (propType) {
9533                            (constructorTypes || (constructorTypes = [])).push(propType);
9534                            definedInConstructor = true;
9535                        }
9536                    }
9537                    const sourceTypes = some(constructorTypes, t => !!(t.flags & ~TypeFlags.Nullable)) ? constructorTypes : types; // TODO: GH#18217
9538                    type = getUnionType(sourceTypes!);
9539                }
9540            }
9541            const widened = getWidenedType(addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor));
9542            if (symbol.valueDeclaration && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) {
9543                reportImplicitAny(symbol.valueDeclaration, anyType);
9544                return anyType;
9545            }
9546            return widened;
9547        }
9548
9549        function getJSContainerObjectType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined {
9550            if (!isInJSFile(decl) || !init || !isObjectLiteralExpression(init) || init.properties.length) {
9551                return undefined;
9552            }
9553            const exports = createSymbolTable();
9554            while (isBinaryExpression(decl) || isPropertyAccessExpression(decl)) {
9555                const s = getSymbolOfNode(decl);
9556                if (s?.exports?.size) {
9557                    mergeSymbolTable(exports, s.exports);
9558                }
9559                decl = isBinaryExpression(decl) ? decl.parent : decl.parent.parent;
9560            }
9561            const s = getSymbolOfNode(decl);
9562            if (s?.exports?.size) {
9563                mergeSymbolTable(exports, s.exports);
9564            }
9565            const type = createAnonymousType(symbol, exports, emptyArray, emptyArray, emptyArray);
9566            type.objectFlags |= ObjectFlags.JSLiteral;
9567            return type;
9568        }
9569
9570        function getAnnotatedTypeForAssignmentDeclaration(declaredType: Type | undefined, expression: Expression, symbol: Symbol, declaration: Declaration) {
9571            const typeNode = getEffectiveTypeAnnotationNode(expression.parent);
9572            if (typeNode) {
9573                const type = getWidenedType(getTypeFromTypeNode(typeNode));
9574                if (!declaredType) {
9575                    return type;
9576                }
9577                else if (!isErrorType(declaredType) && !isErrorType(type) && !isTypeIdenticalTo(declaredType, type)) {
9578                    errorNextVariableOrPropertyDeclarationMustHaveSameType(/*firstDeclaration*/ undefined, declaredType, declaration, type);
9579                }
9580            }
9581            if (symbol.parent?.valueDeclaration) {
9582                const typeNode = getEffectiveTypeAnnotationNode(symbol.parent.valueDeclaration);
9583                if (typeNode) {
9584                    const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName);
9585                    if (annotationSymbol) {
9586                        return getNonMissingTypeOfSymbol(annotationSymbol);
9587                    }
9588                }
9589            }
9590
9591            return declaredType;
9592        }
9593
9594        /** If we don't have an explicit JSDoc type, get the type from the initializer. */
9595        function getInitializerTypeFromAssignmentDeclaration(symbol: Symbol, resolvedSymbol: Symbol | undefined, expression: BinaryExpression | CallExpression, kind: AssignmentDeclarationKind) {
9596            if (isCallExpression(expression)) {
9597                if (resolvedSymbol) {
9598                    return getTypeOfSymbol(resolvedSymbol); // This shouldn't happen except under some hopefully forbidden merges of export assignments and object define assignments
9599                }
9600                const objectLitType = checkExpressionCached((expression as BindableObjectDefinePropertyCall).arguments[2]);
9601                const valueType = getTypeOfPropertyOfType(objectLitType, "value" as __String);
9602                if (valueType) {
9603                    return valueType;
9604                }
9605                const getFunc = getTypeOfPropertyOfType(objectLitType, "get" as __String);
9606                if (getFunc) {
9607                    const getSig = getSingleCallSignature(getFunc);
9608                    if (getSig) {
9609                        return getReturnTypeOfSignature(getSig);
9610                    }
9611                }
9612                const setFunc = getTypeOfPropertyOfType(objectLitType, "set" as __String);
9613                if (setFunc) {
9614                    const setSig = getSingleCallSignature(setFunc);
9615                    if (setSig) {
9616                        return getTypeOfFirstParameterOfSignature(setSig);
9617                    }
9618                }
9619                return anyType;
9620            }
9621            if (containsSameNamedThisProperty(expression.left, expression.right)) {
9622                return anyType;
9623            }
9624            const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression)));
9625            const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol)
9626                : isDirectExport ? getRegularTypeOfLiteralType(checkExpressionCached(expression.right))
9627                : getWidenedLiteralType(checkExpressionCached(expression.right));
9628            if (type.flags & TypeFlags.Object &&
9629                kind === AssignmentDeclarationKind.ModuleExports &&
9630                symbol.escapedName === InternalSymbolName.ExportEquals) {
9631                const exportedType = resolveStructuredTypeMembers(type as ObjectType);
9632                const members = createSymbolTable();
9633                copyEntries(exportedType.members, members);
9634                const initialSize = members.size;
9635                if (resolvedSymbol && !resolvedSymbol.exports) {
9636                    resolvedSymbol.exports = createSymbolTable();
9637                }
9638                (resolvedSymbol || symbol).exports!.forEach((s, name) => {
9639                    const exportedMember = members.get(name)!;
9640                    if (exportedMember && exportedMember !== s && !(s.flags & SymbolFlags.Alias)) {
9641                        if (s.flags & SymbolFlags.Value && exportedMember.flags & SymbolFlags.Value) {
9642                            // If the member has an additional value-like declaration, union the types from the two declarations,
9643                            // but issue an error if they occurred in two different files. The purpose is to support a JS file with
9644                            // a pattern like:
9645                            //
9646                            // module.exports = { a: true };
9647                            // module.exports.a = 3;
9648                            //
9649                            // but we may have a JS file with `module.exports = { a: true }` along with a TypeScript module augmentation
9650                            // declaring an `export const a: number`. In that case, we issue a duplicate identifier error, because
9651                            // it's unclear what that's supposed to mean, so it's probably a mistake.
9652                            if (s.valueDeclaration && exportedMember.valueDeclaration && getSourceFileOfNode(s.valueDeclaration) !== getSourceFileOfNode(exportedMember.valueDeclaration)) {
9653                                const unescapedName = unescapeLeadingUnderscores(s.escapedName);
9654                                const exportedMemberName = tryCast(exportedMember.valueDeclaration, isNamedDeclaration)?.name || exportedMember.valueDeclaration;
9655                                addRelatedInfo(
9656                                    error(s.valueDeclaration, Diagnostics.Duplicate_identifier_0, unescapedName),
9657                                    createDiagnosticForNode(exportedMemberName, Diagnostics._0_was_also_declared_here, unescapedName));
9658                                addRelatedInfo(
9659                                    error(exportedMemberName, Diagnostics.Duplicate_identifier_0, unescapedName),
9660                                    createDiagnosticForNode(s.valueDeclaration, Diagnostics._0_was_also_declared_here, unescapedName));
9661                            }
9662                            const union = createSymbol(s.flags | exportedMember.flags, name);
9663                            union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]);
9664                            union.valueDeclaration = exportedMember.valueDeclaration;
9665                            union.declarations = concatenate(exportedMember.declarations, s.declarations);
9666                            members.set(name, union);
9667                        }
9668                        else {
9669                            members.set(name, mergeSymbol(s, exportedMember));
9670                        }
9671                    }
9672                    else {
9673                        members.set(name, s);
9674                    }
9675                });
9676                const result = createAnonymousType(
9677                    initialSize !== members.size ? undefined : exportedType.symbol, // Only set the type's symbol if it looks to be the same as the original type
9678                    members,
9679                    exportedType.callSignatures,
9680                    exportedType.constructSignatures,
9681                    exportedType.indexInfos);
9682                if (initialSize === members.size) {
9683                    if (type.aliasSymbol) {
9684                        result.aliasSymbol = type.aliasSymbol;
9685                        result.aliasTypeArguments = type.aliasTypeArguments;
9686                    }
9687                    if (getObjectFlags(type) & ObjectFlags.Reference) {
9688                        result.aliasSymbol = (type as TypeReference).symbol;
9689                        const args = getTypeArguments(type as TypeReference);
9690                        result.aliasTypeArguments = length(args) ? args : undefined;
9691                    }
9692                }
9693                result.objectFlags |= (getObjectFlags(type) & ObjectFlags.JSLiteral); // Propagate JSLiteral flag
9694                if (result.symbol && result.symbol.flags & SymbolFlags.Class && type === getDeclaredTypeOfClassOrInterface(result.symbol)) {
9695                    result.objectFlags |= ObjectFlags.IsClassInstanceClone; // Propagate the knowledge that this type is equivalent to the symbol's class instance type
9696                }
9697                return result;
9698            }
9699            if (isEmptyArrayLiteralType(type)) {
9700                reportImplicitAny(expression, anyArrayType);
9701                return anyArrayType;
9702            }
9703            return type;
9704        }
9705
9706        function containsSameNamedThisProperty(thisProperty: Expression, expression: Expression) {
9707            return isPropertyAccessExpression(thisProperty)
9708                && thisProperty.expression.kind === SyntaxKind.ThisKeyword
9709                && forEachChildRecursively(expression, n => isMatchingReference(thisProperty, n));
9710        }
9711
9712        function isDeclarationInConstructor(expression: Expression) {
9713            const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
9714            // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added.
9715            // Function expressions that are assigned to the prototype count as methods.
9716            return thisContainer.kind === SyntaxKind.Constructor ||
9717                thisContainer.kind === SyntaxKind.FunctionDeclaration ||
9718                (thisContainer.kind === SyntaxKind.FunctionExpression && !isPrototypePropertyAssignment(thisContainer.parent));
9719        }
9720
9721        function getConstructorDefinedThisAssignmentTypes(types: Type[], declarations: Declaration[]): Type[] | undefined {
9722            Debug.assert(types.length === declarations.length);
9723            return types.filter((_, i) => {
9724                const declaration = declarations[i];
9725                const expression = isBinaryExpression(declaration) ? declaration :
9726                    isBinaryExpression(declaration.parent) ? declaration.parent : undefined;
9727                return expression && isDeclarationInConstructor(expression);
9728            });
9729        }
9730
9731        // Return the type implied by a binding pattern element. This is the type of the initializer of the element if
9732        // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding
9733        // pattern. Otherwise, it is the type any.
9734        function getTypeFromBindingElement(element: BindingElement, includePatternInType?: boolean, reportErrors?: boolean): Type {
9735            if (element.initializer) {
9736                // The type implied by a binding pattern is independent of context, so we check the initializer with no
9737                // contextual type or, if the element itself is a binding pattern, with the type implied by that binding
9738                // pattern.
9739                const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType;
9740                return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType)));
9741            }
9742            if (isBindingPattern(element.name)) {
9743                return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors);
9744            }
9745            if (reportErrors && !declarationBelongsToPrivateAmbientMember(element)) {
9746                reportImplicitAny(element, anyType);
9747            }
9748            // When we're including the pattern in the type (an indication we're obtaining a contextual type), we
9749            // use a non-inferrable any type. Inference will never directly infer this type, but it is possible
9750            // to infer a type that contains it, e.g. for a binding pattern like [foo] or { foo }. In such cases,
9751            // widening of the binding pattern type substitutes a regular any for the non-inferrable any.
9752            return includePatternInType ? nonInferrableAnyType : anyType;
9753        }
9754
9755        // Return the type implied by an object binding pattern
9756        function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
9757            const members = createSymbolTable();
9758            let stringIndexInfo: IndexInfo | undefined;
9759            let objectFlags = ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral;
9760            forEach(pattern.elements, e => {
9761                const name = e.propertyName || e.name as Identifier;
9762                if (e.dotDotDotToken) {
9763                    stringIndexInfo = createIndexInfo(stringType, anyType, /*isReadonly*/ false);
9764                    return;
9765                }
9766
9767                const exprType = getLiteralTypeFromPropertyName(name);
9768                if (!isTypeUsableAsPropertyName(exprType)) {
9769                    // do not include computed properties in the implied type
9770                    objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
9771                    return;
9772                }
9773                const text = getPropertyNameFromType(exprType);
9774                const flags = SymbolFlags.Property | (e.initializer ? SymbolFlags.Optional : 0);
9775                const symbol = createSymbol(flags, text);
9776                symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors);
9777                symbol.bindingElement = e;
9778                members.set(symbol.escapedName, symbol);
9779            });
9780            const result = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo ? [stringIndexInfo] : emptyArray);
9781            result.objectFlags |= objectFlags;
9782            if (includePatternInType) {
9783                result.pattern = pattern;
9784                result.objectFlags |= ObjectFlags.ContainsObjectOrArrayLiteral;
9785            }
9786            return result;
9787        }
9788
9789        // Return the type implied by an array binding pattern
9790        function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
9791            const elements = pattern.elements;
9792            const lastElement = lastOrUndefined(elements);
9793            const restElement = lastElement && lastElement.kind === SyntaxKind.BindingElement && lastElement.dotDotDotToken ? lastElement : undefined;
9794            if (elements.length === 0 || elements.length === 1 && restElement) {
9795                return languageVersion >= ScriptTarget.ES2015 ? createIterableType(anyType) : anyArrayType;
9796            }
9797            const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors));
9798            const minLength = findLastIndex(elements, e => !(e === restElement || isOmittedExpression(e) || hasDefaultValue(e)), elements.length - 1) + 1;
9799            const elementFlags = map(elements, (e, i) => e === restElement ? ElementFlags.Rest : i >= minLength ? ElementFlags.Optional : ElementFlags.Required);
9800            let result = createTupleType(elementTypes, elementFlags) as TypeReference;
9801            if (includePatternInType) {
9802                result = cloneTypeReference(result);
9803                result.pattern = pattern;
9804                result.objectFlags |= ObjectFlags.ContainsObjectOrArrayLiteral;
9805            }
9806            return result;
9807        }
9808
9809        // Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
9810        // and without regard to its context (i.e. without regard any type annotation or initializer associated with the
9811        // declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any]
9812        // and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is
9813        // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring
9814        // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of
9815        // the parameter.
9816        function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType = false, reportErrors = false): Type {
9817            return pattern.kind === SyntaxKind.ObjectBindingPattern
9818                ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors)
9819                : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors);
9820        }
9821
9822        // Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type
9823        // specified in a type annotation or inferred from an initializer. However, in the case of a destructuring declaration it
9824        // is a bit more involved. For example:
9825        //
9826        //   var [x, s = ""] = [1, "one"];
9827        //
9828        // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the
9829        // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the
9830        // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string.
9831        function getWidenedTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | AnnotationPropertyDeclaration | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, reportErrors?: boolean): Type {
9832            return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), declaration, reportErrors);
9833        }
9834
9835        function isGlobalSymbolConstructor(node: Node) {
9836            const symbol = getSymbolOfNode(node);
9837            const globalSymbol = getGlobalESSymbolConstructorTypeSymbol(/*reportErrors*/ false);
9838            return globalSymbol && symbol && symbol === globalSymbol;
9839        }
9840
9841        function widenTypeForVariableLikeDeclaration(type: Type | undefined, declaration: any, reportErrors?: boolean) {
9842            if (type) {
9843                // TODO: If back compat with pre-3.0/4.0 libs isn't required, remove the following SymbolConstructor special case transforming `symbol` into `unique symbol`
9844                if (type.flags & TypeFlags.ESSymbol && isGlobalSymbolConstructor(declaration.parent)) {
9845                    type = getESSymbolLikeTypeForNode(declaration);
9846                }
9847                if (reportErrors) {
9848                    reportErrorsFromWidening(declaration, type);
9849                }
9850
9851                // always widen a 'unique symbol' type if the type was created for a different declaration.
9852                if (type.flags & TypeFlags.UniqueESSymbol && (isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) {
9853                    type = esSymbolType;
9854                }
9855
9856                return getWidenedType(type);
9857            }
9858
9859            // Rest parameters default to type any[], other parameters default to type any
9860            type = isParameter(declaration) && declaration.dotDotDotToken ? anyArrayType : anyType;
9861
9862            // Report implicit any errors unless this is a private property within an ambient declaration
9863            if (reportErrors) {
9864                if (!declarationBelongsToPrivateAmbientMember(declaration)) {
9865                    reportImplicitAny(declaration, type);
9866                }
9867            }
9868            return type;
9869        }
9870
9871        function declarationBelongsToPrivateAmbientMember(declaration: VariableLikeDeclaration) {
9872            const root = getRootDeclaration(declaration);
9873            const memberDeclaration = root.kind === SyntaxKind.Parameter ? root.parent : root;
9874            return isPrivateWithinAmbient(memberDeclaration);
9875        }
9876
9877        function tryGetTypeFromEffectiveTypeNode(node: Node) {
9878            const typeNode = getEffectiveTypeAnnotationNode(node);
9879            if (typeNode) {
9880                return getTypeFromTypeNode(typeNode);
9881            }
9882        }
9883
9884        function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type {
9885            const links = getSymbolLinks(symbol);
9886            if (!links.type) {
9887                const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol);
9888                // For a contextually typed parameter it is possible that a type has already
9889                // been assigned (in assignTypeToParameterAndFixTypeParameters), and we want
9890                // to preserve this type.
9891                if (!links.type) {
9892                    links.type = type;
9893                }
9894            }
9895            return links.type;
9896        }
9897
9898        function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol): Type {
9899            // Handle prototype property
9900            if (symbol.flags & SymbolFlags.Prototype) {
9901                return getTypeOfPrototypeProperty(symbol);
9902            }
9903            // CommonsJS require and module both have type any.
9904            if (symbol === requireSymbol) {
9905                return anyType;
9906            }
9907            if (symbol.flags & SymbolFlags.ModuleExports && symbol.valueDeclaration) {
9908                const fileSymbol = getSymbolOfNode(getSourceFileOfNode(symbol.valueDeclaration));
9909                const result = createSymbol(fileSymbol.flags, "exports" as __String);
9910                result.declarations = fileSymbol.declarations ? fileSymbol.declarations.slice() : [];
9911                result.parent = symbol;
9912                result.target = fileSymbol;
9913                if (fileSymbol.valueDeclaration) result.valueDeclaration = fileSymbol.valueDeclaration;
9914                if (fileSymbol.members) result.members = new Map(fileSymbol.members);
9915                if (fileSymbol.exports) result.exports = new Map(fileSymbol.exports);
9916                const members = createSymbolTable();
9917                members.set("exports" as __String, result);
9918                return createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray);
9919            }
9920            // Handle catch clause variables
9921            Debug.assertIsDefined(symbol.valueDeclaration);
9922            const declaration = symbol.valueDeclaration;
9923            if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
9924                const typeNode = getEffectiveTypeAnnotationNode(declaration);
9925                if (typeNode === undefined) {
9926                    return useUnknownInCatchVariables ? unknownType : anyType;
9927                }
9928                const type = getTypeOfNode(typeNode);
9929                // an errorType will make `checkTryStatement` issue an error
9930                return isTypeAny(type) || type === unknownType ? type : errorType;
9931            }
9932            // Handle export default expressions
9933            if (isSourceFile(declaration) && isJsonSourceFile(declaration)) {
9934                if (!declaration.statements.length) {
9935                    return emptyObjectType;
9936                }
9937                return getWidenedType(getWidenedLiteralType(checkExpression(declaration.statements[0].expression)));
9938            }
9939            if (isAccessor(declaration)) {
9940                // Binding of certain patterns in JS code will occasionally mark symbols as both properties
9941                // and accessors. Here we dispatch to accessor resolution if needed.
9942                return getTypeOfAccessors(symbol);
9943            }
9944
9945            // Handle variable, parameter or property
9946            if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
9947                // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty`
9948                if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) {
9949                    return getTypeOfFuncClassEnumModule(symbol);
9950                }
9951                return reportCircularityError(symbol);
9952            }
9953            let type: Type;
9954            if (declaration.kind === SyntaxKind.ExportAssignment) {
9955                type = widenTypeForVariableLikeDeclaration(tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionCached((declaration as ExportAssignment).expression), declaration);
9956            }
9957            else if (
9958                isBinaryExpression(declaration) ||
9959                (isInJSFile(declaration) &&
9960                (isCallExpression(declaration) || (isPropertyAccessExpression(declaration) || isBindableStaticElementAccessExpression(declaration)) && isBinaryExpression(declaration.parent)))) {
9961                type = getWidenedTypeForAssignmentDeclaration(symbol);
9962            }
9963            else if (isPropertyAccessExpression(declaration)
9964                || isElementAccessExpression(declaration)
9965                || isIdentifier(declaration)
9966                || isStringLiteralLike(declaration)
9967                || isNumericLiteral(declaration)
9968                || isClassDeclaration(declaration)
9969                || isFunctionDeclaration(declaration)
9970                || (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration))
9971                || isMethodSignature(declaration)
9972                || isSourceFile(declaration)) {
9973                // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty`
9974                if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
9975                    return getTypeOfFuncClassEnumModule(symbol);
9976                }
9977                type = isBinaryExpression(declaration.parent) ?
9978                    getWidenedTypeForAssignmentDeclaration(symbol) :
9979                    tryGetTypeFromEffectiveTypeNode(declaration) || anyType;
9980            }
9981            else if (isPropertyAssignment(declaration)) {
9982                type = tryGetTypeFromEffectiveTypeNode(declaration) || checkPropertyAssignment(declaration);
9983            }
9984            else if (isJsxAttribute(declaration)) {
9985                type = tryGetTypeFromEffectiveTypeNode(declaration) || checkJsxAttribute(declaration);
9986            }
9987            else if (isShorthandPropertyAssignment(declaration)) {
9988                type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, CheckMode.Normal);
9989            }
9990            else if (isObjectLiteralMethod(declaration)) {
9991                type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, CheckMode.Normal);
9992            }
9993            else if (isParameter(declaration)
9994                     || isPropertyDeclaration(declaration)
9995                     || isPropertySignature(declaration)
9996                     || isAnnotationPropertyDeclaration(declaration)
9997                     || isVariableDeclaration(declaration)
9998                     || isBindingElement(declaration)
9999                     || isJSDocPropertyLikeTag(declaration)) {
10000                type = getWidenedTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true);
10001            }
10002            // getTypeOfSymbol dispatches some JS merges incorrectly because their symbol flags are not mutually exclusive.
10003            // Re-dispatch based on valueDeclaration.kind instead.
10004            else if (isEnumDeclaration(declaration)) {
10005                type = getTypeOfFuncClassEnumModule(symbol);
10006            }
10007            else if (isEnumMember(declaration)) {
10008                type = getTypeOfEnumMember(symbol);
10009            }
10010            else {
10011                return Debug.fail("Unhandled declaration kind! " + Debug.formatSyntaxKind(declaration.kind) + " for " + Debug.formatSymbol(symbol));
10012            }
10013
10014            if (!popTypeResolution()) {
10015                // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty`
10016                if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) {
10017                    return getTypeOfFuncClassEnumModule(symbol);
10018                }
10019                return reportCircularityError(symbol);
10020            }
10021            return type;
10022        }
10023
10024        function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | PropertyDeclaration | undefined): TypeNode | undefined {
10025            if (accessor) {
10026                switch (accessor.kind) {
10027                    case SyntaxKind.GetAccessor:
10028                        const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor);
10029                        return getterTypeAnnotation;
10030                    case SyntaxKind.SetAccessor:
10031                        const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor);
10032                        return setterTypeAnnotation;
10033                    case SyntaxKind.PropertyDeclaration:
10034                        Debug.assert(hasAccessorModifier(accessor));
10035                        const accessorTypeAnnotation = getEffectiveTypeAnnotationNode(accessor);
10036                        return accessorTypeAnnotation;
10037                }
10038            }
10039            return undefined;
10040        }
10041
10042        function getAnnotatedAccessorType(accessor: AccessorDeclaration | PropertyDeclaration | undefined): Type | undefined {
10043            const node = getAnnotatedAccessorTypeNode(accessor);
10044            return node && getTypeFromTypeNode(node);
10045        }
10046
10047        function getAnnotatedAccessorThisParameter(accessor: AccessorDeclaration): Symbol | undefined {
10048            const parameter = getAccessorThisParameter(accessor);
10049            return parameter && parameter.symbol;
10050        }
10051
10052        function getThisTypeOfDeclaration(declaration: SignatureDeclaration): Type | undefined {
10053            return getThisTypeOfSignature(getSignatureFromDeclaration(declaration));
10054        }
10055
10056        function getTypeOfAccessors(symbol: Symbol): Type {
10057            const links = getSymbolLinks(symbol);
10058            if (!links.type) {
10059                if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
10060                    return errorType;
10061                }
10062                const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
10063                const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
10064                const accessor = tryCast(getDeclarationOfKind<PropertyDeclaration>(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration);
10065
10066                // We try to resolve a getter type annotation, a setter type annotation, or a getter function
10067                // body return type inference, in that order.
10068                let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) ||
10069                    getAnnotatedAccessorType(getter) ||
10070                    getAnnotatedAccessorType(setter) ||
10071                    getAnnotatedAccessorType(accessor) ||
10072                    getter && getter.body && getReturnTypeFromBody(getter) ||
10073                    accessor && accessor.initializer && getWidenedTypeForVariableLikeDeclaration(accessor, /*includeOptionality*/ true);
10074                if (!type) {
10075                    if (setter && !isPrivateWithinAmbient(setter)) {
10076                        errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
10077                    }
10078                    else if (getter && !isPrivateWithinAmbient(getter)) {
10079                        errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
10080                    }
10081                    else if (accessor && !isPrivateWithinAmbient(accessor)) {
10082                        errorOrSuggestion(noImplicitAny, accessor, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), "any");
10083                    }
10084                    type = anyType;
10085                }
10086                if (!popTypeResolution()) {
10087                    if (getAnnotatedAccessorTypeNode(getter)) {
10088                        error(getter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
10089                    }
10090                    else if (getAnnotatedAccessorTypeNode(setter)) {
10091                        error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
10092                    }
10093                    else if (getAnnotatedAccessorTypeNode(accessor)) {
10094                        error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
10095                    }
10096                    else if (getter && noImplicitAny) {
10097                        error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
10098                    }
10099                    type = anyType;
10100                }
10101                links.type = type;
10102            }
10103            return links.type;
10104        }
10105
10106        function getWriteTypeOfAccessors(symbol: Symbol): Type {
10107            const links = getSymbolLinks(symbol);
10108            if (!links.writeType) {
10109                if (!pushTypeResolution(symbol, TypeSystemPropertyName.WriteType)) {
10110                    return errorType;
10111                }
10112
10113                const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor)
10114                    ?? tryCast(getDeclarationOfKind<PropertyDeclaration>(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration);
10115                let writeType = getAnnotatedAccessorType(setter);
10116                if (!popTypeResolution()) {
10117                    if (getAnnotatedAccessorTypeNode(setter)) {
10118                        error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
10119                    }
10120                    writeType = anyType;
10121                }
10122                // Absent an explicit setter type annotation we use the read type of the accessor.
10123                links.writeType = writeType || getTypeOfAccessors(symbol);
10124            }
10125            return links.writeType;
10126        }
10127
10128        function getBaseTypeVariableOfClass(symbol: Symbol) {
10129            const baseConstructorType = getBaseConstructorTypeOfClass(getDeclaredTypeOfClassOrInterface(symbol));
10130            return baseConstructorType.flags & TypeFlags.TypeVariable ? baseConstructorType :
10131                baseConstructorType.flags & TypeFlags.Intersection ? find((baseConstructorType as IntersectionType).types, t => !!(t.flags & TypeFlags.TypeVariable)) :
10132                undefined;
10133        }
10134
10135        function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
10136            let links = getSymbolLinks(symbol);
10137            const originalLinks = links;
10138            if (!links.type) {
10139                const expando = symbol.valueDeclaration && getSymbolOfExpando(symbol.valueDeclaration, /*allowDeclaration*/ false);
10140                if (expando) {
10141                    const merged = mergeJSSymbols(symbol, expando);
10142                    if (merged) {
10143                        // note:we overwrite links because we just cloned the symbol
10144                        symbol = links = merged;
10145                    }
10146                }
10147                originalLinks.type = links.type = getTypeOfFuncClassEnumModuleWorker(symbol);
10148            }
10149            return links.type;
10150        }
10151
10152        function getTypeOfFuncClassEnumModuleWorker(symbol: Symbol): Type {
10153            const declaration = symbol.valueDeclaration;
10154            if (symbol.flags & SymbolFlags.Module && isShorthandAmbientModuleSymbol(symbol)) {
10155                return anyType;
10156            }
10157            else if (declaration && (declaration.kind === SyntaxKind.BinaryExpression ||
10158                     isAccessExpression(declaration) &&
10159                     declaration.parent.kind === SyntaxKind.BinaryExpression)) {
10160                return getWidenedTypeForAssignmentDeclaration(symbol);
10161            }
10162            else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && declaration.commonJsModuleIndicator) {
10163                const resolvedModule = resolveExternalModuleSymbol(symbol);
10164                if (resolvedModule !== symbol) {
10165                    if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
10166                        return errorType;
10167                    }
10168                    const exportEquals = getMergedSymbol(symbol.exports!.get(InternalSymbolName.ExportEquals)!);
10169                    const type = getWidenedTypeForAssignmentDeclaration(exportEquals, exportEquals === resolvedModule ? undefined : resolvedModule);
10170                    if (!popTypeResolution()) {
10171                        return reportCircularityError(symbol);
10172                    }
10173                    return type;
10174                }
10175            }
10176            const type = createObjectType(ObjectFlags.Anonymous, symbol);
10177            if (symbol.flags & SymbolFlags.Class) {
10178                const baseTypeVariable = getBaseTypeVariableOfClass(symbol);
10179                return baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type;
10180            }
10181            else {
10182                return strictNullChecks && symbol.flags & SymbolFlags.Optional ? getOptionalType(type) : type;
10183            }
10184        }
10185
10186        function getTypeOfEnumMember(symbol: Symbol): Type {
10187            const links = getSymbolLinks(symbol);
10188            return links.type || (links.type = getDeclaredTypeOfEnumMember(symbol));
10189        }
10190
10191        function getTypeOfAlias(symbol: Symbol): Type {
10192            const links = getSymbolLinks(symbol);
10193            if (!links.type) {
10194                const targetSymbol = resolveAlias(symbol);
10195                const exportSymbol = symbol.declarations && getTargetOfAliasDeclaration(getDeclarationOfAliasSymbol(symbol)!, /*dontResolveAlias*/ true);
10196                const declaredType = firstDefined(exportSymbol?.declarations, d => isExportAssignment(d) ? tryGetTypeFromEffectiveTypeNode(d) : undefined);
10197                // It only makes sense to get the type of a value symbol. If the result of resolving
10198                // the alias is not a value, then it has no type. To get the type associated with a
10199                // type symbol, call getDeclaredTypeOfSymbol.
10200                // This check is important because without it, a call to getTypeOfSymbol could end
10201                // up recursively calling getTypeOfAlias, causing a stack overflow.
10202                links.type = exportSymbol?.declarations && isDuplicatedCommonJSExport(exportSymbol.declarations) && symbol.declarations!.length ? getFlowTypeFromCommonJSExport(exportSymbol)
10203                    : isDuplicatedCommonJSExport(symbol.declarations) ? autoType
10204                    : declaredType ? declaredType
10205                    : getAllSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol)
10206                    : errorType;
10207            }
10208            return links.type;
10209        }
10210
10211        function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
10212            const links = getSymbolLinks(symbol);
10213            return links.type || (links.type = instantiateType(getTypeOfSymbol(links.target!), links.mapper));
10214        }
10215
10216        function getWriteTypeOfInstantiatedSymbol(symbol: Symbol): Type {
10217            const links = getSymbolLinks(symbol);
10218            return links.writeType || (links.writeType = instantiateType(getWriteTypeOfSymbol(links.target!), links.mapper));
10219        }
10220
10221        function reportCircularityError(symbol: Symbol) {
10222            const declaration = symbol.valueDeclaration as VariableLikeDeclaration;
10223            // Check if variable has type annotation that circularly references the variable itself
10224            if (getEffectiveTypeAnnotationNode(declaration)) {
10225                error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
10226                    symbolToString(symbol));
10227                return errorType;
10228            }
10229            // Check if variable has initializer that circularly references the variable itself
10230            if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) {
10231                error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
10232                    symbolToString(symbol));
10233            }
10234            // Circularities could also result from parameters in function expressions that end up
10235            // having themselves as contextual types following type argument inference. In those cases
10236            // we have already reported an implicit any error so we don't report anything here.
10237            return anyType;
10238        }
10239
10240        function getTypeOfSymbolWithDeferredType(symbol: Symbol) {
10241            const links = getSymbolLinks(symbol);
10242            if (!links.type) {
10243                Debug.assertIsDefined(links.deferralParent);
10244                Debug.assertIsDefined(links.deferralConstituents);
10245                links.type = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralConstituents) : getIntersectionType(links.deferralConstituents);
10246            }
10247            return links.type;
10248        }
10249
10250        function getWriteTypeOfSymbolWithDeferredType(symbol: Symbol): Type | undefined {
10251            const links = getSymbolLinks(symbol);
10252            if (!links.writeType && links.deferralWriteConstituents) {
10253                Debug.assertIsDefined(links.deferralParent);
10254                Debug.assertIsDefined(links.deferralConstituents);
10255                links.writeType = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents);
10256            }
10257            return links.writeType;
10258        }
10259
10260        /**
10261         * Distinct write types come only from set accessors, but synthetic union and intersection
10262         * properties deriving from set accessors will either pre-compute or defer the union or
10263         * intersection of the writeTypes of their constituents.
10264         */
10265        function getWriteTypeOfSymbol(symbol: Symbol): Type {
10266            const checkFlags = getCheckFlags(symbol);
10267            if (symbol.flags & SymbolFlags.Property) {
10268                return checkFlags & CheckFlags.SyntheticProperty ?
10269                    checkFlags & CheckFlags.DeferredType ?
10270                        getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
10271                        (symbol as TransientSymbol).writeType || (symbol as TransientSymbol).type! :
10272                    getTypeOfSymbol(symbol);
10273            }
10274            if (symbol.flags & SymbolFlags.Accessor) {
10275                return checkFlags & CheckFlags.Instantiated ?
10276                    getWriteTypeOfInstantiatedSymbol(symbol) :
10277                    getWriteTypeOfAccessors(symbol);
10278            }
10279            return getTypeOfSymbol(symbol);
10280        }
10281
10282        function getTypeOfSymbol(symbol: Symbol): Type {
10283            const checkFlags = getCheckFlags(symbol);
10284            if (checkFlags & CheckFlags.DeferredType) {
10285                return getTypeOfSymbolWithDeferredType(symbol);
10286            }
10287            if (checkFlags & CheckFlags.Instantiated) {
10288                return getTypeOfInstantiatedSymbol(symbol);
10289            }
10290            if (checkFlags & CheckFlags.Mapped) {
10291                return getTypeOfMappedSymbol(symbol as MappedSymbol);
10292            }
10293            if (checkFlags & CheckFlags.ReverseMapped) {
10294                return getTypeOfReverseMappedSymbol(symbol as ReverseMappedSymbol);
10295            }
10296            if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
10297                return getTypeOfVariableOrParameterOrProperty(symbol);
10298            }
10299            if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
10300                return getTypeOfFuncClassEnumModule(symbol);
10301            }
10302            if (symbol.flags & SymbolFlags.EnumMember) {
10303                return getTypeOfEnumMember(symbol);
10304            }
10305            if (symbol.flags & SymbolFlags.Accessor) {
10306                return getTypeOfAccessors(symbol);
10307            }
10308            if (symbol.flags & SymbolFlags.Alias) {
10309                return getTypeOfAlias(symbol);
10310            }
10311            return errorType;
10312        }
10313
10314        function getNonMissingTypeOfSymbol(symbol: Symbol) {
10315            return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
10316        }
10317
10318        function isReferenceToType(type: Type, target: Type) {
10319            return type !== undefined
10320                && target !== undefined
10321                && (getObjectFlags(type) & ObjectFlags.Reference) !== 0
10322                && (type as TypeReference).target === target;
10323        }
10324
10325        function getTargetType(type: Type): Type {
10326            return getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target : type;
10327        }
10328
10329        // TODO: GH#18217 If `checkBase` is undefined, we should not call this because this will always return false.
10330        function hasBaseType(type: Type, checkBase: Type | undefined) {
10331            return check(type);
10332            function check(type: Type): boolean {
10333                if (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
10334                    const target = getTargetType(type) as InterfaceType;
10335                    return target === checkBase || some(getBaseTypes(target), check);
10336                }
10337                else if (type.flags & TypeFlags.Intersection) {
10338                    return some((type as IntersectionType).types, check);
10339                }
10340                return false;
10341            }
10342        }
10343
10344        // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set.
10345        // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set
10346        // in-place and returns the same array.
10347        function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: readonly TypeParameterDeclaration[]): TypeParameter[] | undefined {
10348            for (const declaration of declarations) {
10349                typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration)));
10350            }
10351            return typeParameters;
10352        }
10353
10354        // Return the outer type parameters of a node or undefined if the node has no outer type parameters.
10355        function getOuterTypeParameters(node: Node, includeThisTypes?: boolean): TypeParameter[] | undefined {
10356            while (true) {
10357                node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead
10358                if (node && isBinaryExpression(node)) {
10359                    // prototype assignments get the outer type parameters of their constructor function
10360                    const assignmentKind = getAssignmentDeclarationKind(node);
10361                    if (assignmentKind === AssignmentDeclarationKind.Prototype || assignmentKind === AssignmentDeclarationKind.PrototypeProperty) {
10362                        const symbol = getSymbolOfNode(node.left);
10363                        if (symbol && symbol.parent && !findAncestor(symbol.parent.valueDeclaration, d => node === d)) {
10364                            node = symbol.parent.valueDeclaration!;
10365                        }
10366                    }
10367                }
10368                if (!node) {
10369                    return undefined;
10370                }
10371                switch (node.kind) {
10372                    case SyntaxKind.ClassDeclaration:
10373                    case SyntaxKind.ClassExpression:
10374                    case SyntaxKind.InterfaceDeclaration:
10375                    case SyntaxKind.CallSignature:
10376                    case SyntaxKind.ConstructSignature:
10377                    case SyntaxKind.MethodSignature:
10378                    case SyntaxKind.FunctionType:
10379                    case SyntaxKind.ConstructorType:
10380                    case SyntaxKind.JSDocFunctionType:
10381                    case SyntaxKind.FunctionDeclaration:
10382                    case SyntaxKind.MethodDeclaration:
10383                    case SyntaxKind.FunctionExpression:
10384                    case SyntaxKind.ArrowFunction:
10385                    case SyntaxKind.TypeAliasDeclaration:
10386                    case SyntaxKind.JSDocTemplateTag:
10387                    case SyntaxKind.JSDocTypedefTag:
10388                    case SyntaxKind.JSDocEnumTag:
10389                    case SyntaxKind.JSDocCallbackTag:
10390                    case SyntaxKind.MappedType:
10391                    case SyntaxKind.ConditionalType: {
10392                        const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
10393                        if (node.kind === SyntaxKind.MappedType) {
10394                            return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node as MappedTypeNode).typeParameter)));
10395                        }
10396                        else if (node.kind === SyntaxKind.ConditionalType) {
10397                            return concatenate(outerTypeParameters, getInferTypeParameters(node as ConditionalTypeNode));
10398                        }
10399                        const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters));
10400                        const thisType = includeThisTypes &&
10401                            (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
10402                            getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType;
10403                        return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
10404                    }
10405                    case SyntaxKind.JSDocParameterTag:
10406                        const paramSymbol = getParameterSymbolFromJSDoc(node as JSDocParameterTag);
10407                        if (paramSymbol) {
10408                            node = paramSymbol.valueDeclaration!;
10409                        }
10410                        break;
10411                    case SyntaxKind.JSDoc: {
10412                        const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
10413                        return (node as JSDoc).tags
10414                            ? appendTypeParameters(outerTypeParameters, flatMap((node as JSDoc).tags, t => isJSDocTemplateTag(t) ? t.typeParameters : undefined))
10415                            : outerTypeParameters;
10416                    }
10417                }
10418            }
10419        }
10420
10421        // The outer type parameters are those defined by enclosing generic classes, methods, or functions.
10422        function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined {
10423            const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration)!;
10424            Debug.assert(!!declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations");
10425            return getOuterTypeParameters(declaration);
10426        }
10427
10428        // The local type parameters are the combined set of type parameters from all declarations of the class,
10429        // interface, or type alias.
10430        function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] | undefined {
10431            if (!symbol.declarations) {
10432                return;
10433            }
10434            let result: TypeParameter[] | undefined;
10435            for (const node of symbol.declarations) {
10436                if (node.kind === SyntaxKind.InterfaceDeclaration ||
10437                    node.kind === SyntaxKind.ClassDeclaration ||
10438                    node.kind === SyntaxKind.ClassExpression ||
10439                    isJSConstructor(node) ||
10440                    isTypeAlias(node)) {
10441                    const declaration = node as InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag;
10442                    result = appendTypeParameters(result, getEffectiveTypeParameterDeclarations(declaration));
10443                }
10444            }
10445            return result;
10446        }
10447
10448        // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus
10449        // its locally declared type parameters.
10450        function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined {
10451            return concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol));
10452        }
10453
10454        // A type is a mixin constructor if it has a single construct signature taking no type parameters and a single
10455        // rest parameter of type any[].
10456        function isMixinConstructorType(type: Type) {
10457            const signatures = getSignaturesOfType(type, SignatureKind.Construct);
10458            if (signatures.length === 1) {
10459                const s = signatures[0];
10460                if (!s.typeParameters && s.parameters.length === 1 && signatureHasRestParameter(s)) {
10461                    const paramType = getTypeOfParameter(s.parameters[0]);
10462                    return isTypeAny(paramType) || getElementTypeOfArrayType(paramType) === anyType;
10463                }
10464            }
10465            return false;
10466        }
10467
10468        function isConstructorType(type: Type): boolean {
10469            if (getSignaturesOfType(type, SignatureKind.Construct).length > 0) {
10470                return true;
10471            }
10472            if (type.flags & TypeFlags.TypeVariable) {
10473                const constraint = getBaseConstraintOfType(type);
10474                return !!constraint && isMixinConstructorType(constraint);
10475            }
10476            return false;
10477        }
10478
10479        function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined {
10480            const decl = getClassLikeDeclarationOfSymbol(type.symbol);
10481            return decl && getEffectiveBaseTypeNode(decl);
10482        }
10483
10484        function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: readonly TypeNode[] | undefined, location: Node): readonly Signature[] {
10485            const typeArgCount = length(typeArgumentNodes);
10486            const isJavascript = isInJSFile(location);
10487            return filter(getSignaturesOfType(type, SignatureKind.Construct),
10488                sig => (isJavascript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= length(sig.typeParameters));
10489        }
10490
10491        function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: readonly TypeNode[] | undefined, location: Node): readonly Signature[] {
10492            const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location);
10493            const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode);
10494            return sameMap<Signature>(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJSFile(location)) : sig);
10495        }
10496
10497        /**
10498         * The base constructor of a class can resolve to
10499         * * undefinedType if the class has no extends clause,
10500         * * unknownType if an error occurred during resolution of the extends expression,
10501         * * nullType if the extends expression is the null value,
10502         * * anyType if the extends expression has type any, or
10503         * * an object type with at least one construct signature.
10504         */
10505        function getBaseConstructorTypeOfClass(type: InterfaceType): Type {
10506            if (!type.resolvedBaseConstructorType) {
10507                const decl = getClassLikeDeclarationOfSymbol(type.symbol);
10508                const extended = decl && getEffectiveBaseTypeNode(decl);
10509                const baseTypeNode = getBaseTypeNodeOfClass(type);
10510                if (!baseTypeNode) {
10511                    return type.resolvedBaseConstructorType = undefinedType;
10512                }
10513                if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType)) {
10514                    return errorType;
10515                }
10516                const baseConstructorType = checkExpression(baseTypeNode.expression);
10517                if (extended && baseTypeNode !== extended) {
10518                    Debug.assert(!extended.typeArguments); // Because this is in a JS file, and baseTypeNode is in an @extends tag
10519                    checkExpression(extended.expression);
10520                }
10521                if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
10522                    // Resolving the members of a class requires us to resolve the base class of that class.
10523                    // We force resolution here such that we catch circularities now.
10524                    resolveStructuredTypeMembers(baseConstructorType as ObjectType);
10525                }
10526                if (!popTypeResolution()) {
10527                    error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
10528                    return type.resolvedBaseConstructorType = errorType;
10529                }
10530                if (!(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) {
10531                    const err = error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType));
10532                    if (baseConstructorType.flags & TypeFlags.TypeParameter) {
10533                        const constraint = getConstraintFromTypeParameter(baseConstructorType);
10534                        let ctorReturn: Type = unknownType;
10535                        if (constraint) {
10536                            const ctorSig = getSignaturesOfType(constraint, SignatureKind.Construct);
10537                            if (ctorSig[0]) {
10538                                ctorReturn = getReturnTypeOfSignature(ctorSig[0]);
10539                            }
10540                        }
10541                        if (baseConstructorType.symbol.declarations) {
10542                            addRelatedInfo(err, createDiagnosticForNode(baseConstructorType.symbol.declarations[0], Diagnostics.Did_you_mean_for_0_to_be_constrained_to_type_new_args_Colon_any_1, symbolToString(baseConstructorType.symbol), typeToString(ctorReturn)));
10543                        }
10544                    }
10545                    return type.resolvedBaseConstructorType = errorType;
10546                }
10547                type.resolvedBaseConstructorType = baseConstructorType;
10548            }
10549            return type.resolvedBaseConstructorType;
10550        }
10551
10552        function getImplementsTypes(type: InterfaceType): BaseType[] {
10553            let resolvedImplementsTypes: BaseType[] = emptyArray;
10554            if (type.symbol.declarations) {
10555                for (const declaration of type.symbol.declarations) {
10556                    const implementsTypeNodes = getEffectiveImplementsTypeNodes(declaration as ClassLikeDeclaration);
10557                    if (!implementsTypeNodes) continue;
10558                    for (const node of implementsTypeNodes) {
10559                        const implementsType = getTypeFromTypeNode(node);
10560                        if (!isErrorType(implementsType)) {
10561                            if (resolvedImplementsTypes === emptyArray) {
10562                                resolvedImplementsTypes = [implementsType as ObjectType];
10563                            }
10564                            else {
10565                                resolvedImplementsTypes.push(implementsType);
10566                            }
10567                        }
10568                    }
10569                }
10570            }
10571            return resolvedImplementsTypes;
10572        }
10573
10574        function reportCircularBaseType(node: Node, type: Type) {
10575            error(node, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
10576        }
10577
10578        function getBaseTypes(type: InterfaceType): BaseType[] {
10579            if (!type.baseTypesResolved) {
10580                if (pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseTypes)) {
10581                    if (type.objectFlags & ObjectFlags.Tuple) {
10582                        type.resolvedBaseTypes = [getTupleBaseType(type as TupleType)];
10583                    }
10584                    else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
10585                        if (type.symbol.flags & SymbolFlags.Class) {
10586                            resolveBaseTypesOfClass(type);
10587                        }
10588                        if (type.symbol.flags & SymbolFlags.Interface) {
10589                            resolveBaseTypesOfInterface(type);
10590                        }
10591                    }
10592                    else {
10593                        Debug.fail("type must be class or interface");
10594                    }
10595                    if (!popTypeResolution() && type.symbol.declarations) {
10596                        for (const declaration of type.symbol.declarations) {
10597                            if (declaration.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.InterfaceDeclaration) {
10598                                reportCircularBaseType(declaration, type);
10599                            }
10600                        }
10601                    }
10602                }
10603                type.baseTypesResolved = true;
10604            }
10605            return type.resolvedBaseTypes;
10606        }
10607
10608        function getTupleBaseType(type: TupleType) {
10609            const elementTypes = sameMap(type.typeParameters, (t, i) => type.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t);
10610            return createArrayType(getUnionType(elementTypes || emptyArray), type.readonly);
10611        }
10612
10613        function resolveBaseTypesOfClass(type: InterfaceType) {
10614            type.resolvedBaseTypes = resolvingEmptyArray;
10615            const baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type));
10616            if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Any))) {
10617                return type.resolvedBaseTypes = emptyArray;
10618            }
10619            const baseTypeNode = getBaseTypeNodeOfClass(type)!;
10620            let baseType: Type;
10621            const originalBaseType = baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined;
10622            if (baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class &&
10623                areAllOuterTypeParametersApplied(originalBaseType!)) {
10624                // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the
10625                // class and all return the instance type of the class. There is no need for further checks and we can apply the
10626                // type arguments in the same manner as a type reference to get the same error reporting experience.
10627                baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol);
10628            }
10629            else if (baseConstructorType.flags & TypeFlags.Any) {
10630                baseType = baseConstructorType;
10631            }
10632            else {
10633                // The class derives from a "class-like" constructor function, check that we have at least one construct signature
10634                // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere
10635                // we check that all instantiated signatures return the same type.
10636                const constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments, baseTypeNode);
10637                if (!constructors.length) {
10638                    error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
10639                    return type.resolvedBaseTypes = emptyArray;
10640                }
10641                baseType = getReturnTypeOfSignature(constructors[0]);
10642            }
10643
10644            if (isErrorType(baseType)) {
10645                return type.resolvedBaseTypes = emptyArray;
10646            }
10647            const reducedBaseType = getReducedType(baseType);
10648            if (!isValidBaseType(reducedBaseType)) {
10649                const elaboration = elaborateNeverIntersection(/*errorInfo*/ undefined, baseType);
10650                const diagnostic = chainDiagnosticMessages(elaboration, Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(reducedBaseType));
10651                diagnostics.add(createDiagnosticForNodeFromMessageChain(baseTypeNode.expression, diagnostic));
10652                return type.resolvedBaseTypes = emptyArray;
10653            }
10654            if (type === reducedBaseType || hasBaseType(reducedBaseType, type)) {
10655                error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
10656                    typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
10657                return type.resolvedBaseTypes = emptyArray;
10658            }
10659            if (type.resolvedBaseTypes === resolvingEmptyArray) {
10660                // Circular reference, likely through instantiation of default parameters
10661                // (otherwise there'd be an error from hasBaseType) - this is fine, but `.members` should be reset
10662                // as `getIndexedAccessType` via `instantiateType` via `getTypeFromClassOrInterfaceReference` forces a
10663                // partial instantiation of the members without the base types fully resolved
10664                type.members = undefined;
10665            }
10666            return type.resolvedBaseTypes = [reducedBaseType];
10667        }
10668
10669        function areAllOuterTypeParametersApplied(type: Type): boolean { // TODO: GH#18217 Shouldn't this take an InterfaceType?
10670            // An unapplied type parameter has its symbol still the same as the matching argument symbol.
10671            // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked.
10672            const outerTypeParameters = (type as InterfaceType).outerTypeParameters;
10673            if (outerTypeParameters) {
10674                const last = outerTypeParameters.length - 1;
10675                const typeArguments = getTypeArguments(type as TypeReference);
10676                return outerTypeParameters[last].symbol !== typeArguments[last].symbol;
10677            }
10678            return true;
10679        }
10680
10681        // A valid base type is `any`, an object type or intersection of object types.
10682        function isValidBaseType(type: Type): type is BaseType {
10683            if ((type.flags & TypeFlags.Object) && ((type as ObjectType).objectFlags & ObjectFlags.Annotation)) {
10684                return false;
10685            }
10686            if (type.flags & TypeFlags.TypeParameter) {
10687                const constraint = getBaseConstraintOfType(type);
10688                if (constraint) {
10689                    return isValidBaseType(constraint);
10690                }
10691            }
10692            // TODO: Given that we allow type parmeters here now, is this `!isGenericMappedType(type)` check really needed?
10693            // There's no reason a `T` should be allowed while a `Readonly<T>` should not.
10694            return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) ||
10695                type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isValidBaseType));
10696        }
10697
10698        function resolveBaseTypesOfInterface(type: InterfaceType): void {
10699            type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
10700            if (type.symbol.declarations) {
10701                for (const declaration of type.symbol.declarations) {
10702                    if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration)) {
10703                        for (const node of getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration)!) {
10704                            const baseType = getReducedType(getTypeFromTypeNode(node));
10705                            if (!isErrorType(baseType)) {
10706                                if (isValidBaseType(baseType)) {
10707                                    if (type !== baseType && !hasBaseType(baseType, type)) {
10708                                        if (type.resolvedBaseTypes === emptyArray) {
10709                                            type.resolvedBaseTypes = [baseType as ObjectType];
10710                                        }
10711                                        else {
10712                                            type.resolvedBaseTypes.push(baseType);
10713                                        }
10714                                    }
10715                                    else {
10716                                        reportCircularBaseType(declaration, type);
10717                                    }
10718                                }
10719                                else {
10720                                    error(node, Diagnostics.An_interface_can_only_extend_an_object_type_or_intersection_of_object_types_with_statically_known_members);
10721                                }
10722                            }
10723                        }
10724                    }
10725                }
10726            }
10727        }
10728
10729        /**
10730         * Returns true if the interface given by the symbol is free of "this" references.
10731         *
10732         * Specifically, the result is true if the interface itself contains no references
10733         * to "this" in its body, if all base types are interfaces,
10734         * and if none of the base interfaces have a "this" type.
10735         */
10736        function isThislessInterface(symbol: Symbol): boolean {
10737            if (!symbol.declarations) {
10738                return true;
10739            }
10740            for (const declaration of symbol.declarations) {
10741                if (declaration.kind === SyntaxKind.InterfaceDeclaration) {
10742                    if (declaration.flags & NodeFlags.ContainsThis) {
10743                        return false;
10744                    }
10745                    const baseTypeNodes = getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration);
10746                    if (baseTypeNodes) {
10747                        for (const node of baseTypeNodes) {
10748                            if (isEntityNameExpression(node.expression)) {
10749                                const baseSymbol = resolveEntityName(node.expression, SymbolFlags.Type, /*ignoreErrors*/ true);
10750                                if (!baseSymbol || !(baseSymbol.flags & SymbolFlags.Interface) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) {
10751                                    return false;
10752                                }
10753                            }
10754                        }
10755                    }
10756                }
10757            }
10758            return true;
10759        }
10760
10761        function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType {
10762            let links = getSymbolLinks(symbol);
10763            const originalLinks = links;
10764            if (!links.declaredType) {
10765                const kind = (symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface) | (symbol.flags & SymbolFlags.Annotation ? ObjectFlags.Annotation : 0);
10766                const merged = mergeJSSymbols(symbol, symbol.valueDeclaration && getAssignedClassSymbol(symbol.valueDeclaration));
10767                if (merged) {
10768                    // note:we overwrite links because we just cloned the symbol
10769                    symbol = links = merged;
10770                }
10771
10772                const type = originalLinks.declaredType = links.declaredType = createObjectType(kind, symbol) as InterfaceType;
10773                const outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol);
10774                const localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
10775                // A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type
10776                // because it is not feasible to analyze all members to determine if the "this" type escapes the class (in particular,
10777                // property types inferred from initializers and method return types inferred from return statements are very hard
10778                // to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of
10779                // "this" references.
10780                if (outerTypeParameters || localTypeParameters || kind === ObjectFlags.Class || !isThislessInterface(symbol)) {
10781                    type.objectFlags |= ObjectFlags.Reference;
10782                    type.typeParameters = concatenate(outerTypeParameters, localTypeParameters);
10783                    type.outerTypeParameters = outerTypeParameters;
10784                    type.localTypeParameters = localTypeParameters;
10785                    (type as GenericType).instantiations = new Map<string, TypeReference>();
10786                    (type as GenericType).instantiations.set(getTypeListId(type.typeParameters), type as GenericType);
10787                    (type as GenericType).target = type as GenericType;
10788                    (type as GenericType).resolvedTypeArguments = type.typeParameters;
10789                    type.thisType = createTypeParameter(symbol);
10790                    type.thisType.isThisType = true;
10791                    type.thisType.constraint = type;
10792                }
10793            }
10794            return links.declaredType as InterfaceType;
10795        }
10796
10797        function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type {
10798            const links = getSymbolLinks(symbol);
10799            if (!links.declaredType) {
10800                // Note that we use the links object as the target here because the symbol object is used as the unique
10801                // identity for resolution of the 'type' property in SymbolLinks.
10802                if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
10803                    return errorType;
10804                }
10805
10806                const declaration = Debug.checkDefined(symbol.declarations?.find(isTypeAlias), "Type alias symbol with no valid declaration found");
10807                const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type;
10808                // If typeNode is missing, we will error in checkJSDocTypedefTag.
10809                let type = typeNode ? getTypeFromTypeNode(typeNode) : errorType;
10810
10811                if (popTypeResolution()) {
10812                    const typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
10813                    if (typeParameters) {
10814                        // Initialize the instantiation cache for generic type aliases. The declared type corresponds to
10815                        // an instantiation of the type alias with the type parameters supplied as type arguments.
10816                        links.typeParameters = typeParameters;
10817                        links.instantiations = new Map<string, Type>();
10818                        links.instantiations.set(getTypeListId(typeParameters), type);
10819                    }
10820                }
10821                else {
10822                    type = errorType;
10823                    if (declaration.kind === SyntaxKind.JSDocEnumTag) {
10824                        error(declaration.typeExpression.type, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
10825                    }
10826                    else {
10827                        error(isNamedDeclaration(declaration) ? declaration.name || declaration : declaration, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
10828                    }
10829                }
10830                links.declaredType = type;
10831            }
10832            return links.declaredType;
10833        }
10834
10835        function isStringConcatExpression(expr: Node): boolean {
10836            if (isStringLiteralLike(expr)) {
10837                return true;
10838            }
10839            else if (expr.kind === SyntaxKind.BinaryExpression) {
10840                return isStringConcatExpression((expr as BinaryExpression).left) && isStringConcatExpression((expr as BinaryExpression).right);
10841            }
10842            return false;
10843        }
10844
10845        function isLiteralEnumMember(member: EnumMember) {
10846            const expr = member.initializer;
10847            if (!expr) {
10848                return !(member.flags & NodeFlags.Ambient);
10849            }
10850            switch (expr.kind) {
10851                case SyntaxKind.StringLiteral:
10852                case SyntaxKind.NumericLiteral:
10853                case SyntaxKind.NoSubstitutionTemplateLiteral:
10854                    return true;
10855                case SyntaxKind.PrefixUnaryExpression:
10856                    return (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken &&
10857                        (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.NumericLiteral;
10858                case SyntaxKind.Identifier:
10859                    return nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports!.get((expr as Identifier).escapedText);
10860                case SyntaxKind.BinaryExpression:
10861                    return isStringConcatExpression(expr);
10862                default:
10863                    return false;
10864            }
10865        }
10866
10867        function getEnumKind(symbol: Symbol): EnumKind {
10868            const links = getSymbolLinks(symbol);
10869            if (links.enumKind !== undefined) {
10870                return links.enumKind;
10871            }
10872            let hasNonLiteralMember = false;
10873            if (symbol.declarations) {
10874                for (const declaration of symbol.declarations) {
10875                    if (declaration.kind === SyntaxKind.EnumDeclaration) {
10876                        for (const member of (declaration as EnumDeclaration).members) {
10877                            if (member.initializer && isStringLiteralLike(member.initializer)) {
10878                                return links.enumKind = EnumKind.Literal;
10879                            }
10880                            if (!isLiteralEnumMember(member)) {
10881                                hasNonLiteralMember = true;
10882                            }
10883                        }
10884                    }
10885                }
10886            }
10887            return links.enumKind = hasNonLiteralMember ? EnumKind.Numeric : EnumKind.Literal;
10888        }
10889
10890        function getBaseTypeOfEnumLiteralType(type: Type) {
10891            return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type;
10892        }
10893
10894        function getDeclaredTypeOfEnum(symbol: Symbol): Type {
10895            const links = getSymbolLinks(symbol);
10896            if (links.declaredType) {
10897                return links.declaredType;
10898            }
10899            if (getEnumKind(symbol) === EnumKind.Literal) {
10900                enumCount++;
10901                const memberTypeList: Type[] = [];
10902                if (symbol.declarations) {
10903                    for (const declaration of symbol.declarations) {
10904                        if (declaration.kind === SyntaxKind.EnumDeclaration) {
10905                            for (const member of (declaration as EnumDeclaration).members) {
10906                                const value = getEnumMemberValue(member);
10907                                const memberType = getFreshTypeOfLiteralType(getEnumLiteralType(value !== undefined ? value : 0, enumCount, getSymbolOfNode(member)));
10908                                getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType;
10909                                memberTypeList.push(getRegularTypeOfLiteralType(memberType));
10910                            }
10911                        }
10912                    }
10913                }
10914                if (memberTypeList.length) {
10915                    const enumType = getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined);
10916                    if (enumType.flags & TypeFlags.Union) {
10917                        enumType.flags |= TypeFlags.EnumLiteral;
10918                        enumType.symbol = symbol;
10919                    }
10920                    return links.declaredType = enumType;
10921                }
10922            }
10923            const enumType = createType(TypeFlags.Enum);
10924            enumType.symbol = symbol;
10925            return links.declaredType = enumType;
10926        }
10927
10928        function getDeclaredTypeOfEnumMember(symbol: Symbol): Type {
10929            const links = getSymbolLinks(symbol);
10930            if (!links.declaredType) {
10931                const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)!);
10932                if (!links.declaredType) {
10933                    links.declaredType = enumType;
10934                }
10935            }
10936            return links.declaredType;
10937        }
10938
10939        function getDeclaredTypeOfTypeParameter(symbol: Symbol): TypeParameter {
10940            const links = getSymbolLinks(symbol);
10941            return links.declaredType || (links.declaredType = createTypeParameter(symbol));
10942        }
10943
10944        function getDeclaredTypeOfAlias(symbol: Symbol): Type {
10945            const links = getSymbolLinks(symbol);
10946            return links.declaredType || (links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol)));
10947        }
10948
10949        function getDeclaredTypeOfSymbol(symbol: Symbol): Type {
10950            return tryGetDeclaredTypeOfSymbol(symbol) || errorType;
10951        }
10952
10953        function tryGetDeclaredTypeOfSymbol(symbol: Symbol): Type | undefined {
10954            if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
10955                return getDeclaredTypeOfClassOrInterface(symbol);
10956            }
10957            if (symbol.flags & SymbolFlags.TypeAlias) {
10958                return getDeclaredTypeOfTypeAlias(symbol);
10959            }
10960            if (symbol.flags & SymbolFlags.TypeParameter) {
10961                return getDeclaredTypeOfTypeParameter(symbol);
10962            }
10963            if (symbol.flags & SymbolFlags.Enum) {
10964                return getDeclaredTypeOfEnum(symbol);
10965            }
10966            if (symbol.flags & SymbolFlags.EnumMember) {
10967                return getDeclaredTypeOfEnumMember(symbol);
10968            }
10969            if (symbol.flags & SymbolFlags.Alias) {
10970                return getDeclaredTypeOfAlias(symbol);
10971            }
10972            return undefined;
10973        }
10974
10975        /**
10976         * A type is free of this references if it's the any, string, number, boolean, symbol, or void keyword, a string
10977         * literal type, an array with an element type that is free of this references, or a type reference that is
10978         * free of this references.
10979         */
10980        function isThislessType(node: TypeNode): boolean {
10981            switch (node.kind) {
10982                case SyntaxKind.AnyKeyword:
10983                case SyntaxKind.UnknownKeyword:
10984                case SyntaxKind.StringKeyword:
10985                case SyntaxKind.NumberKeyword:
10986                case SyntaxKind.BigIntKeyword:
10987                case SyntaxKind.BooleanKeyword:
10988                case SyntaxKind.SymbolKeyword:
10989                case SyntaxKind.ObjectKeyword:
10990                case SyntaxKind.VoidKeyword:
10991                case SyntaxKind.UndefinedKeyword:
10992                case SyntaxKind.NeverKeyword:
10993                case SyntaxKind.LiteralType:
10994                    return true;
10995                case SyntaxKind.ArrayType:
10996                    return isThislessType((node as ArrayTypeNode).elementType);
10997                case SyntaxKind.TypeReference:
10998                    return !(node as TypeReferenceNode).typeArguments || (node as TypeReferenceNode).typeArguments!.every(isThislessType);
10999            }
11000            return false;
11001        }
11002
11003        /** A type parameter is thisless if its constraint is thisless, or if it has no constraint. */
11004        function isThislessTypeParameter(node: TypeParameterDeclaration) {
11005            const constraint = getEffectiveConstraintOfTypeParameter(node);
11006            return !constraint || isThislessType(constraint);
11007        }
11008
11009        /**
11010         * A variable-like declaration is free of this references if it has a type annotation
11011         * that is thisless, or if it has no type annotation and no initializer (and is thus of type any).
11012         */
11013        function isThislessVariableLikeDeclaration(node: VariableLikeDeclaration): boolean {
11014            const typeNode = getEffectiveTypeAnnotationNode(node);
11015            return typeNode ? isThislessType(typeNode) : !hasInitializer(node);
11016        }
11017
11018        /**
11019         * A function-like declaration is considered free of `this` references if it has a return type
11020         * annotation that is free of this references and if each parameter is thisless and if
11021         * each type parameter (if present) is thisless.
11022         */
11023        function isThislessFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
11024            const returnType = getEffectiveReturnTypeNode(node);
11025            const typeParameters = getEffectiveTypeParameterDeclarations(node);
11026            return (node.kind === SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) &&
11027                node.parameters.every(isThislessVariableLikeDeclaration) &&
11028                typeParameters.every(isThislessTypeParameter);
11029        }
11030
11031        /**
11032         * Returns true if the class or interface member given by the symbol is free of "this" references. The
11033         * function may return false for symbols that are actually free of "this" references because it is not
11034         * feasible to perform a complete analysis in all cases. In particular, property members with types
11035         * inferred from their initializers and function members with inferred return types are conservatively
11036         * assumed not to be free of "this" references.
11037         */
11038        function isThisless(symbol: Symbol): boolean {
11039            if (symbol.declarations && symbol.declarations.length === 1) {
11040                const declaration = symbol.declarations[0];
11041                if (declaration) {
11042                    switch (declaration.kind) {
11043                        case SyntaxKind.PropertyDeclaration:
11044                        case SyntaxKind.PropertySignature:
11045                            return isThislessVariableLikeDeclaration(declaration as VariableLikeDeclaration);
11046                        case SyntaxKind.MethodDeclaration:
11047                        case SyntaxKind.MethodSignature:
11048                        case SyntaxKind.Constructor:
11049                        case SyntaxKind.GetAccessor:
11050                        case SyntaxKind.SetAccessor:
11051                            return isThislessFunctionLikeDeclaration(declaration as FunctionLikeDeclaration | AccessorDeclaration);
11052                    }
11053                }
11054            }
11055            return false;
11056        }
11057
11058        // The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true,
11059        // we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation.
11060        function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper, mappingThisOnly: boolean): SymbolTable {
11061            const result = createSymbolTable();
11062            for (const symbol of symbols) {
11063                result.set(symbol.escapedName, mappingThisOnly && isThisless(symbol) ? symbol : instantiateSymbol(symbol, mapper));
11064            }
11065            return result;
11066        }
11067
11068        function addInheritedMembers(symbols: SymbolTable, baseSymbols: Symbol[]) {
11069            for (const s of baseSymbols) {
11070                if (!symbols.has(s.escapedName) && !isStaticPrivateIdentifierProperty(s)) {
11071                    symbols.set(s.escapedName, s);
11072                }
11073            }
11074        }
11075
11076        function isStaticPrivateIdentifierProperty(s: Symbol): boolean {
11077            return !!s.valueDeclaration && isPrivateIdentifierClassElementDeclaration(s.valueDeclaration) && isStatic(s.valueDeclaration);
11078        }
11079
11080        function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers {
11081            if (!(type as InterfaceTypeWithDeclaredMembers).declaredProperties) {
11082                const symbol = type.symbol;
11083                const members = getMembersOfSymbol(symbol);
11084                (type as InterfaceTypeWithDeclaredMembers).declaredProperties = getNamedMembers(members);
11085                // Start with signatures at empty array in case of recursive types
11086                (type as InterfaceTypeWithDeclaredMembers).declaredCallSignatures = emptyArray;
11087                (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = emptyArray;
11088                (type as InterfaceTypeWithDeclaredMembers).declaredIndexInfos = emptyArray;
11089
11090                (type as InterfaceTypeWithDeclaredMembers).declaredCallSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call));
11091                (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New));
11092                (type as InterfaceTypeWithDeclaredMembers).declaredIndexInfos = getIndexInfosOfSymbol(symbol);
11093            }
11094            return type as InterfaceTypeWithDeclaredMembers;
11095        }
11096
11097        /**
11098         * Indicates whether a type can be used as a property name.
11099         */
11100        function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType {
11101            return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique);
11102        }
11103
11104        /**
11105         * Indicates whether a declaration name is definitely late-bindable.
11106         * A declaration name is only late-bindable if:
11107         * - It is a `ComputedPropertyName`.
11108         * - Its expression is an `Identifier` or either a `PropertyAccessExpression` an
11109         * `ElementAccessExpression` consisting only of these same three types of nodes.
11110         * - The type of its expression is a string or numeric literal type, or is a `unique symbol` type.
11111         */
11112        function isLateBindableName(node: DeclarationName): node is LateBoundName {
11113            if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
11114                return false;
11115            }
11116            const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
11117            return isEntityNameExpression(expr)
11118                && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr));
11119        }
11120
11121        function isLateBoundName(name: __String): boolean {
11122            return (name as string).charCodeAt(0) === CharacterCodes._ &&
11123                (name as string).charCodeAt(1) === CharacterCodes._ &&
11124                (name as string).charCodeAt(2) === CharacterCodes.at;
11125        }
11126
11127        /**
11128         * Indicates whether a declaration has a late-bindable dynamic name.
11129         */
11130        function hasLateBindableName(node: Declaration): node is LateBoundDeclaration | LateBoundBinaryExpressionDeclaration {
11131            const name = getNameOfDeclaration(node);
11132            return !!name && isLateBindableName(name);
11133        }
11134
11135        /**
11136         * Indicates whether a declaration has an early-bound name or a dynamic name that can be late-bound.
11137         */
11138        function hasBindableName(node: Declaration) {
11139            return !hasDynamicName(node) || hasLateBindableName(node);
11140        }
11141
11142        /**
11143         * Indicates whether a declaration name is a dynamic name that cannot be late-bound.
11144         */
11145        function isNonBindableDynamicName(node: DeclarationName) {
11146            return isDynamicName(node) && !isLateBindableName(node);
11147        }
11148
11149        /**
11150         * Gets the symbolic name for a member from its type.
11151         */
11152        function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String {
11153            if (type.flags & TypeFlags.UniqueESSymbol) {
11154                return (type as UniqueESSymbolType).escapedName;
11155            }
11156            if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
11157                return escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value);
11158            }
11159            return Debug.fail();
11160        }
11161
11162        /**
11163         * Adds a declaration to a late-bound dynamic member. This performs the same function for
11164         * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound
11165         * members.
11166         */
11167        function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration | BinaryExpression, symbolFlags: SymbolFlags) {
11168            Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol.");
11169            symbol.flags |= symbolFlags;
11170            getSymbolLinks(member.symbol).lateSymbol = symbol;
11171            if (!symbol.declarations) {
11172                symbol.declarations = [member];
11173            }
11174            else if(!member.symbol.isReplaceableByMethod) {
11175                symbol.declarations.push(member);
11176            }
11177            if (symbolFlags & SymbolFlags.Value) {
11178                if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) {
11179                    symbol.valueDeclaration = member;
11180                }
11181            }
11182        }
11183
11184        /**
11185         * Performs late-binding of a dynamic member. This performs the same function for
11186         * late-bound members that `declareSymbol` in binder.ts performs for early-bound
11187         * members.
11188         *
11189         * If a symbol is a dynamic name from a computed property, we perform an additional "late"
11190         * binding phase to attempt to resolve the name for the symbol from the type of the computed
11191         * property's expression. If the type of the expression is a string-literal, numeric-literal,
11192         * or unique symbol type, we can use that type as the name of the symbol.
11193         *
11194         * For example, given:
11195         *
11196         *   const x = Symbol();
11197         *
11198         *   interface I {
11199         *     [x]: number;
11200         *   }
11201         *
11202         * The binder gives the property `[x]: number` a special symbol with the name "__computed".
11203         * In the late-binding phase we can type-check the expression `x` and see that it has a
11204         * unique symbol type which we can then use as the name of the member. This allows users
11205         * to define custom symbols that can be used in the members of an object type.
11206         *
11207         * @param parent The containing symbol for the member.
11208         * @param earlySymbols The early-bound symbols of the parent.
11209         * @param lateSymbols The late-bound symbols of the parent.
11210         * @param decl The member to bind.
11211         */
11212        function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: UnderscoreEscapedMap<TransientSymbol>, decl: LateBoundDeclaration | LateBoundBinaryExpressionDeclaration) {
11213            Debug.assert(!!decl.symbol, "The member is expected to have a symbol.");
11214            const links = getNodeLinks(decl);
11215            if (!links.resolvedSymbol) {
11216                // In the event we attempt to resolve the late-bound name of this member recursively,
11217                // fall back to the early-bound name of this member.
11218                links.resolvedSymbol = decl.symbol;
11219                const declName = isBinaryExpression(decl) ? decl.left : decl.name;
11220                const type = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName);
11221                if (isTypeUsableAsPropertyName(type)) {
11222                    const memberName = getPropertyNameFromType(type);
11223                    const symbolFlags = decl.symbol.flags;
11224
11225                    // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations.
11226                    let lateSymbol = lateSymbols.get(memberName);
11227                    if (!lateSymbol) lateSymbols.set(memberName, lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late));
11228
11229                    // Report an error if a late-bound member has the same name as an early-bound member,
11230                    // or if we have another early-bound symbol declaration with the same name and
11231                    // conflicting flags.
11232                    const earlySymbol = earlySymbols && earlySymbols.get(memberName);
11233                    if (lateSymbol.flags & getExcludedSymbolFlags(symbolFlags) || earlySymbol) {
11234                        // If we have an existing early-bound member, combine its declarations so that we can
11235                        // report an error at each declaration.
11236                        const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations;
11237                        const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(declName);
11238                        forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Property_0_was_also_declared_here, name));
11239                        error(declName || decl, Diagnostics.Duplicate_property_0, name);
11240                        lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late);
11241                    }
11242                    lateSymbol.nameType = type;
11243                    addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags);
11244                    if (lateSymbol.parent) {
11245                        Debug.assert(lateSymbol.parent === parent, "Existing symbol parent should match new one");
11246                    }
11247                    else {
11248                        lateSymbol.parent = parent;
11249                    }
11250                    return links.resolvedSymbol = lateSymbol;
11251                }
11252            }
11253            return links.resolvedSymbol;
11254        }
11255
11256        function getResolvedMembersOrExportsOfSymbol(symbol: Symbol, resolutionKind: MembersOrExportsResolutionKind): UnderscoreEscapedMap<Symbol> {
11257            const links = getSymbolLinks(symbol);
11258            if (!links[resolutionKind]) {
11259                const isStatic = resolutionKind === MembersOrExportsResolutionKind.resolvedExports;
11260                const earlySymbols = !isStatic ? symbol.members :
11261                    symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol) :
11262                    symbol.exports;
11263
11264                // In the event we recursively resolve the members/exports of the symbol, we
11265                // set the initial value of resolvedMembers/resolvedExports to the early-bound
11266                // members/exports of the symbol.
11267                links[resolutionKind] = earlySymbols || emptySymbols;
11268
11269                // fill in any as-yet-unresolved late-bound members.
11270                const lateSymbols = createSymbolTable() as UnderscoreEscapedMap<TransientSymbol>;
11271                for (const decl of symbol.declarations || emptyArray) {
11272                    const members = getMembersOfDeclaration(decl);
11273                    if (members) {
11274                        for (const member of members) {
11275                            if (isStatic === hasStaticModifier(member)) {
11276                                if (hasLateBindableName(member)) {
11277                                    lateBindMember(symbol, earlySymbols, lateSymbols, member);
11278                                }
11279                            }
11280                        }
11281                    }
11282                }
11283                const assignments = symbol.assignmentDeclarationMembers;
11284                if (assignments) {
11285                    const decls = arrayFrom(assignments.values());
11286                    for (const member of decls) {
11287                        const assignmentKind = getAssignmentDeclarationKind(member as BinaryExpression | CallExpression);
11288                        const isInstanceMember = assignmentKind === AssignmentDeclarationKind.PrototypeProperty
11289                            || isBinaryExpression(member) && isPossiblyAliasedThisProperty(member, assignmentKind)
11290                            || assignmentKind === AssignmentDeclarationKind.ObjectDefinePrototypeProperty
11291                            || assignmentKind === AssignmentDeclarationKind.Prototype; // A straight `Prototype` assignment probably can never have a computed name
11292                        if (isStatic === !isInstanceMember) {
11293                            if (hasLateBindableName(member)) {
11294                                lateBindMember(symbol, earlySymbols, lateSymbols, member);
11295                            }
11296                        }
11297                    }
11298                }
11299
11300                links[resolutionKind] = combineSymbolTables(earlySymbols, lateSymbols) || emptySymbols;
11301            }
11302
11303            return links[resolutionKind]!;
11304        }
11305
11306        /**
11307         * Gets a SymbolTable containing both the early- and late-bound members of a symbol.
11308         *
11309         * For a description of late-binding, see `lateBindMember`.
11310         */
11311        function getMembersOfSymbol(symbol: Symbol) {
11312            return symbol.flags & SymbolFlags.LateBindingContainer
11313                ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedMembers)
11314                : symbol.members || emptySymbols;
11315        }
11316
11317        /**
11318         * If a symbol is the dynamic name of the member of an object type, get the late-bound
11319         * symbol of the member.
11320         *
11321         * For a description of late-binding, see `lateBindMember`.
11322         */
11323        function getLateBoundSymbol(symbol: Symbol): Symbol {
11324            if (symbol.flags & SymbolFlags.ClassMember && symbol.escapedName === InternalSymbolName.Computed) {
11325                const links = getSymbolLinks(symbol);
11326                if (!links.lateSymbol && some(symbol.declarations, hasLateBindableName)) {
11327                    // force late binding of members/exports. This will set the late-bound symbol
11328                    const parent = getMergedSymbol(symbol.parent)!;
11329                    if (some(symbol.declarations, hasStaticModifier)) {
11330                        getExportsOfSymbol(parent);
11331                    }
11332                    else {
11333                        getMembersOfSymbol(parent);
11334                    }
11335                }
11336                return links.lateSymbol || (links.lateSymbol = symbol);
11337            }
11338            return symbol;
11339        }
11340
11341        function getTypeWithThisArgument(type: Type, thisArgument?: Type, needApparentType?: boolean): Type {
11342            if (getObjectFlags(type) & ObjectFlags.Reference) {
11343                const target = (type as TypeReference).target;
11344                const typeArguments = getTypeArguments(type as TypeReference);
11345                if (length(target.typeParameters) === length(typeArguments)) {
11346                    const ref = createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType!]));
11347                    return needApparentType ? getApparentType(ref) : ref;
11348                }
11349            }
11350            else if (type.flags & TypeFlags.Intersection) {
11351                const types = sameMap((type as IntersectionType).types, t => getTypeWithThisArgument(t, thisArgument, needApparentType));
11352                return types !== (type as IntersectionType).types ? getIntersectionType(types) : type;
11353            }
11354            return needApparentType ? getApparentType(type) : type;
11355        }
11356
11357        function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: readonly TypeParameter[], typeArguments: readonly Type[]) {
11358            let mapper: TypeMapper | undefined;
11359            let members: SymbolTable;
11360            let callSignatures: readonly Signature[];
11361            let constructSignatures: readonly Signature[];
11362            let indexInfos: readonly IndexInfo[];
11363            if (rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) {
11364                members = source.symbol ? getMembersOfSymbol(source.symbol) : createSymbolTable(source.declaredProperties);
11365                callSignatures = source.declaredCallSignatures;
11366                constructSignatures = source.declaredConstructSignatures;
11367                indexInfos = source.declaredIndexInfos;
11368            }
11369            else {
11370                mapper = createTypeMapper(typeParameters, typeArguments);
11371                members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1);
11372                callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper);
11373                constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper);
11374                indexInfos = instantiateIndexInfos(source.declaredIndexInfos, mapper);
11375            }
11376            const baseTypes = getBaseTypes(source);
11377            if (baseTypes.length) {
11378                if (source.symbol && members === getMembersOfSymbol(source.symbol)) {
11379                    members = createSymbolTable(source.declaredProperties);
11380                }
11381                setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos);
11382                const thisArgument = lastOrUndefined(typeArguments);
11383                for (const baseType of baseTypes) {
11384                    const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
11385                    addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType));
11386                    callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
11387                    constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
11388                    const inheritedIndexInfos = instantiatedBaseType !== anyType ? getIndexInfosOfType(instantiatedBaseType) : [createIndexInfo(stringType, anyType, /*isReadonly*/ false)];
11389                    indexInfos = concatenate(indexInfos, filter(inheritedIndexInfos, info => !findIndexInfo(indexInfos, info.keyType)));
11390                }
11391            }
11392            setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos);
11393        }
11394
11395        function resolveClassOrInterfaceMembers(type: InterfaceType): void {
11396            resolveObjectTypeMembers(type, resolveDeclaredMembers(type), emptyArray, emptyArray);
11397        }
11398
11399        function resolveTypeReferenceMembers(type: TypeReference): void {
11400            const source = resolveDeclaredMembers(type.target);
11401            const typeParameters = concatenate(source.typeParameters!, [source.thisType!]);
11402            const typeArguments = getTypeArguments(type);
11403            const paddedTypeArguments = typeArguments.length === typeParameters.length ? typeArguments : concatenate(typeArguments, [type]);
11404            resolveObjectTypeMembers(type, source, typeParameters, paddedTypeArguments);
11405        }
11406
11407        function createSignature(
11408            declaration: SignatureDeclaration | JSDocSignature | undefined,
11409            typeParameters: readonly TypeParameter[] | undefined,
11410            thisParameter: Symbol | undefined,
11411            parameters: readonly Symbol[],
11412            resolvedReturnType: Type | undefined,
11413            resolvedTypePredicate: TypePredicate | undefined,
11414            minArgumentCount: number,
11415            flags: SignatureFlags
11416        ): Signature {
11417            const sig = new Signature(checker, flags);
11418            sig.declaration = declaration;
11419            sig.typeParameters = typeParameters;
11420            sig.parameters = parameters;
11421            sig.thisParameter = thisParameter;
11422            sig.resolvedReturnType = resolvedReturnType;
11423            sig.resolvedTypePredicate = resolvedTypePredicate;
11424            sig.minArgumentCount = minArgumentCount;
11425            sig.resolvedMinArgumentCount = undefined;
11426            sig.target = undefined;
11427            sig.mapper = undefined;
11428            sig.compositeSignatures = undefined;
11429            sig.compositeKind = undefined;
11430            return sig;
11431        }
11432
11433        function cloneSignature(sig: Signature): Signature {
11434            const result = createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /*resolvedReturnType*/ undefined,
11435                /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags);
11436            result.target = sig.target;
11437            result.mapper = sig.mapper;
11438            result.compositeSignatures = sig.compositeSignatures;
11439            result.compositeKind = sig.compositeKind;
11440            return result;
11441        }
11442
11443        function createUnionSignature(signature: Signature, unionSignatures: Signature[]) {
11444            const result = cloneSignature(signature);
11445            result.compositeSignatures = unionSignatures;
11446            result.compositeKind = TypeFlags.Union;
11447            result.target = undefined;
11448            result.mapper = undefined;
11449            return result;
11450        }
11451
11452        function getOptionalCallSignature(signature: Signature, callChainFlags: SignatureFlags): Signature {
11453            if ((signature.flags & SignatureFlags.CallChainFlags) === callChainFlags) {
11454                return signature;
11455            }
11456            if (!signature.optionalCallSignatureCache) {
11457                signature.optionalCallSignatureCache = {};
11458            }
11459            const key = callChainFlags === SignatureFlags.IsInnerCallChain ? "inner" : "outer";
11460            return signature.optionalCallSignatureCache[key]
11461                || (signature.optionalCallSignatureCache[key] = createOptionalCallSignature(signature, callChainFlags));
11462        }
11463
11464        function createOptionalCallSignature(signature: Signature, callChainFlags: SignatureFlags) {
11465            Debug.assert(callChainFlags === SignatureFlags.IsInnerCallChain || callChainFlags === SignatureFlags.IsOuterCallChain,
11466                "An optional call signature can either be for an inner call chain or an outer call chain, but not both.");
11467            const result = cloneSignature(signature);
11468            result.flags |= callChainFlags;
11469            return result;
11470        }
11471
11472        function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] {
11473            if (signatureHasRestParameter(sig)) {
11474                const restIndex = sig.parameters.length - 1;
11475                const restType = getTypeOfSymbol(sig.parameters[restIndex]);
11476                if (isTupleType(restType)) {
11477                    return [expandSignatureParametersWithTupleMembers(restType, restIndex)];
11478                }
11479                else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) {
11480                    return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex));
11481                }
11482            }
11483            return [sig.parameters];
11484
11485            function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
11486                const elementTypes = getTypeArguments(restType);
11487                const associatedNames = restType.target.labeledElementDeclarations;
11488                const restParams = map(elementTypes, (t, i) => {
11489                    // Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
11490                    const tupleLabelName = !!associatedNames && getTupleElementLabel(associatedNames[i]);
11491                    const name = tupleLabelName || getParameterNameAtPosition(sig, restIndex + i, restType);
11492                    const flags = restType.target.elementFlags[i];
11493                    const checkFlags = flags & ElementFlags.Variable ? CheckFlags.RestParameter :
11494                        flags & ElementFlags.Optional ? CheckFlags.OptionalParameter : 0;
11495                    const symbol = createSymbol(SymbolFlags.FunctionScopedVariable, name, checkFlags);
11496                    symbol.type = flags & ElementFlags.Rest ? createArrayType(t) : t;
11497                    return symbol;
11498                });
11499                return concatenate(sig.parameters.slice(0, restIndex), restParams);
11500            }
11501        }
11502
11503        function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
11504            const baseConstructorType = getBaseConstructorTypeOfClass(classType);
11505            const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
11506            const declaration = getClassLikeDeclarationOfSymbol(classType.symbol);
11507            const isAbstract = !!declaration && hasSyntacticModifier(declaration, ModifierFlags.Abstract);
11508            if (baseSignatures.length === 0) {
11509                return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, isAbstract ? SignatureFlags.Abstract : SignatureFlags.None)];
11510            }
11511            const baseTypeNode = getBaseTypeNodeOfClass(classType)!;
11512            const isJavaScript = isInJSFile(baseTypeNode);
11513            const typeArguments = typeArgumentsFromTypeReferenceNode(baseTypeNode);
11514            const typeArgCount = length(typeArguments);
11515            const result: Signature[] = [];
11516            for (const baseSig of baseSignatures) {
11517                const minTypeArgumentCount = getMinTypeArgumentCount(baseSig.typeParameters);
11518                const typeParamCount = length(baseSig.typeParameters);
11519                if (isJavaScript || typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount) {
11520                    const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig);
11521                    sig.typeParameters = classType.localTypeParameters;
11522                    sig.resolvedReturnType = classType;
11523                    sig.flags = isAbstract ? sig.flags | SignatureFlags.Abstract : sig.flags & ~SignatureFlags.Abstract;
11524                    result.push(sig);
11525                }
11526            }
11527            return result;
11528        }
11529
11530        function findMatchingSignature(signatureList: readonly Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature | undefined {
11531            for (const s of signatureList) {
11532                if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, partialMatch ? compareTypesSubtypeOf : compareTypesIdentical)) {
11533                    return s;
11534                }
11535            }
11536        }
11537
11538        function findMatchingSignatures(signatureLists: readonly (readonly Signature[])[], signature: Signature, listIndex: number): Signature[] | undefined {
11539            if (signature.typeParameters) {
11540                // We require an exact match for generic signatures, so we only return signatures from the first
11541                // signature list and only if they have exact matches in the other signature lists.
11542                if (listIndex > 0) {
11543                    return undefined;
11544                }
11545                for (let i = 1; i < signatureLists.length; i++) {
11546                    if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false)) {
11547                        return undefined;
11548                    }
11549                }
11550                return [signature];
11551            }
11552            let result: Signature[] | undefined;
11553            for (let i = 0; i < signatureLists.length; i++) {
11554                // Allow matching non-generic signatures to have excess parameters and different return types.
11555                // Prefer matching this types if possible.
11556                const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true);
11557                if (!match) {
11558                    return undefined;
11559                }
11560                result = appendIfUnique(result, match);
11561            }
11562            return result;
11563        }
11564
11565        // The signatures of a union type are those signatures that are present in each of the constituent types.
11566        // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional
11567        // parameters and may differ in return types. When signatures differ in return types, the resulting return
11568        // type is the union of the constituent return types.
11569        function getUnionSignatures(signatureLists: readonly (readonly Signature[])[]): Signature[] {
11570            let result: Signature[] | undefined;
11571            let indexWithLengthOverOne: number | undefined;
11572            for (let i = 0; i < signatureLists.length; i++) {
11573                if (signatureLists[i].length === 0) return emptyArray;
11574                if (signatureLists[i].length > 1) {
11575                    indexWithLengthOverOne = indexWithLengthOverOne === undefined ? i : -1; // -1 is a signal there are multiple overload sets
11576                }
11577                for (const signature of signatureLists[i]) {
11578                    // Only process signatures with parameter lists that aren't already in the result list
11579                    if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ true)) {
11580                        const unionSignatures = findMatchingSignatures(signatureLists, signature, i);
11581                        if (unionSignatures) {
11582                            let s = signature;
11583                            // Union the result types when more than one signature matches
11584                            if (unionSignatures.length > 1) {
11585                                let thisParameter = signature.thisParameter;
11586                                const firstThisParameterOfUnionSignatures = forEach(unionSignatures, sig => sig.thisParameter);
11587                                if (firstThisParameterOfUnionSignatures) {
11588                                    const thisType = getIntersectionType(mapDefined(unionSignatures, sig => sig.thisParameter && getTypeOfSymbol(sig.thisParameter)));
11589                                    thisParameter = createSymbolWithType(firstThisParameterOfUnionSignatures, thisType);
11590                                }
11591                                s = createUnionSignature(signature, unionSignatures);
11592                                s.thisParameter = thisParameter;
11593                            }
11594                            (result || (result = [])).push(s);
11595                        }
11596                    }
11597                }
11598            }
11599            if (!length(result) && indexWithLengthOverOne !== -1) {
11600                // No sufficiently similar signature existed to subsume all the other signatures in the union - time to see if we can make a single
11601                // signature that handles all over them. We only do this when there are overloads in only one constituent.
11602                // (Overloads are conditional in nature and having overloads in multiple constituents would necessitate making a power set of
11603                // signatures from the type, whose ordering would be non-obvious)
11604                const masterList = signatureLists[indexWithLengthOverOne !== undefined ? indexWithLengthOverOne : 0];
11605                let results: Signature[] | undefined = masterList.slice();
11606                for (const signatures of signatureLists) {
11607                    if (signatures !== masterList) {
11608                        const signature = signatures[0];
11609                        Debug.assert(!!signature, "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass");
11610                        results = !!signature.typeParameters && some(results, s => !!s.typeParameters && !compareTypeParametersIdentical(signature.typeParameters, s.typeParameters)) ? undefined : map(results, sig => combineSignaturesOfUnionMembers(sig, signature));
11611                        if (!results) {
11612                            break;
11613                        }
11614                    }
11615                }
11616                result = results;
11617            }
11618            return result || emptyArray;
11619        }
11620
11621        function compareTypeParametersIdentical(sourceParams: readonly TypeParameter[] | undefined, targetParams: readonly TypeParameter[] | undefined): boolean {
11622            if (length(sourceParams) !== length(targetParams)) {
11623                return false;
11624            }
11625            if (!sourceParams || !targetParams) {
11626                return true;
11627            }
11628
11629            const mapper = createTypeMapper(targetParams, sourceParams);
11630            for (let i = 0; i < sourceParams.length; i++) {
11631                const source = sourceParams[i];
11632                const target = targetParams[i];
11633                if (source === target) continue;
11634                // We instantiate the target type parameter constraints into the source types so we can recognize `<T, U extends T>` as the same as `<A, B extends A>`
11635                if (!isTypeIdenticalTo(getConstraintFromTypeParameter(source) || unknownType, instantiateType(getConstraintFromTypeParameter(target) || unknownType, mapper))) return false;
11636                // We don't compare defaults - we just use the type parameter defaults from the first signature that seems to match.
11637                // It might make sense to combine these defaults in the future, but doing so intelligently requires knowing
11638                // if the parameter is used covariantly or contravariantly (so we intersect if it's used like a parameter or union if used like a return type)
11639                // and, since it's just an inference _default_, just picking one arbitrarily works OK.
11640            }
11641
11642            return true;
11643        }
11644
11645        function combineUnionThisParam(left: Symbol | undefined, right: Symbol | undefined, mapper: TypeMapper | undefined): Symbol | undefined {
11646            if (!left || !right) {
11647                return left || right;
11648            }
11649            // A signature `this` type might be a read or a write position... It's very possible that it should be invariant
11650            // and we should refuse to merge signatures if there are `this` types and they do not match. However, so as to be
11651            // permissive when calling, for now, we'll intersect the `this` types just like we do for param types in union signatures.
11652            const thisType = getIntersectionType([getTypeOfSymbol(left), instantiateType(getTypeOfSymbol(right), mapper)]);
11653            return createSymbolWithType(left, thisType);
11654        }
11655
11656        function combineUnionParameters(left: Signature, right: Signature, mapper: TypeMapper | undefined) {
11657            const leftCount = getParameterCount(left);
11658            const rightCount = getParameterCount(right);
11659            const longest = leftCount >= rightCount ? left : right;
11660            const shorter = longest === left ? right : left;
11661            const longestCount = longest === left ? leftCount : rightCount;
11662            const eitherHasEffectiveRest = (hasEffectiveRestParameter(left) || hasEffectiveRestParameter(right));
11663            const needsExtraRestElement = eitherHasEffectiveRest && !hasEffectiveRestParameter(longest);
11664            const params = new Array<Symbol>(longestCount + (needsExtraRestElement ? 1 : 0));
11665            for (let i = 0; i < longestCount; i++) {
11666                let longestParamType = tryGetTypeAtPosition(longest, i)!;
11667                if (longest === right) {
11668                    longestParamType = instantiateType(longestParamType, mapper);
11669                }
11670                let shorterParamType = tryGetTypeAtPosition(shorter, i) || unknownType;
11671                if (shorter === right) {
11672                    shorterParamType = instantiateType(shorterParamType, mapper);
11673                }
11674                const unionParamType = getIntersectionType([longestParamType, shorterParamType]);
11675                const isRestParam = eitherHasEffectiveRest && !needsExtraRestElement && i === (longestCount - 1);
11676                const isOptional = i >= getMinArgumentCount(longest) && i >= getMinArgumentCount(shorter);
11677                const leftName = i >= leftCount ? undefined : getParameterNameAtPosition(left, i);
11678                const rightName = i >= rightCount ? undefined : getParameterNameAtPosition(right, i);
11679
11680                const paramName = leftName === rightName ? leftName :
11681                    !leftName ? rightName :
11682                    !rightName ? leftName :
11683                    undefined;
11684                const paramSymbol = createSymbol(
11685                    SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0),
11686                    paramName || `arg${i}` as __String
11687                );
11688                paramSymbol.type = isRestParam ? createArrayType(unionParamType) : unionParamType;
11689                params[i] = paramSymbol;
11690            }
11691            if (needsExtraRestElement) {
11692                const restParamSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "args" as __String);
11693                restParamSymbol.type = createArrayType(getTypeAtPosition(shorter, longestCount));
11694                if (shorter === right) {
11695                    restParamSymbol.type = instantiateType(restParamSymbol.type, mapper);
11696                }
11697                params[longestCount] = restParamSymbol;
11698            }
11699            return params;
11700        }
11701
11702        function combineSignaturesOfUnionMembers(left: Signature, right: Signature): Signature {
11703            const typeParams = left.typeParameters || right.typeParameters;
11704            let paramMapper: TypeMapper | undefined;
11705            if (left.typeParameters && right.typeParameters) {
11706                paramMapper = createTypeMapper(right.typeParameters, left.typeParameters);
11707                // We just use the type parameter defaults from the first signature
11708            }
11709            const declaration = left.declaration;
11710            const params = combineUnionParameters(left, right, paramMapper);
11711            const thisParam = combineUnionThisParam(left.thisParameter, right.thisParameter, paramMapper);
11712            const minArgCount = Math.max(left.minArgumentCount, right.minArgumentCount);
11713            const result = createSignature(
11714                declaration,
11715                typeParams,
11716                thisParam,
11717                params,
11718                /*resolvedReturnType*/ undefined,
11719                /*resolvedTypePredicate*/ undefined,
11720                minArgCount,
11721                (left.flags | right.flags) & SignatureFlags.PropagatingFlags
11722            );
11723            result.compositeKind = TypeFlags.Union;
11724            result.compositeSignatures = concatenate(left.compositeKind !== TypeFlags.Intersection && left.compositeSignatures || [left], [right]);
11725            if (paramMapper) {
11726                result.mapper = left.compositeKind !== TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper;
11727            }
11728            return result;
11729        }
11730
11731        function getUnionIndexInfos(types: readonly Type[]): IndexInfo[] {
11732            const sourceInfos = getIndexInfosOfType(types[0]);
11733            if (sourceInfos) {
11734                const result = [];
11735                for (const info of sourceInfos) {
11736                    const indexType = info.keyType;
11737                    if (every(types, t => !!getIndexInfoOfType(t, indexType))) {
11738                        result.push(createIndexInfo(indexType, getUnionType(map(types, t => getIndexTypeOfType(t, indexType)!)),
11739                            some(types, t => getIndexInfoOfType(t, indexType)!.isReadonly)));
11740                    }
11741                }
11742                return result;
11743            }
11744            return emptyArray;
11745        }
11746
11747        function resolveUnionTypeMembers(type: UnionType) {
11748            // The members and properties collections are empty for union types. To get all properties of a union
11749            // type use getPropertiesOfType (only the language service uses this).
11750            const callSignatures = getUnionSignatures(map(type.types, t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, SignatureKind.Call)));
11751            const constructSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Construct)));
11752            const indexInfos = getUnionIndexInfos(type.types);
11753            setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, indexInfos);
11754        }
11755
11756        function intersectTypes(type1: Type, type2: Type): Type;
11757        function intersectTypes(type1: Type | undefined, type2: Type | undefined): Type | undefined;
11758        function intersectTypes(type1: Type | undefined, type2: Type | undefined): Type | undefined {
11759            return !type1 ? type2 : !type2 ? type1 : getIntersectionType([type1, type2]);
11760        }
11761
11762        function findMixins(types: readonly Type[]): readonly boolean[] {
11763            const constructorTypeCount = countWhere(types, (t) => getSignaturesOfType(t, SignatureKind.Construct).length > 0);
11764            const mixinFlags = map(types, isMixinConstructorType);
11765            if (constructorTypeCount > 0 && constructorTypeCount === countWhere(mixinFlags, (b) => b)) {
11766                const firstMixinIndex = mixinFlags.indexOf(/*searchElement*/ true);
11767                mixinFlags[firstMixinIndex] = false;
11768            }
11769            return mixinFlags;
11770        }
11771
11772        function includeMixinType(type: Type, types: readonly Type[], mixinFlags: readonly boolean[], index: number): Type {
11773            const mixedTypes: Type[] = [];
11774            for (let i = 0; i < types.length; i++) {
11775                if (i === index) {
11776                    mixedTypes.push(type);
11777                }
11778                else if (mixinFlags[i]) {
11779                    mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], SignatureKind.Construct)[0]));
11780                }
11781            }
11782            return getIntersectionType(mixedTypes);
11783        }
11784
11785        function resolveIntersectionTypeMembers(type: IntersectionType) {
11786            // The members and properties collections are empty for intersection types. To get all properties of an
11787            // intersection type use getPropertiesOfType (only the language service uses this).
11788            let callSignatures: Signature[] | undefined;
11789            let constructSignatures: Signature[] | undefined;
11790            let indexInfos: IndexInfo[] | undefined;
11791            const types = type.types;
11792            const mixinFlags = findMixins(types);
11793            const mixinCount = countWhere(mixinFlags, (b) => b);
11794            for (let i = 0; i < types.length; i++) {
11795                const t = type.types[i];
11796                // When an intersection type contains mixin constructor types, the construct signatures from
11797                // those types are discarded and their return types are mixed into the return types of all
11798                // other construct signatures in the intersection type. For example, the intersection type
11799                // '{ new(...args: any[]) => A } & { new(s: string) => B }' has a single construct signature
11800                // 'new(s: string) => A & B'.
11801                if (!mixinFlags[i]) {
11802                    let signatures = getSignaturesOfType(t, SignatureKind.Construct);
11803                    if (signatures.length && mixinCount > 0) {
11804                        signatures = map(signatures, s => {
11805                            const clone = cloneSignature(s);
11806                            clone.resolvedReturnType = includeMixinType(getReturnTypeOfSignature(s), types, mixinFlags, i);
11807                            return clone;
11808                        });
11809                    }
11810                    constructSignatures = appendSignatures(constructSignatures, signatures);
11811                }
11812                callSignatures = appendSignatures(callSignatures, getSignaturesOfType(t, SignatureKind.Call));
11813                indexInfos = reduceLeft(getIndexInfosOfType(t), (infos, newInfo) => appendIndexInfo(infos, newInfo, /*union*/ false), indexInfos);
11814            }
11815            setStructuredTypeMembers(type, emptySymbols, callSignatures || emptyArray, constructSignatures || emptyArray, indexInfos || emptyArray);
11816        }
11817
11818        function appendSignatures(signatures: Signature[] | undefined, newSignatures: readonly Signature[]) {
11819            for (const sig of newSignatures) {
11820                if (!signatures || every(signatures, s => !compareSignaturesIdentical(s, sig, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, compareTypesIdentical))) {
11821                    signatures = append(signatures, sig);
11822                }
11823            }
11824            return signatures;
11825        }
11826
11827        function appendIndexInfo(indexInfos: IndexInfo[] | undefined, newInfo: IndexInfo, union: boolean) {
11828            if (indexInfos) {
11829                for (let i = 0; i < indexInfos.length; i++) {
11830                    const info = indexInfos[i];
11831                    if (info.keyType === newInfo.keyType) {
11832                        indexInfos[i] = createIndexInfo(info.keyType,
11833                            union ? getUnionType([info.type, newInfo.type]) : getIntersectionType([info.type, newInfo.type]),
11834                            union ? info.isReadonly || newInfo.isReadonly : info.isReadonly && newInfo.isReadonly);
11835                        return indexInfos;
11836                    }
11837                }
11838            }
11839            return append(indexInfos, newInfo);
11840        }
11841
11842        /**
11843         * Converts an AnonymousType to a ResolvedType.
11844         */
11845        function resolveAnonymousTypeMembers(type: AnonymousType) {
11846            if (type.target) {
11847                setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray);
11848                const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper!, /*mappingThisOnly*/ false);
11849                const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper!);
11850                const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper!);
11851                const indexInfos = instantiateIndexInfos(getIndexInfosOfType(type.target), type.mapper!);
11852                setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos);
11853                return;
11854            }
11855            const symbol = getMergedSymbol(type.symbol);
11856            if (symbol.flags & SymbolFlags.TypeLiteral) {
11857                setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray);
11858                const members = getMembersOfSymbol(symbol);
11859                const callSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call));
11860                const constructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New));
11861                const indexInfos = getIndexInfosOfSymbol(symbol);
11862                setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos);
11863                return;
11864            }
11865            // Combinations of function, class, enum and module
11866            let members = emptySymbols;
11867            let indexInfos: IndexInfo[] | undefined;
11868            if (symbol.exports) {
11869                members = getExportsOfSymbol(symbol);
11870                if (symbol === globalThisSymbol) {
11871                    const varsOnly = new Map<string, Symbol>() as SymbolTable;
11872                    members.forEach(p => {
11873                        if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) {
11874                            varsOnly.set(p.escapedName, p);
11875                        }
11876                    });
11877                    members = varsOnly;
11878                }
11879            }
11880            let baseConstructorIndexInfo: IndexInfo | undefined;
11881            setStructuredTypeMembers(type, members, emptyArray, emptyArray, emptyArray);
11882            if (symbol.flags & SymbolFlags.Class) {
11883                const classType = getDeclaredTypeOfClassOrInterface(symbol);
11884                const baseConstructorType = getBaseConstructorTypeOfClass(classType);
11885                if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.TypeVariable)) {
11886                    members = createSymbolTable(getNamedOrIndexSignatureMembers(members));
11887                    addInheritedMembers(members, getPropertiesOfType(baseConstructorType));
11888                }
11889                else if (baseConstructorType === anyType) {
11890                    baseConstructorIndexInfo = createIndexInfo(stringType, anyType, /*isReadonly*/ false);
11891                }
11892            }
11893
11894            const indexSymbol = getIndexSymbolFromSymbolTable(members);
11895            if (indexSymbol) {
11896                indexInfos = getIndexInfosOfIndexSymbol(indexSymbol);
11897            }
11898            else {
11899                if (baseConstructorIndexInfo) {
11900                    indexInfos = append(indexInfos, baseConstructorIndexInfo);
11901                }
11902                if (symbol.flags & SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & TypeFlags.Enum ||
11903                    some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & TypeFlags.NumberLike)))) {
11904                    indexInfos = append(indexInfos, enumNumberIndexInfo);
11905                }
11906            }
11907            setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos || emptyArray);
11908            // We resolve the members before computing the signatures because a signature may use
11909            // typeof with a qualified name expression that circularly references the type we are
11910            // in the process of resolving (see issue #6072). The temporarily empty signature list
11911            // will never be observed because a qualified name can't reference signatures.
11912            if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
11913                type.callSignatures = getSignaturesOfSymbol(symbol);
11914            }
11915            // And likewise for construct signatures for classes
11916            if (symbol.flags & SymbolFlags.Class) {
11917                const classType = getDeclaredTypeOfClassOrInterface(symbol);
11918                if (symbol.flags & SymbolFlags.Annotation) {
11919                    // Make call signature "(annotationType): voidType"
11920                    const proto = getPropertyOfType(getTypeOfSymbol(symbol), "prototype" as __String)!;
11921                    type.callSignatures = [createSignature(
11922                        /*declaration*/ undefined,
11923                        /*typeParameters*/ undefined,
11924                        /*thisParameter*/  undefined,
11925                        /*parameters*/ [proto],
11926                        /*resolvedReturnType*/ voidType,
11927                        /*resolvedTypePredicate*/ undefined,
11928                        /*resolvedReturnType*/ 1,
11929                        /*flags*/ SignatureFlags.None)];
11930                    type.constructSignatures = [];
11931                    return;
11932                }
11933                let constructSignatures = symbol.members ? getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)) : emptyArray;
11934                if (symbol.flags & SymbolFlags.Function) {
11935                    constructSignatures = addRange(constructSignatures.slice(), mapDefined(
11936                        type.callSignatures,
11937                        sig => isJSConstructor(sig.declaration) ?
11938                            createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags) :
11939                            undefined));
11940                }
11941                if (!constructSignatures.length) {
11942                    constructSignatures = getDefaultConstructSignatures(classType);
11943                }
11944                type.constructSignatures = constructSignatures;
11945            }
11946        }
11947
11948        type ReplaceableIndexedAccessType = IndexedAccessType & { objectType: TypeParameter, indexType: TypeParameter };
11949        function replaceIndexedAccess(instantiable: Type, type: ReplaceableIndexedAccessType, replacement: Type) {
11950            // map type.indexType to 0
11951            // map type.objectType to `[TReplacement]`
11952            // thus making the indexed access `[TReplacement][0]` or `TReplacement`
11953            return instantiateType(instantiable, createTypeMapper([type.indexType, type.objectType], [getNumberLiteralType(0), createTupleType([replacement])]));
11954        }
11955
11956        function resolveReverseMappedTypeMembers(type: ReverseMappedType) {
11957            const indexInfo = getIndexInfoOfType(type.source, stringType);
11958            const modifiers = getMappedTypeModifiers(type.mappedType);
11959            const readonlyMask = modifiers & MappedTypeModifiers.IncludeReadonly ? false : true;
11960            const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : SymbolFlags.Optional;
11961            const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : emptyArray;
11962            const members = createSymbolTable();
11963            for (const prop of getPropertiesOfType(type.source)) {
11964                const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0);
11965                const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol;
11966                inferredProp.declarations = prop.declarations;
11967                inferredProp.nameType = getSymbolLinks(prop).nameType;
11968                inferredProp.propertyType = getTypeOfSymbol(prop);
11969                if (type.constraintType.type.flags & TypeFlags.IndexedAccess
11970                    && (type.constraintType.type as IndexedAccessType).objectType.flags & TypeFlags.TypeParameter
11971                    && (type.constraintType.type as IndexedAccessType).indexType.flags & TypeFlags.TypeParameter) {
11972                    // A reverse mapping of `{[K in keyof T[K_1]]: T[K_1]}` is the same as that of `{[K in keyof T]: T}`, since all we care about is
11973                    // inferring to the "type parameter" (or indexed access) shared by the constraint and template. So, to reduce the number of
11974                    // type identities produced, we simplify such indexed access occurences
11975                    const newTypeParam = (type.constraintType.type as IndexedAccessType).objectType;
11976                    const newMappedType = replaceIndexedAccess(type.mappedType, type.constraintType.type as ReplaceableIndexedAccessType, newTypeParam);
11977                    inferredProp.mappedType = newMappedType as MappedType;
11978                    inferredProp.constraintType = getIndexType(newTypeParam) as IndexType;
11979                }
11980                else {
11981                    inferredProp.mappedType = type.mappedType;
11982                    inferredProp.constraintType = type.constraintType;
11983                }
11984                members.set(prop.escapedName, inferredProp);
11985            }
11986            setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos);
11987        }
11988
11989        // Return the lower bound of the key type in a mapped type. Intuitively, the lower
11990        // bound includes those keys that are known to always be present, for example because
11991        // because of constraints on type parameters (e.g. 'keyof T' for a constrained T).
11992        function getLowerBoundOfKeyType(type: Type): Type {
11993            if (type.flags & TypeFlags.Index) {
11994                const t = getApparentType((type as IndexType).type);
11995                return isGenericTupleType(t) ? getKnownKeysOfTupleType(t) : getIndexType(t);
11996            }
11997            if (type.flags & TypeFlags.Conditional) {
11998                if ((type as ConditionalType).root.isDistributive) {
11999                    const checkType = (type as ConditionalType).checkType;
12000                    const constraint = getLowerBoundOfKeyType(checkType);
12001                    if (constraint !== checkType) {
12002                        return getConditionalTypeInstantiation(type as ConditionalType, prependTypeMapping((type as ConditionalType).root.checkType, constraint, (type as ConditionalType).mapper));
12003                    }
12004                }
12005                return type;
12006            }
12007            if (type.flags & TypeFlags.Union) {
12008                return mapType(type as UnionType, getLowerBoundOfKeyType);
12009            }
12010            if (type.flags & TypeFlags.Intersection) {
12011                // Similarly to getTypeFromIntersectionTypeNode, we preserve the special string & {}, number & {},
12012                // and bigint & {} intersections that are used to prevent subtype reduction in union types.
12013                const types = (type as IntersectionType).types;
12014                if (types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType) {
12015                    return type;
12016                }
12017                return getIntersectionType(sameMap((type as UnionType).types, getLowerBoundOfKeyType));
12018            }
12019            return type;
12020        }
12021
12022        function getIsLateCheckFlag(s: Symbol): CheckFlags {
12023            return getCheckFlags(s) & CheckFlags.Late;
12024        }
12025
12026        function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: Type, include: TypeFlags, stringsOnly: boolean, cb: (keyType: Type) => void) {
12027            for (const prop of getPropertiesOfType(type)) {
12028                cb(getLiteralTypeFromProperty(prop, include));
12029            }
12030            if (type.flags & TypeFlags.Any) {
12031                cb(stringType);
12032            }
12033            else {
12034                for (const info of getIndexInfosOfType(type)) {
12035                    if (!stringsOnly || info.keyType.flags & (TypeFlags.String | TypeFlags.TemplateLiteral)) {
12036                        cb(info.keyType);
12037                    }
12038                }
12039            }
12040        }
12041
12042        /** Resolve the members of a mapped type { [P in K]: T } */
12043        function resolveMappedTypeMembers(type: MappedType) {
12044            const members: SymbolTable = createSymbolTable();
12045            let indexInfos: IndexInfo[] | undefined;
12046            // Resolve upfront such that recursive references see an empty object type.
12047            setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray);
12048            // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type,
12049            // and T as the template type.
12050            const typeParameter = getTypeParameterFromMappedType(type);
12051            const constraintType = getConstraintTypeFromMappedType(type);
12052            const nameType = getNameTypeFromMappedType(type.target as MappedType || type);
12053            const templateType = getTemplateTypeFromMappedType(type.target as MappedType || type);
12054            const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
12055            const templateModifiers = getMappedTypeModifiers(type);
12056            const include = keyofStringsOnly ? TypeFlags.StringLiteral : TypeFlags.StringOrNumberLiteralOrUnique;
12057            if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
12058                // We have a { [P in keyof T]: X }
12059                forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, include, keyofStringsOnly, addMemberForKeyType);
12060            }
12061            else {
12062                forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
12063            }
12064            setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos || emptyArray);
12065
12066            function addMemberForKeyType(keyType: Type) {
12067                const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType;
12068                forEachType(propNameType, t => addMemberForKeyTypeWorker(keyType, t));
12069            }
12070
12071            function addMemberForKeyTypeWorker(keyType: Type, propNameType: Type) {
12072                // If the current iteration type constituent is a string literal type, create a property.
12073                // Otherwise, for type string create a string index signature.
12074                if (isTypeUsableAsPropertyName(propNameType)) {
12075                    const propName = getPropertyNameFromType(propNameType);
12076                    // String enum members from separate enums with identical values
12077                    // are distinct types with the same property name. Make the resulting
12078                    // property symbol's name type be the union of those enum member types.
12079                    const existingProp = members.get(propName) as MappedSymbol | undefined;
12080                    if (existingProp) {
12081                        existingProp.nameType = getUnionType([existingProp.nameType!, propNameType]);
12082                        existingProp.keyType = getUnionType([existingProp.keyType, keyType]);
12083                    }
12084                    else {
12085                        const modifiersProp = isTypeUsableAsPropertyName(keyType) ? getPropertyOfType(modifiersType, getPropertyNameFromType(keyType)) : undefined;
12086                        const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional ||
12087                            !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional);
12088                        const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly ||
12089                            !(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp && isReadonlySymbol(modifiersProp));
12090                        const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional;
12091                        const lateFlag: CheckFlags = modifiersProp ? getIsLateCheckFlag(modifiersProp) : 0;
12092                        const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName,
12093                            lateFlag | CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)) as MappedSymbol;
12094                        prop.mappedType = type;
12095                        prop.nameType = propNameType;
12096                        prop.keyType = keyType;
12097                        if (modifiersProp) {
12098                            prop.syntheticOrigin = modifiersProp;
12099                            // If the mapped type has an `as XXX` clause, the property name likely won't match the declaration name and
12100                            // multiple properties may map to the same name. Thus, we attach no declarations to the symbol.
12101                            prop.declarations = nameType ? undefined : modifiersProp.declarations;
12102                        }
12103                        members.set(propName, prop);
12104                    }
12105                }
12106                else if (isValidIndexKeyType(propNameType) || propNameType.flags & (TypeFlags.Any | TypeFlags.Enum)) {
12107                    const indexKeyType = propNameType.flags & (TypeFlags.Any | TypeFlags.String) ? stringType :
12108                        propNameType.flags & (TypeFlags.Number | TypeFlags.Enum) ? numberType :
12109                        propNameType;
12110                    const propType = instantiateType(templateType, appendTypeMapping(type.mapper, typeParameter, keyType));
12111                    const indexInfo = createIndexInfo(indexKeyType, propType, !!(templateModifiers & MappedTypeModifiers.IncludeReadonly));
12112                    indexInfos = appendIndexInfo(indexInfos, indexInfo, /*union*/ true);
12113                }
12114            }
12115        }
12116
12117        function getTypeOfMappedSymbol(symbol: MappedSymbol) {
12118            if (!symbol.type) {
12119                const mappedType = symbol.mappedType;
12120                if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
12121                    mappedType.containsError = true;
12122                    return errorType;
12123                }
12124                const templateType = getTemplateTypeFromMappedType(mappedType.target as MappedType || mappedType);
12125                const mapper = appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), symbol.keyType);
12126                const propType = instantiateType(templateType, mapper);
12127                // When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the
12128                // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
12129                // mode, if the underlying property is optional we remove 'undefined' from the type.
12130                let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) :
12131                    symbol.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) :
12132                    propType;
12133                if (!popTypeResolution()) {
12134                    error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType));
12135                    type = errorType;
12136                }
12137                symbol.type = type;
12138            }
12139            return symbol.type;
12140        }
12141
12142        function getTypeParameterFromMappedType(type: MappedType) {
12143            return type.typeParameter ||
12144                (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter)));
12145        }
12146
12147        function getConstraintTypeFromMappedType(type: MappedType) {
12148            return type.constraintType ||
12149                (type.constraintType = getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)) || errorType);
12150        }
12151
12152        function getNameTypeFromMappedType(type: MappedType) {
12153            return type.declaration.nameType ?
12154                type.nameType || (type.nameType = instantiateType(getTypeFromTypeNode(type.declaration.nameType), type.mapper)) :
12155                undefined;
12156        }
12157
12158        function getTemplateTypeFromMappedType(type: MappedType) {
12159            return type.templateType ||
12160                (type.templateType = type.declaration.type ?
12161                    instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), /*isProperty*/ true, !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) :
12162                    errorType);
12163        }
12164
12165        function getConstraintDeclarationForMappedType(type: MappedType) {
12166            return getEffectiveConstraintOfTypeParameter(type.declaration.typeParameter);
12167        }
12168
12169        function isMappedTypeWithKeyofConstraintDeclaration(type: MappedType) {
12170            const constraintDeclaration = getConstraintDeclarationForMappedType(type)!; // TODO: GH#18217
12171            return constraintDeclaration.kind === SyntaxKind.TypeOperator &&
12172                (constraintDeclaration as TypeOperatorNode).operator === SyntaxKind.KeyOfKeyword;
12173        }
12174
12175        function getModifiersTypeFromMappedType(type: MappedType) {
12176            if (!type.modifiersType) {
12177                if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
12178                    // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
12179                    // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
12180                    // 'keyof T' to a literal union type and we can't recover T from that type.
12181                    type.modifiersType = instantiateType(getTypeFromTypeNode((getConstraintDeclarationForMappedType(type) as TypeOperatorNode).type), type.mapper);
12182                }
12183                else {
12184                    // Otherwise, get the declared constraint type, and if the constraint type is a type parameter,
12185                    // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T',
12186                    // the modifiers type is T. Otherwise, the modifiers type is unknown.
12187                    const declaredType = getTypeFromMappedTypeNode(type.declaration) as MappedType;
12188                    const constraint = getConstraintTypeFromMappedType(declaredType);
12189                    const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(constraint as TypeParameter) : constraint;
12190                    type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((extendedConstraint as IndexType).type, type.mapper) : unknownType;
12191                }
12192            }
12193            return type.modifiersType;
12194        }
12195
12196        function getMappedTypeModifiers(type: MappedType): MappedTypeModifiers {
12197            const declaration = type.declaration;
12198            return (declaration.readonlyToken ? declaration.readonlyToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeReadonly : MappedTypeModifiers.IncludeReadonly : 0) |
12199                (declaration.questionToken ? declaration.questionToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeOptional : MappedTypeModifiers.IncludeOptional : 0);
12200        }
12201
12202        function getMappedTypeOptionality(type: MappedType): number {
12203            const modifiers = getMappedTypeModifiers(type);
12204            return modifiers & MappedTypeModifiers.ExcludeOptional ? -1 : modifiers & MappedTypeModifiers.IncludeOptional ? 1 : 0;
12205        }
12206
12207        function getCombinedMappedTypeOptionality(type: MappedType): number {
12208            const optionality = getMappedTypeOptionality(type);
12209            const modifiersType = getModifiersTypeFromMappedType(type);
12210            return optionality || (isGenericMappedType(modifiersType) ? getMappedTypeOptionality(modifiersType) : 0);
12211        }
12212
12213        function isPartialMappedType(type: Type) {
12214            return !!(getObjectFlags(type) & ObjectFlags.Mapped && getMappedTypeModifiers(type as MappedType) & MappedTypeModifiers.IncludeOptional);
12215        }
12216
12217        function isGenericMappedType(type: Type): type is MappedType {
12218            if (getObjectFlags(type) & ObjectFlags.Mapped) {
12219                const constraint = getConstraintTypeFromMappedType(type as MappedType);
12220                if (isGenericIndexType(constraint)) {
12221                    return true;
12222                }
12223                // A mapped type is generic if the 'as' clause references generic types other than the iteration type.
12224                // To determine this, we substitute the constraint type (that we now know isn't generic) for the iteration
12225                // type and check whether the resulting type is generic.
12226                const nameType = getNameTypeFromMappedType(type as MappedType);
12227                if (nameType && isGenericIndexType(instantiateType(nameType, makeUnaryTypeMapper(getTypeParameterFromMappedType(type as MappedType), constraint)))) {
12228                    return true;
12229                }
12230            }
12231            return false;
12232        }
12233
12234        function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
12235            if (!(type as ResolvedType).members) {
12236                if (type.flags & TypeFlags.Object) {
12237                    if ((type as ObjectType).objectFlags & ObjectFlags.Reference) {
12238                        resolveTypeReferenceMembers(type as TypeReference);
12239                    }
12240                    else if ((type as ObjectType).objectFlags & ObjectFlags.ClassOrInterface) {
12241                        resolveClassOrInterfaceMembers(type as InterfaceType);
12242                    }
12243                    else if ((type as ReverseMappedType).objectFlags & ObjectFlags.ReverseMapped) {
12244                        resolveReverseMappedTypeMembers(type as ReverseMappedType);
12245                    }
12246                    else if ((type as ObjectType).objectFlags & ObjectFlags.Anonymous) {
12247                        resolveAnonymousTypeMembers(type as AnonymousType);
12248                    }
12249                    else if ((type as MappedType).objectFlags & ObjectFlags.Mapped) {
12250                        resolveMappedTypeMembers(type as MappedType);
12251                    }
12252                    else {
12253                        Debug.fail("Unhandled object type " + Debug.formatObjectFlags(type.objectFlags));
12254                    }
12255                }
12256                else if (type.flags & TypeFlags.Union) {
12257                    resolveUnionTypeMembers(type as UnionType);
12258                }
12259                else if (type.flags & TypeFlags.Intersection) {
12260                    resolveIntersectionTypeMembers(type as IntersectionType);
12261                }
12262                else {
12263                    Debug.fail("Unhandled type " + Debug.formatTypeFlags(type.flags));
12264                }
12265            }
12266            return type as ResolvedType;
12267        }
12268
12269        /** Return properties of an object type or an empty array for other types */
12270        function getPropertiesOfObjectType(type: Type): Symbol[] {
12271            if (type.flags & TypeFlags.Object) {
12272                return resolveStructuredTypeMembers(type as ObjectType).properties;
12273            }
12274            return emptyArray;
12275        }
12276
12277        /** If the given type is an object type and that type has a property by the given name,
12278         * return the symbol for that property. Otherwise return undefined.
12279         */
12280        function getPropertyOfObjectType(type: Type, name: __String): Symbol | undefined {
12281            if (type.flags & TypeFlags.Object) {
12282                const resolved = resolveStructuredTypeMembers(type as ObjectType);
12283                const symbol = resolved.members.get(name);
12284                if (symbol && symbolIsValue(symbol)) {
12285                    return symbol;
12286                }
12287            }
12288        }
12289
12290        function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
12291            if (!type.resolvedProperties) {
12292                const members = createSymbolTable();
12293                for (const current of type.types) {
12294                    for (const prop of getPropertiesOfType(current)) {
12295                        if (!members.has(prop.escapedName)) {
12296                            const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName);
12297                            if (combinedProp) {
12298                                members.set(prop.escapedName, combinedProp);
12299                            }
12300                        }
12301                    }
12302                    // The properties of a union type are those that are present in all constituent types, so
12303                    // we only need to check the properties of the first type without index signature
12304                    if (type.flags & TypeFlags.Union && getIndexInfosOfType(current).length === 0) {
12305                        break;
12306                    }
12307                }
12308                type.resolvedProperties = getNamedMembers(members);
12309            }
12310            return type.resolvedProperties;
12311        }
12312
12313        function getPropertiesOfType(type: Type): Symbol[] {
12314            type = getReducedApparentType(type);
12315            return type.flags & TypeFlags.UnionOrIntersection ?
12316                getPropertiesOfUnionOrIntersectionType(type as UnionType) :
12317                getPropertiesOfObjectType(type);
12318        }
12319
12320        function forEachPropertyOfType(type: Type, action: (symbol: Symbol, escapedName: __String) => void): void {
12321            type = getReducedApparentType(type);
12322            if (type.flags & TypeFlags.StructuredType) {
12323                resolveStructuredTypeMembers(type as StructuredType).members.forEach((symbol, escapedName) => {
12324                    if (isNamedMember(symbol, escapedName)) {
12325                        action(symbol, escapedName);
12326                    }
12327                });
12328            }
12329        }
12330
12331        function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean {
12332            const list = obj.properties as NodeArray<ObjectLiteralElementLike | JsxAttributeLike>;
12333            return list.some(property => {
12334                const nameType = property.name && getLiteralTypeFromPropertyName(property.name);
12335                const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
12336                const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name);
12337                return !!expected && isLiteralType(expected) && !isTypeAssignableTo(getTypeOfNode(property), expected);
12338            });
12339        }
12340
12341        function getAllPossiblePropertiesOfTypes(types: readonly Type[]): Symbol[] {
12342            const unionType = getUnionType(types);
12343            if (!(unionType.flags & TypeFlags.Union)) {
12344                return getAugmentedPropertiesOfType(unionType);
12345            }
12346
12347            const props = createSymbolTable();
12348            for (const memberType of types) {
12349                for (const { escapedName } of getAugmentedPropertiesOfType(memberType)) {
12350                    if (!props.has(escapedName)) {
12351                        const prop = createUnionOrIntersectionProperty(unionType as UnionType, escapedName);
12352                        // May be undefined if the property is private
12353                        if (prop) props.set(escapedName, prop);
12354                    }
12355                }
12356            }
12357            return arrayFrom(props.values());
12358        }
12359
12360        function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined {
12361            return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type as TypeParameter) :
12362                type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type as IndexedAccessType) :
12363                type.flags & TypeFlags.Conditional ? getConstraintOfConditionalType(type as ConditionalType) :
12364                getBaseConstraintOfType(type);
12365        }
12366
12367        function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type | undefined {
12368            return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined;
12369        }
12370
12371        function getConstraintOfIndexedAccess(type: IndexedAccessType) {
12372            return hasNonCircularBaseConstraint(type) ? getConstraintFromIndexedAccess(type) : undefined;
12373        }
12374
12375        function getSimplifiedTypeOrConstraint(type: Type) {
12376            const simplified = getSimplifiedType(type, /*writing*/ false);
12377            return simplified !== type ? simplified : getConstraintOfType(type);
12378        }
12379
12380        function getConstraintFromIndexedAccess(type: IndexedAccessType) {
12381            if (isMappedTypeGenericIndexedAccess(type)) {
12382                // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic,
12383                // we substitute an instantiation of E where P is replaced with X.
12384                return substituteIndexedMappedType(type.objectType as MappedType, type.indexType);
12385            }
12386            const indexConstraint = getSimplifiedTypeOrConstraint(type.indexType);
12387            if (indexConstraint && indexConstraint !== type.indexType) {
12388                const indexedAccess = getIndexedAccessTypeOrUndefined(type.objectType, indexConstraint, type.accessFlags);
12389                if (indexedAccess) {
12390                    return indexedAccess;
12391                }
12392            }
12393            const objectConstraint = getSimplifiedTypeOrConstraint(type.objectType);
12394            if (objectConstraint && objectConstraint !== type.objectType) {
12395                return getIndexedAccessTypeOrUndefined(objectConstraint, type.indexType, type.accessFlags);
12396            }
12397            return undefined;
12398        }
12399
12400        function getDefaultConstraintOfConditionalType(type: ConditionalType) {
12401            if (!type.resolvedDefaultConstraint) {
12402                // An `any` branch of a conditional type would normally be viral - specifically, without special handling here,
12403                // a conditional type with a single branch of type `any` would be assignable to anything, since it's constraint would simplify to
12404                // just `any`. This result is _usually_ unwanted - so instead here we elide an `any` branch from the constraint type,
12405                // in effect treating `any` like `never` rather than `unknown` in this location.
12406                const trueConstraint = getInferredTrueTypeFromConditionalType(type);
12407                const falseConstraint = getFalseTypeFromConditionalType(type);
12408                type.resolvedDefaultConstraint = isTypeAny(trueConstraint) ? falseConstraint : isTypeAny(falseConstraint) ? trueConstraint : getUnionType([trueConstraint, falseConstraint]);
12409            }
12410            return type.resolvedDefaultConstraint;
12411        }
12412
12413        function getConstraintOfDistributiveConditionalType(type: ConditionalType): Type | undefined {
12414            // Check if we have a conditional type of the form 'T extends U ? X : Y', where T is a constrained
12415            // type parameter. If so, create an instantiation of the conditional type where T is replaced
12416            // with its constraint. We do this because if the constraint is a union type it will be distributed
12417            // over the conditional type and possibly reduced. For example, 'T extends undefined ? never : T'
12418            // removes 'undefined' from T.
12419            // We skip returning a distributive constraint for a restrictive instantiation of a conditional type
12420            // as the constraint for all type params (check type included) have been replace with `unknown`, which
12421            // is going to produce even more false positive/negative results than the distribute constraint already does.
12422            // Please note: the distributive constraint is a kludge for emulating what a negated type could to do filter
12423            // a union - once negated types exist and are applied to the conditional false branch, this "constraint"
12424            // likely doesn't need to exist.
12425            if (type.root.isDistributive && type.restrictiveInstantiation !== type) {
12426                const simplified = getSimplifiedType(type.checkType, /*writing*/ false);
12427                const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
12428                if (constraint && constraint !== type.checkType) {
12429                    const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper));
12430                    if (!(instantiated.flags & TypeFlags.Never)) {
12431                        return instantiated;
12432                    }
12433                }
12434            }
12435            return undefined;
12436        }
12437
12438        function getConstraintFromConditionalType(type: ConditionalType) {
12439            return getConstraintOfDistributiveConditionalType(type) || getDefaultConstraintOfConditionalType(type);
12440        }
12441
12442        function getConstraintOfConditionalType(type: ConditionalType) {
12443            return hasNonCircularBaseConstraint(type) ? getConstraintFromConditionalType(type) : undefined;
12444        }
12445
12446        function getEffectiveConstraintOfIntersection(types: readonly Type[], targetIsUnion: boolean) {
12447            let constraints: Type[] | undefined;
12448            let hasDisjointDomainType = false;
12449            for (const t of types) {
12450                if (t.flags & TypeFlags.Instantiable) {
12451                    // We keep following constraints as long as we have an instantiable type that is known
12452                    // not to be circular or infinite (hence we stop on index access types).
12453                    let constraint = getConstraintOfType(t);
12454                    while (constraint && constraint.flags & (TypeFlags.TypeParameter | TypeFlags.Index | TypeFlags.Conditional)) {
12455                        constraint = getConstraintOfType(constraint);
12456                    }
12457                    if (constraint) {
12458                        constraints = append(constraints, constraint);
12459                        if (targetIsUnion) {
12460                            constraints = append(constraints, t);
12461                        }
12462                    }
12463                }
12464                else if (t.flags & TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) {
12465                    hasDisjointDomainType = true;
12466                }
12467            }
12468            // If the target is a union type or if we are intersecting with types belonging to one of the
12469            // disjoint domains, we may end up producing a constraint that hasn't been examined before.
12470            if (constraints && (targetIsUnion || hasDisjointDomainType)) {
12471                if (hasDisjointDomainType) {
12472                    // We add any types belong to one of the disjoint domains because they might cause the final
12473                    // intersection operation to reduce the union constraints.
12474                    for (const t of types) {
12475                        if (t.flags & TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) {
12476                            constraints = append(constraints, t);
12477                        }
12478                    }
12479                }
12480                // The source types were normalized; ensure the result is normalized too.
12481                return getNormalizedType(getIntersectionType(constraints), /*writing*/ false);
12482            }
12483            return undefined;
12484        }
12485
12486        function getBaseConstraintOfType(type: Type): Type | undefined {
12487            if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral | TypeFlags.StringMapping)) {
12488                const constraint = getResolvedBaseConstraint(type as InstantiableType | UnionOrIntersectionType);
12489                return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
12490            }
12491            return type.flags & TypeFlags.Index ? keyofConstraintType : undefined;
12492        }
12493
12494        /**
12495         * This is similar to `getBaseConstraintOfType` except it returns the input type if there's no base constraint, instead of `undefined`
12496         * It also doesn't map indexes to `string`, as where this is used this would be unneeded (and likely undesirable)
12497         */
12498        function getBaseConstraintOrType(type: Type) {
12499            return getBaseConstraintOfType(type) || type;
12500        }
12501
12502        function hasNonCircularBaseConstraint(type: InstantiableType): boolean {
12503            return getResolvedBaseConstraint(type) !== circularConstraintType;
12504        }
12505
12506        /**
12507         * Return the resolved base constraint of a type variable. The noConstraintType singleton is returned if the
12508         * type variable has no constraint, and the circularConstraintType singleton is returned if the constraint
12509         * circularly references the type variable.
12510         */
12511        function getResolvedBaseConstraint(type: InstantiableType | UnionOrIntersectionType): Type {
12512            if (type.resolvedBaseConstraint) {
12513                return type.resolvedBaseConstraint;
12514            }
12515            const stack: object[] = [];
12516            return type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type);
12517
12518            function getImmediateBaseConstraint(t: Type): Type {
12519                if (!t.immediateBaseConstraint) {
12520                    if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) {
12521                        return circularConstraintType;
12522                    }
12523                    let result;
12524                    // We always explore at least 10 levels of nested constraints. Thereafter, we continue to explore
12525                    // up to 50 levels of nested constraints provided there are no "deeply nested" types on the stack
12526                    // (i.e. no types for which five instantiations have been recorded on the stack). If we reach 50
12527                    // levels of nesting, we are presumably exploring a repeating pattern with a long cycle that hasn't
12528                    // yet triggered the deeply nested limiter. We have no test cases that actually get to 50 levels of
12529                    // nesting, so it is effectively just a safety stop.
12530                    const identity = getRecursionIdentity(t);
12531                    if (stack.length < 10 || stack.length < 50 && !contains(stack, identity)) {
12532                        stack.push(identity);
12533                        result = computeBaseConstraint(getSimplifiedType(t, /*writing*/ false));
12534                        stack.pop();
12535                    }
12536                    if (!popTypeResolution()) {
12537                        if (t.flags & TypeFlags.TypeParameter) {
12538                            const errorNode = getConstraintDeclaration(t as TypeParameter);
12539                            if (errorNode) {
12540                                const diagnostic = error(errorNode, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(t));
12541                                if (currentNode && !isNodeDescendantOf(errorNode, currentNode) && !isNodeDescendantOf(currentNode, errorNode)) {
12542                                    addRelatedInfo(diagnostic, createDiagnosticForNode(currentNode, Diagnostics.Circularity_originates_in_type_at_this_location));
12543                                }
12544                            }
12545                        }
12546                        result = circularConstraintType;
12547                    }
12548                    t.immediateBaseConstraint = result || noConstraintType;
12549                }
12550                return t.immediateBaseConstraint;
12551            }
12552
12553            function getBaseConstraint(t: Type): Type | undefined {
12554                const c = getImmediateBaseConstraint(t);
12555                return c !== noConstraintType && c !== circularConstraintType ? c : undefined;
12556            }
12557
12558            function computeBaseConstraint(t: Type): Type | undefined {
12559                if (t.flags & TypeFlags.TypeParameter) {
12560                    const constraint = getConstraintFromTypeParameter(t as TypeParameter);
12561                    return (t as TypeParameter).isThisType || !constraint ?
12562                        constraint :
12563                        getBaseConstraint(constraint);
12564                }
12565                if (t.flags & TypeFlags.UnionOrIntersection) {
12566                    const types = (t as UnionOrIntersectionType).types;
12567                    const baseTypes: Type[] = [];
12568                    let different = false;
12569                    for (const type of types) {
12570                        const baseType = getBaseConstraint(type);
12571                        if (baseType) {
12572                            if (baseType !== type) {
12573                                different = true;
12574                            }
12575                            baseTypes.push(baseType);
12576                        }
12577                        else {
12578                            different = true;
12579                        }
12580                    }
12581                    if (!different) {
12582                        return t;
12583                    }
12584                    return t.flags & TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) :
12585                        t.flags & TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) :
12586                        undefined;
12587                }
12588                if (t.flags & TypeFlags.Index) {
12589                    return keyofConstraintType;
12590                }
12591                if (t.flags & TypeFlags.TemplateLiteral) {
12592                    const types = (t as TemplateLiteralType).types;
12593                    const constraints = mapDefined(types, getBaseConstraint);
12594                    return constraints.length === types.length ? getTemplateLiteralType((t as TemplateLiteralType).texts, constraints) : stringType;
12595                }
12596                if (t.flags & TypeFlags.StringMapping) {
12597                    const constraint = getBaseConstraint((t as StringMappingType).type);
12598                    return constraint && constraint !== (t as StringMappingType).type ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType;
12599                }
12600                if (t.flags & TypeFlags.IndexedAccess) {
12601                    if (isMappedTypeGenericIndexedAccess(t)) {
12602                        // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic,
12603                        // we substitute an instantiation of E where P is replaced with X.
12604                        return getBaseConstraint(substituteIndexedMappedType((t as IndexedAccessType).objectType as MappedType, (t as IndexedAccessType).indexType));
12605                    }
12606                    const baseObjectType = getBaseConstraint((t as IndexedAccessType).objectType);
12607                    const baseIndexType = getBaseConstraint((t as IndexedAccessType).indexType);
12608                    const baseIndexedAccess = baseObjectType && baseIndexType && getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, (t as IndexedAccessType).accessFlags);
12609                    return baseIndexedAccess && getBaseConstraint(baseIndexedAccess);
12610                }
12611                if (t.flags & TypeFlags.Conditional) {
12612                    const constraint = getConstraintFromConditionalType(t as ConditionalType);
12613                    return constraint && getBaseConstraint(constraint);
12614                }
12615                if (t.flags & TypeFlags.Substitution) {
12616                    return getBaseConstraint(getSubstitutionIntersection(t as SubstitutionType));
12617                }
12618                return t;
12619            }
12620        }
12621
12622        function getApparentTypeOfIntersectionType(type: IntersectionType) {
12623            return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true));
12624        }
12625
12626        function getResolvedTypeParameterDefault(typeParameter: TypeParameter): Type | undefined {
12627            if (!typeParameter.default) {
12628                if (typeParameter.target) {
12629                    const targetDefault = getResolvedTypeParameterDefault(typeParameter.target);
12630                    typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType;
12631                }
12632                else {
12633                    // To block recursion, set the initial value to the resolvingDefaultType.
12634                    typeParameter.default = resolvingDefaultType;
12635                    const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default);
12636                    const defaultType = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType;
12637                    if (typeParameter.default === resolvingDefaultType) {
12638                        // If we have not been called recursively, set the correct default type.
12639                        typeParameter.default = defaultType;
12640                    }
12641                }
12642            }
12643            else if (typeParameter.default === resolvingDefaultType) {
12644                // If we are called recursively for this type parameter, mark the default as circular.
12645                typeParameter.default = circularConstraintType;
12646            }
12647            return typeParameter.default;
12648        }
12649
12650        /**
12651         * Gets the default type for a type parameter.
12652         *
12653         * If the type parameter is the result of an instantiation, this gets the instantiated
12654         * default type of its target. If the type parameter has no default type or the default is
12655         * circular, `undefined` is returned.
12656         */
12657        function getDefaultFromTypeParameter(typeParameter: TypeParameter): Type | undefined {
12658            const defaultType = getResolvedTypeParameterDefault(typeParameter);
12659            return defaultType !== noConstraintType && defaultType !== circularConstraintType ? defaultType : undefined;
12660        }
12661
12662        function hasNonCircularTypeParameterDefault(typeParameter: TypeParameter) {
12663            return getResolvedTypeParameterDefault(typeParameter) !== circularConstraintType;
12664        }
12665
12666        /**
12667         * Indicates whether the declaration of a typeParameter has a default type.
12668         */
12669        function hasTypeParameterDefault(typeParameter: TypeParameter): boolean {
12670            return !!(typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default));
12671        }
12672
12673        function getApparentTypeOfMappedType(type: MappedType) {
12674            return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type));
12675        }
12676
12677        function getResolvedApparentTypeOfMappedType(type: MappedType) {
12678            const typeVariable = getHomomorphicTypeVariable(type);
12679            if (typeVariable && !type.declaration.nameType) {
12680                const constraint = getConstraintOfTypeParameter(typeVariable);
12681                if (constraint && isArrayOrTupleType(constraint)) {
12682                    return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
12683                }
12684            }
12685            return type;
12686        }
12687
12688        function isMappedTypeGenericIndexedAccess(type: Type) {
12689            let objectType;
12690            return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped &&
12691                !isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) &&
12692                !(getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.ExcludeOptional) && !(objectType as MappedType).declaration.nameType);
12693        }
12694
12695        /**
12696         * For a type parameter, return the base constraint of the type parameter. For the string, number,
12697         * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
12698         * type itself.
12699         */
12700        function getApparentType(type: Type): Type {
12701            const t = !(type.flags & TypeFlags.Instantiable) ? type : getBaseConstraintOfType(type) || unknownType;
12702            return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as MappedType) :
12703                t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as IntersectionType) :
12704                t.flags & TypeFlags.StringLike ? globalStringType :
12705                t.flags & TypeFlags.NumberLike ? globalNumberType :
12706                t.flags & TypeFlags.BigIntLike ? getGlobalBigIntType() :
12707                t.flags & TypeFlags.BooleanLike ? globalBooleanType :
12708                t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType() :
12709                t.flags & TypeFlags.NonPrimitive ? emptyObjectType :
12710                t.flags & TypeFlags.Index ? keyofConstraintType :
12711                t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType :
12712                t;
12713        }
12714
12715        function getReducedApparentType(type: Type): Type {
12716            // Since getApparentType may return a non-reduced union or intersection type, we need to perform
12717            // type reduction both before and after obtaining the apparent type. For example, given a type parameter
12718            // 'T extends A | B', the type 'T & X' becomes 'A & X | B & X' after obtaining the apparent type, and
12719            // that type may need further reduction to remove empty intersections.
12720            return getReducedType(getApparentType(getReducedType(type)));
12721        }
12722
12723        function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
12724            let singleProp: Symbol | undefined;
12725            let propSet: ESMap<SymbolId, Symbol> | undefined;
12726            let indexTypes: Type[] | undefined;
12727            const isUnion = containingType.flags & TypeFlags.Union;
12728            // Flags we want to propagate to the result if they exist in all source symbols
12729            let optionalFlag: SymbolFlags | undefined;
12730            let syntheticFlag = CheckFlags.SyntheticMethod;
12731            let checkFlags = isUnion ? 0 : CheckFlags.Readonly;
12732            let mergedInstantiations = false;
12733            for (const current of containingType.types) {
12734                const type = getApparentType(current);
12735                if (!(isErrorType(type) || type.flags & TypeFlags.Never)) {
12736                    const prop = getPropertyOfType(type, name, skipObjectFunctionPropertyAugment);
12737                    const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
12738                    if (prop) {
12739                        if (prop.flags & SymbolFlags.ClassMember) {
12740                            optionalFlag ??= isUnion ? SymbolFlags.None : SymbolFlags.Optional;
12741                            if (isUnion) {
12742                                optionalFlag |= (prop.flags & SymbolFlags.Optional);
12743                            }
12744                            else {
12745                                optionalFlag &= prop.flags;
12746                            }
12747                        }
12748                        if (!singleProp) {
12749                            singleProp = prop;
12750                        }
12751                        else if (prop !== singleProp) {
12752                            const isInstantiation = (getTargetSymbol(prop) || prop) === (getTargetSymbol(singleProp) || singleProp);
12753                            // If the symbols are instances of one another with identical types - consider the symbols
12754                            // equivalent and just use the first one, which thus allows us to avoid eliding private
12755                            // members when intersecting a (this-)instantiations of a class with its raw base or another instance
12756                            if (isInstantiation && compareProperties(singleProp, prop, (a, b) => a === b ? Ternary.True : Ternary.False) === Ternary.True) {
12757                                // If we merged instantiations of a generic type, we replicate the symbol parent resetting behavior we used
12758                                // to do when we recorded multiple distinct symbols so that we still get, eg, `Array<T>.length` printed
12759                                // back and not `Array<string>.length` when we're looking at a `.length` access on a `string[] | number[]`
12760                                mergedInstantiations = !!singleProp.parent && !!length(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(singleProp.parent));
12761                            }
12762                            else {
12763                                if (!propSet) {
12764                                    propSet = new Map<SymbolId, Symbol>();
12765                                    propSet.set(getSymbolId(singleProp), singleProp);
12766                                }
12767                                const id = getSymbolId(prop);
12768                                if (!propSet.has(id)) {
12769                                    propSet.set(id, prop);
12770                                }
12771                            }
12772                        }
12773                        if (isUnion && isReadonlySymbol(prop)) {
12774                            checkFlags |= CheckFlags.Readonly;
12775                        }
12776                        else if (!isUnion && !isReadonlySymbol(prop)) {
12777                            checkFlags &= ~CheckFlags.Readonly;
12778                        }
12779                        checkFlags |= (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) |
12780                            (modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) |
12781                            (modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) |
12782                            (modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0);
12783                        if (!isPrototypeProperty(prop)) {
12784                            syntheticFlag = CheckFlags.SyntheticProperty;
12785                        }
12786                    }
12787                    else if (isUnion) {
12788                        const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name);
12789                        if (indexInfo) {
12790                            checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0);
12791                            indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type);
12792                        }
12793                        else if (isObjectLiteralType(type) && !(getObjectFlags(type) & ObjectFlags.ContainsSpread)) {
12794                            checkFlags |= CheckFlags.WritePartial;
12795                            indexTypes = append(indexTypes, undefinedType);
12796                        }
12797                        else {
12798                            checkFlags |= CheckFlags.ReadPartial;
12799                        }
12800                    }
12801                }
12802            }
12803            if (!singleProp ||
12804                isUnion &&
12805                (propSet || checkFlags & CheckFlags.Partial) &&
12806                checkFlags & (CheckFlags.ContainsPrivate | CheckFlags.ContainsProtected) &&
12807                !(propSet && getCommonDeclarationsOfSymbols(arrayFrom(propSet.values())))
12808            ) {
12809                // No property was found, or, in a union, a property has a private or protected declaration in one
12810                // constituent, but is missing or has a different declaration in another constituent.
12811                return undefined;
12812            }
12813            if (!propSet && !(checkFlags & CheckFlags.ReadPartial) && !indexTypes) {
12814                if (mergedInstantiations) {
12815                    // No symbol from a union/intersection should have a `.parent` set (since unions/intersections don't act as symbol parents)
12816                    // Unless that parent is "reconstituted" from the "first value declaration" on the symbol (which is likely different than its instantiated parent!)
12817                    // They also have a `.containingType` set, which affects some services endpoints behavior, like `getRootSymbol`
12818                    const clone = createSymbolWithType(singleProp, (singleProp as TransientSymbol).type);
12819                    clone.parent = singleProp.valueDeclaration?.symbol?.parent;
12820                    clone.containingType = containingType;
12821                    clone.mapper = (singleProp as TransientSymbol).mapper;
12822                    return clone;
12823                }
12824                else {
12825                    return singleProp;
12826                }
12827            }
12828            const props = propSet ? arrayFrom(propSet.values()) : [singleProp];
12829            let declarations: Declaration[] | undefined;
12830            let firstType: Type | undefined;
12831            let nameType: Type | undefined;
12832            const propTypes: Type[] = [];
12833            let writeTypes: Type[] | undefined;
12834            let firstValueDeclaration: Declaration | undefined;
12835            let hasNonUniformValueDeclaration = false;
12836            for (const prop of props) {
12837                if (!firstValueDeclaration) {
12838                    firstValueDeclaration = prop.valueDeclaration;
12839                }
12840                else if (prop.valueDeclaration && prop.valueDeclaration !== firstValueDeclaration) {
12841                    hasNonUniformValueDeclaration = true;
12842                }
12843                declarations = addRange(declarations, prop.declarations);
12844                const type = getTypeOfSymbol(prop);
12845                if (!firstType) {
12846                    firstType = type;
12847                    nameType = getSymbolLinks(prop).nameType;
12848                }
12849                const writeType = getWriteTypeOfSymbol(prop);
12850                if (writeTypes || writeType !== type) {
12851                    writeTypes = append(!writeTypes ? propTypes.slice() : writeTypes, writeType);
12852                }
12853                else if (type !== firstType) {
12854                    checkFlags |= CheckFlags.HasNonUniformType;
12855                }
12856                if (isLiteralType(type) || isPatternLiteralType(type) || type === uniqueLiteralType) {
12857                    checkFlags |= CheckFlags.HasLiteralType;
12858                }
12859                if (type.flags & TypeFlags.Never && type !== uniqueLiteralType) {
12860                    checkFlags |= CheckFlags.HasNeverType;
12861                }
12862                propTypes.push(type);
12863            }
12864            addRange(propTypes, indexTypes);
12865            const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
12866            result.containingType = containingType;
12867            if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
12868                result.valueDeclaration = firstValueDeclaration;
12869
12870                // Inherit information about parent type.
12871                if (firstValueDeclaration.symbol.parent) {
12872                    result.parent = firstValueDeclaration.symbol.parent;
12873                }
12874            }
12875
12876            result.declarations = declarations;
12877            result.nameType = nameType;
12878            if (propTypes.length > 2) {
12879                // When `propTypes` has the potential to explode in size when normalized, defer normalization until absolutely needed
12880                result.checkFlags |= CheckFlags.DeferredType;
12881                result.deferralParent = containingType;
12882                result.deferralConstituents = propTypes;
12883                result.deferralWriteConstituents = writeTypes;
12884            }
12885            else {
12886                result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes);
12887                if (writeTypes) {
12888                    result.writeType = isUnion ? getUnionType(writeTypes) : getIntersectionType(writeTypes);
12889                }
12890            }
12891            return result;
12892        }
12893
12894        // Return the symbol for a given property in a union or intersection type, or undefined if the property
12895        // does not exist in any constituent type. Note that the returned property may only be present in some
12896        // constituents, in which case the isPartial flag is set when the containing type is union type. We need
12897        // these partial properties when identifying discriminant properties, but otherwise they are filtered out
12898        // and do not appear to be present in the union type.
12899        function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
12900            let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) ||
12901                !skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined;
12902            if (!property) {
12903                property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment);
12904                if (property) {
12905                    const properties = skipObjectFunctionPropertyAugment ?
12906                        type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() :
12907                        type.propertyCache ||= createSymbolTable();
12908                    properties.set(name, property);
12909                }
12910            }
12911            return property;
12912        }
12913
12914        function getCommonDeclarationsOfSymbols(symbols: readonly Symbol[]) {
12915            let commonDeclarations: Set<Node> | undefined;
12916            for (const symbol of symbols) {
12917                if (!symbol.declarations) {
12918                    return undefined;
12919                }
12920                if (!commonDeclarations) {
12921                    commonDeclarations = new Set(symbol.declarations);
12922                    continue;
12923                }
12924                commonDeclarations.forEach(declaration => {
12925                    if (!contains(symbol.declarations, declaration)) {
12926                        commonDeclarations!.delete(declaration);
12927                    }
12928                });
12929                if (commonDeclarations.size === 0) {
12930                    return undefined;
12931                }
12932            }
12933            return commonDeclarations;
12934        }
12935
12936        function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
12937            const property = getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment);
12938            // We need to filter out partial properties in union types
12939            return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined;
12940        }
12941
12942        /**
12943         * Return the reduced form of the given type. For a union type, it is a union of the normalized constituent types.
12944         * For an intersection of types containing one or more mututally exclusive discriminant properties, it is 'never'.
12945         * For all other types, it is simply the type itself. Discriminant properties are considered mutually exclusive when
12946         * no constituent property has type 'never', but the intersection of the constituent property types is 'never'.
12947         */
12948        function getReducedType(type: Type): Type {
12949            if (type.flags & TypeFlags.Union && (type as UnionType).objectFlags & ObjectFlags.ContainsIntersections) {
12950                return (type as UnionType).resolvedReducedType || ((type as UnionType).resolvedReducedType = getReducedUnionType(type as UnionType));
12951            }
12952            else if (type.flags & TypeFlags.Intersection) {
12953                if (!((type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) {
12954                    (type as IntersectionType).objectFlags |= ObjectFlags.IsNeverIntersectionComputed |
12955                        (some(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isNeverReducedProperty) ? ObjectFlags.IsNeverIntersection : 0);
12956                }
12957                return (type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type;
12958            }
12959            return type;
12960        }
12961
12962        function getReducedUnionType(unionType: UnionType) {
12963            const reducedTypes = sameMap(unionType.types, getReducedType);
12964            if (reducedTypes === unionType.types) {
12965                return unionType;
12966            }
12967            const reduced = getUnionType(reducedTypes);
12968            if (reduced.flags & TypeFlags.Union) {
12969                (reduced as UnionType).resolvedReducedType = reduced;
12970            }
12971            return reduced;
12972        }
12973
12974        function isNeverReducedProperty(prop: Symbol) {
12975            return isDiscriminantWithNeverType(prop) || isConflictingPrivateProperty(prop);
12976        }
12977
12978        function isDiscriminantWithNeverType(prop: Symbol) {
12979            // Return true for a synthetic non-optional property with non-uniform types, where at least one is
12980            // a literal type and none is never, that reduces to never.
12981            return !(prop.flags & SymbolFlags.Optional) &&
12982                (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant &&
12983                !!(getTypeOfSymbol(prop).flags & TypeFlags.Never);
12984        }
12985
12986        function isConflictingPrivateProperty(prop: Symbol) {
12987            // Return true for a synthetic property with multiple declarations, at least one of which is private.
12988            return !prop.valueDeclaration && !!(getCheckFlags(prop) & CheckFlags.ContainsPrivate);
12989        }
12990
12991        function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: Type) {
12992            if (type.flags & TypeFlags.Intersection && getObjectFlags(type) & ObjectFlags.IsNeverIntersection) {
12993                const neverProp = find(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isDiscriminantWithNeverType);
12994                if (neverProp) {
12995                    return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents,
12996                        typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp));
12997                }
12998                const privateProp = find(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isConflictingPrivateProperty);
12999                if (privateProp) {
13000                    return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some,
13001                        typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp));
13002                }
13003            }
13004            return errorInfo;
13005        }
13006
13007        /**
13008         * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
13009         * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
13010         * Object and Function as appropriate.
13011         *
13012         * @param type a type to look up property from
13013         * @param name a name of property to look up in a given type
13014         */
13015        function getPropertyOfType(type: Type, name: __String, skipObjectFunctionPropertyAugment?: boolean, includeTypeOnlyMembers?: boolean): Symbol | undefined {
13016            type = getReducedApparentType(type);
13017            if (type.flags & TypeFlags.Object) {
13018                const resolved = resolveStructuredTypeMembers(type as ObjectType);
13019                const symbol = resolved.members.get(name);
13020                if (symbol && symbolIsValue(symbol, includeTypeOnlyMembers)) {
13021                    return symbol;
13022                }
13023                if (skipObjectFunctionPropertyAugment) return undefined;
13024                const functionType = resolved === anyFunctionType ? globalFunctionType :
13025                    resolved.callSignatures.length ? globalCallableFunctionType :
13026                    resolved.constructSignatures.length ? globalNewableFunctionType :
13027                    undefined;
13028                if (functionType) {
13029                    const symbol = getPropertyOfObjectType(functionType, name);
13030                    if (symbol) {
13031                        return symbol;
13032                    }
13033                }
13034                return getPropertyOfObjectType(globalObjectType, name);
13035            }
13036            if (type.flags & TypeFlags.UnionOrIntersection) {
13037                return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment);
13038            }
13039            return undefined;
13040        }
13041
13042        function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): readonly Signature[] {
13043            if (type.flags & TypeFlags.StructuredType) {
13044                const resolved = resolveStructuredTypeMembers(type as ObjectType);
13045                return kind === SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures;
13046            }
13047            return emptyArray;
13048        }
13049
13050        /**
13051         * Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
13052         * maps primitive types and type parameters are to their apparent types.
13053         */
13054        function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] {
13055            return getSignaturesOfStructuredType(getReducedApparentType(type), kind);
13056        }
13057
13058        function findIndexInfo(indexInfos: readonly IndexInfo[], keyType: Type) {
13059            return find(indexInfos, info => info.keyType === keyType);
13060        }
13061
13062        function findApplicableIndexInfo(indexInfos: readonly IndexInfo[], keyType: Type) {
13063            // Index signatures for type 'string' are considered only when no other index signatures apply.
13064            let stringIndexInfo: IndexInfo | undefined;
13065            let applicableInfo: IndexInfo | undefined;
13066            let applicableInfos: IndexInfo[] | undefined;
13067            for (const info of indexInfos) {
13068                if (info.keyType === stringType) {
13069                    stringIndexInfo = info;
13070                }
13071                else if (isApplicableIndexType(keyType, info.keyType)) {
13072                    if (!applicableInfo) {
13073                        applicableInfo = info;
13074                    }
13075                    else {
13076                        (applicableInfos || (applicableInfos = [applicableInfo])).push(info);
13077                    }
13078                }
13079            }
13080            // When more than one index signature is applicable we create a synthetic IndexInfo. Instead of computing
13081            // the intersected key type, we just use unknownType for the key type as nothing actually depends on the
13082            // keyType property of the returned IndexInfo.
13083            return applicableInfos ? createIndexInfo(unknownType, getIntersectionType(map(applicableInfos, info => info.type)),
13084                    reduceLeft(applicableInfos, (isReadonly, info) => isReadonly && info.isReadonly, /*initial*/ true)) :
13085                applicableInfo ? applicableInfo :
13086                stringIndexInfo && isApplicableIndexType(keyType, stringType) ? stringIndexInfo :
13087                undefined;
13088        }
13089
13090        function isApplicableIndexType(source: Type, target: Type): boolean {
13091            // A 'string' index signature applies to types assignable to 'string' or 'number', and a 'number' index
13092            // signature applies to types assignable to 'number', `${number}` and numeric string literal types.
13093            return isTypeAssignableTo(source, target) ||
13094                target === stringType && isTypeAssignableTo(source, numberType) ||
13095                target === numberType && (source === numericStringType || !!(source.flags & TypeFlags.StringLiteral) && isNumericLiteralName((source as StringLiteralType).value));
13096        }
13097
13098        function getIndexInfosOfStructuredType(type: Type): readonly IndexInfo[] {
13099            if (type.flags & TypeFlags.StructuredType) {
13100                const resolved = resolveStructuredTypeMembers(type as ObjectType);
13101                return resolved.indexInfos;
13102            }
13103            return emptyArray;
13104        }
13105
13106        function getIndexInfosOfType(type: Type): readonly IndexInfo[] {
13107            return getIndexInfosOfStructuredType(getReducedApparentType(type));
13108        }
13109
13110        // Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and
13111        // maps primitive types and type parameters are to their apparent types.
13112        function getIndexInfoOfType(type: Type, keyType: Type): IndexInfo | undefined {
13113            return findIndexInfo(getIndexInfosOfType(type), keyType);
13114        }
13115
13116        // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
13117        // maps primitive types and type parameters are to their apparent types.
13118        function getIndexTypeOfType(type: Type, keyType: Type): Type | undefined {
13119            return getIndexInfoOfType(type, keyType)?.type;
13120        }
13121
13122        function getApplicableIndexInfos(type: Type, keyType: Type): IndexInfo[] {
13123            return getIndexInfosOfType(type).filter(info => isApplicableIndexType(keyType, info.keyType));
13124        }
13125
13126        function getApplicableIndexInfo(type: Type, keyType: Type): IndexInfo | undefined {
13127            return findApplicableIndexInfo(getIndexInfosOfType(type), keyType);
13128        }
13129
13130        function getApplicableIndexInfoForName(type: Type, name: __String): IndexInfo | undefined {
13131            return getApplicableIndexInfo(type, isLateBoundName(name) ? esSymbolType : getStringLiteralType(unescapeLeadingUnderscores(name)));
13132        }
13133
13134        // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
13135        // type checking functions).
13136        function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): readonly TypeParameter[] | undefined {
13137            let result: TypeParameter[] | undefined;
13138            for (const node of getEffectiveTypeParameterDeclarations(declaration)) {
13139                result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol));
13140            }
13141            return result?.length ? result
13142                : isFunctionDeclaration(declaration) ? getSignatureOfTypeTag(declaration)?.typeParameters
13143                : undefined;
13144        }
13145
13146        function symbolsToArray(symbols: SymbolTable): Symbol[] {
13147            const result: Symbol[] = [];
13148            symbols.forEach((symbol, id) => {
13149                if (!isReservedMemberName(id)) {
13150                    result.push(symbol);
13151                }
13152            });
13153            return result;
13154        }
13155
13156        function isJSDocOptionalParameter(node: ParameterDeclaration) {
13157            return isInJSFile(node) && (
13158                // node.type should only be a JSDocOptionalType when node is a parameter of a JSDocFunctionType
13159                node.type && node.type.kind === SyntaxKind.JSDocOptionalType
13160                || getJSDocParameterTags(node).some(({ isBracketed, typeExpression }) =>
13161                    isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType));
13162        }
13163
13164        function tryFindAmbientModule(moduleName: string, withAugmentations: boolean) {
13165            if (isExternalModuleNameRelative(moduleName)) {
13166                return undefined;
13167            }
13168            const symbol = getSymbol(globals, '"' + moduleName + '"' as __String, SymbolFlags.ValueModule);
13169            // merged symbol is module declaration symbol combined with all augmentations
13170            return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol;
13171        }
13172
13173        function isOptionalParameter(node: ParameterDeclaration | JSDocParameterTag | JSDocPropertyTag) {
13174            if (hasQuestionToken(node) || isOptionalJSDocPropertyLikeTag(node) || isJSDocOptionalParameter(node)) {
13175                return true;
13176            }
13177
13178            if (node.initializer) {
13179                const signature = getSignatureFromDeclaration(node.parent);
13180                const parameterIndex = node.parent.parameters.indexOf(node);
13181                Debug.assert(parameterIndex >= 0);
13182                // Only consider syntactic or instantiated parameters as optional, not `void` parameters as this function is used
13183                // in grammar checks and checking for `void` too early results in parameter types widening too early
13184                // and causes some noImplicitAny errors to be lost.
13185                return parameterIndex >= getMinArgumentCount(signature, MinArgumentCountFlags.StrongArityForUntypedJS | MinArgumentCountFlags.VoidIsNonOptional);
13186            }
13187            const iife = getImmediatelyInvokedFunctionExpression(node.parent);
13188            if (iife) {
13189                return !node.type &&
13190                    !node.dotDotDotToken &&
13191                    node.parent.parameters.indexOf(node) >= iife.arguments.length;
13192            }
13193
13194            return false;
13195        }
13196
13197        function isOptionalPropertyDeclaration(node: Declaration) {
13198            return isPropertyDeclaration(node) && !hasAccessorModifier(node) && node.questionToken;
13199        }
13200
13201        function isOptionalJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag {
13202            if (!isJSDocPropertyLikeTag(node)) {
13203                return false;
13204            }
13205            const { isBracketed, typeExpression } = node;
13206            return isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
13207        }
13208
13209        function createTypePredicate(kind: TypePredicateKind, parameterName: string | undefined, parameterIndex: number | undefined, type: Type | undefined): TypePredicate {
13210            return { kind, parameterName, parameterIndex, type } as TypePredicate;
13211        }
13212
13213        /**
13214         * Gets the minimum number of type arguments needed to satisfy all non-optional type
13215         * parameters.
13216         */
13217        function getMinTypeArgumentCount(typeParameters: readonly TypeParameter[] | undefined): number {
13218            let minTypeArgumentCount = 0;
13219            if (typeParameters) {
13220                for (let i = 0; i < typeParameters.length; i++) {
13221                    if (!hasTypeParameterDefault(typeParameters[i])) {
13222                        minTypeArgumentCount = i + 1;
13223                    }
13224                }
13225            }
13226            return minTypeArgumentCount;
13227        }
13228
13229        /**
13230         * Fill in default types for unsupplied type arguments. If `typeArguments` is undefined
13231         * when a default type is supplied, a new array will be created and returned.
13232         *
13233         * @param typeArguments The supplied type arguments.
13234         * @param typeParameters The requested type parameters.
13235         * @param minTypeArgumentCount The minimum number of required type arguments.
13236         */
13237        function fillMissingTypeArguments(typeArguments: readonly Type[], typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
13238        function fillMissingTypeArguments(typeArguments: readonly Type[] | undefined, typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
13239        function fillMissingTypeArguments(typeArguments: readonly Type[] | undefined, typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
13240            const numTypeParameters = length(typeParameters);
13241            if (!numTypeParameters) {
13242                return [];
13243            }
13244            const numTypeArguments = length(typeArguments);
13245            if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
13246                const result = typeArguments ? typeArguments.slice() : [];
13247                // Map invalid forward references in default types to the error type
13248                for (let i = numTypeArguments; i < numTypeParameters; i++) {
13249                    result[i] = errorType;
13250                }
13251                const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
13252                for (let i = numTypeArguments; i < numTypeParameters; i++) {
13253                    let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
13254                    if (isJavaScriptImplicitAny && defaultType && (isTypeIdenticalTo(defaultType, unknownType) || isTypeIdenticalTo(defaultType, emptyObjectType))) {
13255                        defaultType = anyType;
13256                    }
13257                    result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) : baseDefaultType;
13258                }
13259                result.length = typeParameters!.length;
13260                return result;
13261            }
13262            return typeArguments && typeArguments.slice();
13263        }
13264
13265        function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature {
13266            const links = getNodeLinks(declaration);
13267            if (!links.resolvedSignature) {
13268                const parameters: Symbol[] = [];
13269                let flags = SignatureFlags.None;
13270                let minArgumentCount = 0;
13271                let thisParameter: Symbol | undefined;
13272                let hasThisParameter = false;
13273                const iife = getImmediatelyInvokedFunctionExpression(declaration);
13274                const isJSConstructSignature = isJSDocConstructSignature(declaration);
13275                const isUntypedSignatureInJSFile = !iife &&
13276                    isInJSFile(declaration) &&
13277                    isValueSignatureDeclaration(declaration) &&
13278                    !hasJSDocParameterTags(declaration) &&
13279                    !getJSDocType(declaration);
13280                if (isUntypedSignatureInJSFile) {
13281                    flags |= SignatureFlags.IsUntypedSignatureInJSFile;
13282                }
13283
13284                // If this is a JSDoc construct signature, then skip the first parameter in the
13285                // parameter list.  The first parameter represents the return type of the construct
13286                // signature.
13287                for (let i = isJSConstructSignature ? 1 : 0; i < declaration.parameters.length; i++) {
13288                    const param = declaration.parameters[i];
13289
13290                    let paramSymbol = param.symbol;
13291                    const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type;
13292                    // Include parameter symbol instead of property symbol in the signature
13293                    if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) {
13294                        const resolvedSymbol = resolveName(param, paramSymbol.escapedName, SymbolFlags.Value, undefined, undefined, /*isUse*/ false);
13295                        paramSymbol = resolvedSymbol!;
13296                    }
13297                    if (i === 0 && paramSymbol && paramSymbol.escapedName === InternalSymbolName.This) {
13298                        hasThisParameter = true;
13299                        thisParameter = param.symbol;
13300                    }
13301                    else {
13302                        parameters.push(paramSymbol);
13303                    }
13304
13305                    if (type && type.kind === SyntaxKind.LiteralType) {
13306                        flags |= SignatureFlags.HasLiteralTypes;
13307                    }
13308
13309                    // Record a new minimum argument count if this is not an optional parameter
13310                    const isOptionalParameter = isOptionalJSDocPropertyLikeTag(param) ||
13311                        param.initializer || param.questionToken || isRestParameter(param) ||
13312                        iife && parameters.length > iife.arguments.length && !type ||
13313                        isJSDocOptionalParameter(param);
13314                    if (!isOptionalParameter) {
13315                        minArgumentCount = parameters.length;
13316                    }
13317                }
13318
13319                // If only one accessor includes a this-type annotation, the other behaves as if it had the same type annotation
13320                if ((declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) &&
13321                    hasBindableName(declaration) &&
13322                    (!hasThisParameter || !thisParameter)) {
13323                    const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
13324                    const other = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(declaration), otherKind);
13325                    if (other) {
13326                        thisParameter = getAnnotatedAccessorThisParameter(other);
13327                    }
13328                }
13329
13330                const classType = declaration.kind === SyntaxKind.Constructor ?
13331                    getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol))
13332                    : undefined;
13333                const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration);
13334                if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) {
13335                    flags |= SignatureFlags.HasRestParameter;
13336                }
13337                if (isConstructorTypeNode(declaration) && hasSyntacticModifier(declaration, ModifierFlags.Abstract) ||
13338                    isConstructorDeclaration(declaration) && hasSyntacticModifier(declaration.parent, ModifierFlags.Abstract)) {
13339                    flags |= SignatureFlags.Abstract;
13340                }
13341                links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters,
13342                    /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined,
13343                    minArgumentCount, flags);
13344            }
13345            return links.resolvedSignature;
13346        }
13347
13348        /**
13349         * A JS function gets a synthetic rest parameter if it references `arguments` AND:
13350         * 1. It has no parameters but at least one `@param` with a type that starts with `...`
13351         * OR
13352         * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...`
13353         */
13354        function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration | JSDocSignature, parameters: Symbol[]): boolean {
13355            if (isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) {
13356                return false;
13357            }
13358            const lastParam = lastOrUndefined(declaration.parameters);
13359            const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter(isJSDocParameterTag);
13360            const lastParamVariadicType = firstDefined(lastParamTags, p =>
13361                p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined);
13362
13363            const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String, CheckFlags.RestParameter);
13364            if (lastParamVariadicType) {
13365                // Parameter has effective annotation, lock in type
13366                syntheticArgsSymbol.type = createArrayType(getTypeFromTypeNode(lastParamVariadicType.type));
13367            }
13368            else {
13369                // Parameter has no annotation
13370                // By using a `DeferredType` symbol, we allow the type of this rest arg to be overriden by contextual type assignment so long as its type hasn't been
13371                // cached by `getTypeOfSymbol` yet.
13372                syntheticArgsSymbol.checkFlags |= CheckFlags.DeferredType;
13373                syntheticArgsSymbol.deferralParent = neverType;
13374                syntheticArgsSymbol.deferralConstituents = [anyArrayType];
13375                syntheticArgsSymbol.deferralWriteConstituents = [anyArrayType];
13376            }
13377            if (lastParamVariadicType) {
13378                // Replace the last parameter with a rest parameter.
13379                parameters.pop();
13380            }
13381            parameters.push(syntheticArgsSymbol);
13382            return true;
13383        }
13384
13385        function getSignatureOfTypeTag(node: SignatureDeclaration | JSDocSignature) {
13386            // should be attached to a function declaration or expression
13387            if (!(isInJSFile(node) && isFunctionLikeDeclaration(node))) return undefined;
13388            const typeTag = getJSDocTypeTag(node);
13389            return typeTag?.typeExpression && getSingleCallSignature(getTypeFromTypeNode(typeTag.typeExpression));
13390        }
13391
13392        function getParameterTypeOfTypeTag(func: FunctionLikeDeclaration, parameter: ParameterDeclaration) {
13393            const signature = getSignatureOfTypeTag(func);
13394            if (!signature) return undefined;
13395            const pos = func.parameters.indexOf(parameter);
13396            return parameter.dotDotDotToken ? getRestTypeAtPosition(signature, pos) : getTypeAtPosition(signature, pos);
13397        }
13398
13399        function getReturnTypeOfTypeTag(node: SignatureDeclaration | JSDocSignature) {
13400            const signature = getSignatureOfTypeTag(node);
13401            return signature && getReturnTypeOfSignature(signature);
13402        }
13403
13404        function containsArgumentsReference(declaration: SignatureDeclaration): boolean {
13405            const links = getNodeLinks(declaration);
13406            if (links.containsArgumentsReference === undefined) {
13407                if (links.flags & NodeCheckFlags.CaptureArguments) {
13408                    links.containsArgumentsReference = true;
13409                }
13410                else {
13411                    links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body!);
13412                }
13413            }
13414            return links.containsArgumentsReference;
13415
13416            function traverse(node: Node): boolean {
13417                if (!node) return false;
13418                switch (node.kind) {
13419                    case SyntaxKind.Identifier:
13420                        return (node as Identifier).escapedText === argumentsSymbol.escapedName && getReferencedValueSymbol(node as Identifier) === argumentsSymbol;
13421
13422                    case SyntaxKind.PropertyDeclaration:
13423                    case SyntaxKind.MethodDeclaration:
13424                    case SyntaxKind.GetAccessor:
13425                    case SyntaxKind.SetAccessor:
13426                        return (node as NamedDeclaration).name!.kind === SyntaxKind.ComputedPropertyName
13427                            && traverse((node as NamedDeclaration).name!);
13428
13429                    case SyntaxKind.PropertyAccessExpression:
13430                    case SyntaxKind.ElementAccessExpression:
13431                        return traverse((node as PropertyAccessExpression | ElementAccessExpression).expression);
13432
13433                    case SyntaxKind.PropertyAssignment:
13434                        return traverse((node as PropertyAssignment).initializer);
13435
13436                    default:
13437                        return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && !!forEachChild(node, traverse);
13438                }
13439            }
13440        }
13441
13442        function getSignaturesOfSymbol(symbol: Symbol | undefined): Signature[] {
13443            if (!symbol || !symbol.declarations) return emptyArray;
13444            const result: Signature[] = [];
13445            for (let i = 0; i < symbol.declarations.length; i++) {
13446                const decl = symbol.declarations[i];
13447                if (!isFunctionLike(decl)) continue;
13448                // Don't include signature if node is the implementation of an overloaded function. A node is considered
13449                // an implementation node if it has a body and the previous node is of the same kind and immediately
13450                // precedes the implementation node (i.e. has the same parent and ends where the implementation starts).
13451                if (i > 0 && (decl as FunctionLikeDeclaration).body) {
13452                    const previous = symbol.declarations[i - 1];
13453                    if (decl.parent === previous.parent && decl.kind === previous.kind && decl.pos === previous.end) {
13454                        continue;
13455                    }
13456                }
13457                // If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters.
13458                // Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would supress checks that the two are compatible.
13459                result.push(
13460                    (!isFunctionExpressionOrArrowFunction(decl) &&
13461                        !isObjectLiteralMethod(decl) &&
13462                        getSignatureOfTypeTag(decl)) ||
13463                        getSignatureFromDeclaration(decl)
13464                );
13465            }
13466            return result;
13467        }
13468
13469        function resolveExternalModuleTypeByLiteral(name: StringLiteral) {
13470            const moduleSym = resolveExternalModuleName(name, name);
13471            if (moduleSym) {
13472                const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym);
13473                if (resolvedModuleSymbol) {
13474                    return getTypeOfSymbol(resolvedModuleSymbol);
13475                }
13476            }
13477
13478            return anyType;
13479        }
13480
13481        function getThisTypeOfSignature(signature: Signature): Type | undefined {
13482            if (signature.thisParameter) {
13483                return getTypeOfSymbol(signature.thisParameter);
13484            }
13485        }
13486
13487        function getTypePredicateOfSignature(signature: Signature): TypePredicate | undefined {
13488            if (!signature.resolvedTypePredicate) {
13489                if (signature.target) {
13490                    const targetTypePredicate = getTypePredicateOfSignature(signature.target);
13491                    signature.resolvedTypePredicate = targetTypePredicate ? instantiateTypePredicate(targetTypePredicate, signature.mapper!) : noTypePredicate;
13492                }
13493                else if (signature.compositeSignatures) {
13494                    signature.resolvedTypePredicate = getUnionOrIntersectionTypePredicate(signature.compositeSignatures, signature.compositeKind) || noTypePredicate;
13495                }
13496                else {
13497                    const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration);
13498                    let jsdocPredicate: TypePredicate | undefined;
13499                    if (!type) {
13500                        const jsdocSignature = getSignatureOfTypeTag(signature.declaration!);
13501                        if (jsdocSignature && signature !== jsdocSignature) {
13502                            jsdocPredicate = getTypePredicateOfSignature(jsdocSignature);
13503                        }
13504                    }
13505                    signature.resolvedTypePredicate = type && isTypePredicateNode(type) ?
13506                        createTypePredicateFromTypePredicateNode(type, signature) :
13507                        jsdocPredicate || noTypePredicate;
13508                }
13509                Debug.assert(!!signature.resolvedTypePredicate);
13510            }
13511            return signature.resolvedTypePredicate === noTypePredicate ? undefined : signature.resolvedTypePredicate;
13512        }
13513
13514        function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, signature: Signature): TypePredicate {
13515            const parameterName = node.parameterName;
13516            const type = node.type && getTypeFromTypeNode(node.type);
13517            return parameterName.kind === SyntaxKind.ThisType ?
13518                createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsThis : TypePredicateKind.This, /*parameterName*/ undefined, /*parameterIndex*/ undefined, type) :
13519                createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsIdentifier : TypePredicateKind.Identifier, parameterName.escapedText as string,
13520                    findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText), type);
13521        }
13522
13523        function getUnionOrIntersectionType(types: Type[], kind: TypeFlags | undefined, unionReduction?: UnionReduction) {
13524            return kind !== TypeFlags.Intersection ? getUnionType(types, unionReduction) : getIntersectionType(types);
13525        }
13526
13527        function getReturnTypeOfSignature(signature: Signature): Type {
13528            if (!signature.resolvedReturnType) {
13529                if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) {
13530                    return errorType;
13531                }
13532                let type = signature.target ? instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper) :
13533                    signature.compositeSignatures ? instantiateType(getUnionOrIntersectionType(map(signature.compositeSignatures, getReturnTypeOfSignature), signature.compositeKind, UnionReduction.Subtype), signature.mapper) :
13534                    getReturnTypeFromAnnotation(signature.declaration!) ||
13535                    (nodeIsMissing((signature.declaration as FunctionLikeDeclaration).body) ? anyType : getReturnTypeFromBody(signature.declaration as FunctionLikeDeclaration));
13536                if (signature.flags & SignatureFlags.IsInnerCallChain) {
13537                    type = addOptionalTypeMarker(type);
13538                }
13539                else if (signature.flags & SignatureFlags.IsOuterCallChain) {
13540                    type = getOptionalType(type);
13541                }
13542                if (!popTypeResolution()) {
13543                    if (signature.declaration) {
13544                        const typeNode = getEffectiveReturnTypeNode(signature.declaration);
13545                        if (typeNode) {
13546                            error(typeNode, Diagnostics.Return_type_annotation_circularly_references_itself);
13547                        }
13548                        else if (noImplicitAny) {
13549                            const declaration = signature.declaration as Declaration;
13550                            const name = getNameOfDeclaration(declaration);
13551                            if (name) {
13552                                error(name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(name));
13553                            }
13554                            else {
13555                                error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
13556                            }
13557                        }
13558                    }
13559                    type = anyType;
13560                }
13561                signature.resolvedReturnType = type;
13562            }
13563            return signature.resolvedReturnType;
13564        }
13565
13566        function getReturnTypeFromAnnotation(declaration: SignatureDeclaration | JSDocSignature) {
13567            if (declaration.kind === SyntaxKind.Constructor) {
13568                return getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol));
13569            }
13570            if (isJSDocConstructSignature(declaration)) {
13571                return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type!); // TODO: GH#18217
13572            }
13573            const typeNode = getEffectiveReturnTypeNode(declaration);
13574            if (typeNode) {
13575                return getTypeFromTypeNode(typeNode);
13576            }
13577            if (declaration.kind === SyntaxKind.GetAccessor && hasBindableName(declaration)) {
13578                const jsDocType = isInJSFile(declaration) && getTypeForDeclarationFromJSDocComment(declaration);
13579                if (jsDocType) {
13580                    return jsDocType;
13581                }
13582                const setter = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(declaration), SyntaxKind.SetAccessor);
13583                const setterType = getAnnotatedAccessorType(setter);
13584                if (setterType) {
13585                    return setterType;
13586                }
13587            }
13588            return getReturnTypeOfTypeTag(declaration);
13589        }
13590
13591        function isResolvingReturnTypeOfSignature(signature: Signature) {
13592            return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0;
13593        }
13594
13595        function getRestTypeOfSignature(signature: Signature): Type {
13596            return tryGetRestTypeOfSignature(signature) || anyType;
13597        }
13598
13599        function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
13600            if (signatureHasRestParameter(signature)) {
13601                const sigRestType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
13602                const restType = isTupleType(sigRestType) ? getRestTypeOfTupleType(sigRestType) : sigRestType;
13603                return restType && getIndexTypeOfType(restType, numberType);
13604            }
13605            return undefined;
13606        }
13607
13608        function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature {
13609            const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript));
13610            if (inferredTypeParameters) {
13611                const returnSignature = getSingleCallOrConstructSignature(getReturnTypeOfSignature(instantiatedSignature));
13612                if (returnSignature) {
13613                    const newReturnSignature = cloneSignature(returnSignature);
13614                    newReturnSignature.typeParameters = inferredTypeParameters;
13615                    const newInstantiatedSignature = cloneSignature(instantiatedSignature);
13616                    newInstantiatedSignature.resolvedReturnType = getOrCreateTypeFromSignature(newReturnSignature);
13617                    return newInstantiatedSignature;
13618                }
13619            }
13620            return instantiatedSignature;
13621        }
13622
13623        function getSignatureInstantiationWithoutFillingInTypeArguments(signature: Signature, typeArguments: readonly Type[] | undefined): Signature {
13624            const instantiations = signature.instantiations || (signature.instantiations = new Map<string, Signature>());
13625            const id = getTypeListId(typeArguments);
13626            let instantiation = instantiations.get(id);
13627            if (!instantiation) {
13628                instantiations.set(id, instantiation = createSignatureInstantiation(signature, typeArguments));
13629            }
13630            return instantiation;
13631        }
13632
13633        function createSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined): Signature {
13634            return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true);
13635        }
13636
13637        function createSignatureTypeMapper(signature: Signature, typeArguments: readonly Type[] | undefined): TypeMapper {
13638            return createTypeMapper(signature.typeParameters!, typeArguments);
13639        }
13640
13641        function getErasedSignature(signature: Signature): Signature {
13642            return signature.typeParameters ?
13643                signature.erasedSignatureCache || (signature.erasedSignatureCache = createErasedSignature(signature)) :
13644                signature;
13645        }
13646
13647        function createErasedSignature(signature: Signature) {
13648            // Create an instantiation of the signature where all type arguments are the any type.
13649            return instantiateSignature(signature, createTypeEraser(signature.typeParameters!), /*eraseTypeParameters*/ true);
13650        }
13651
13652        function getCanonicalSignature(signature: Signature): Signature {
13653            return signature.typeParameters ?
13654                signature.canonicalSignatureCache || (signature.canonicalSignatureCache = createCanonicalSignature(signature)) :
13655                signature;
13656        }
13657
13658        function createCanonicalSignature(signature: Signature) {
13659            // Create an instantiation of the signature where each unconstrained type parameter is replaced with
13660            // its original. When a generic class or interface is instantiated, each generic method in the class or
13661            // interface is instantiated with a fresh set of cloned type parameters (which we need to handle scenarios
13662            // where different generations of the same type parameter are in scope). This leads to a lot of new type
13663            // identities, and potentially a lot of work comparing those identities, so here we create an instantiation
13664            // that uses the original type identities for all unconstrained type parameters.
13665            return getSignatureInstantiation(
13666                signature,
13667                map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp),
13668                isInJSFile(signature.declaration));
13669        }
13670
13671        function getBaseSignature(signature: Signature) {
13672            const typeParameters = signature.typeParameters;
13673            if (typeParameters) {
13674                if (signature.baseSignatureCache) {
13675                    return signature.baseSignatureCache;
13676                }
13677                const typeEraser = createTypeEraser(typeParameters);
13678                const baseConstraintMapper = createTypeMapper(typeParameters, map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType));
13679                let baseConstraints: readonly Type[] = map(typeParameters, tp => instantiateType(tp, baseConstraintMapper) || unknownType);
13680                // Run N type params thru the immediate constraint mapper up to N times
13681                // This way any noncircular interdependent type parameters are definitely resolved to their external dependencies
13682                for (let i = 0; i < typeParameters.length - 1; i++) {
13683                    baseConstraints = instantiateTypes(baseConstraints, baseConstraintMapper);
13684                }
13685                // and then apply a type eraser to remove any remaining circularly dependent type parameters
13686                baseConstraints = instantiateTypes(baseConstraints, typeEraser);
13687                return signature.baseSignatureCache = instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
13688            }
13689            return signature;
13690        }
13691
13692        function getOrCreateTypeFromSignature(signature: Signature): ObjectType {
13693            // There are two ways to declare a construct signature, one is by declaring a class constructor
13694            // using the constructor keyword, and the other is declaring a bare construct signature in an
13695            // object type literal or interface (using the new keyword). Each way of declaring a constructor
13696            // will result in a different declaration kind.
13697            if (!signature.isolatedSignatureType) {
13698                const kind = signature.declaration?.kind;
13699
13700                // If declaration is undefined, it is likely to be the signature of the default constructor.
13701                const isConstructor = kind === undefined || kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType;
13702
13703                const type = createObjectType(ObjectFlags.Anonymous);
13704                type.members = emptySymbols;
13705                type.properties = emptyArray;
13706                type.callSignatures = !isConstructor ? [signature] : emptyArray;
13707                type.constructSignatures = isConstructor ? [signature] : emptyArray;
13708                type.indexInfos = emptyArray;
13709                signature.isolatedSignatureType = type;
13710            }
13711
13712            return signature.isolatedSignatureType;
13713        }
13714
13715        function getIndexSymbol(symbol: Symbol): Symbol | undefined {
13716            return symbol.members ? getIndexSymbolFromSymbolTable(symbol.members) : undefined;
13717        }
13718
13719        function getIndexSymbolFromSymbolTable(symbolTable: SymbolTable): Symbol | undefined {
13720            return symbolTable.get(InternalSymbolName.Index);
13721        }
13722
13723        function createIndexInfo(keyType: Type, type: Type, isReadonly: boolean, declaration?: IndexSignatureDeclaration): IndexInfo {
13724            return { keyType, type, isReadonly, declaration };
13725        }
13726
13727        function getIndexInfosOfSymbol(symbol: Symbol): IndexInfo[] {
13728            const indexSymbol = getIndexSymbol(symbol);
13729            return indexSymbol ? getIndexInfosOfIndexSymbol(indexSymbol) : emptyArray;
13730        }
13731
13732        function getIndexInfosOfIndexSymbol(indexSymbol: Symbol): IndexInfo[] {
13733            if (indexSymbol.declarations) {
13734                const indexInfos: IndexInfo[] = [];
13735                for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) {
13736                    if (declaration.parameters.length === 1) {
13737                        const parameter = declaration.parameters[0];
13738                        if (parameter.type) {
13739                            forEachType(getTypeFromTypeNode(parameter.type), keyType => {
13740                                if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) {
13741                                    indexInfos.push(createIndexInfo(keyType, declaration.type ? getTypeFromTypeNode(declaration.type) : anyType,
13742                                        hasEffectiveModifier(declaration, ModifierFlags.Readonly), declaration));
13743                                }
13744                            });
13745                        }
13746                    }
13747                }
13748                return indexInfos;
13749            }
13750            return emptyArray;
13751        }
13752
13753        function isValidIndexKeyType(type: Type): boolean {
13754            return !!(type.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.ESSymbol)) || isPatternLiteralType(type) ||
13755                !!(type.flags & TypeFlags.Intersection) && !isGenericType(type) && some((type as IntersectionType).types, isValidIndexKeyType);
13756        }
13757
13758        function getConstraintDeclaration(type: TypeParameter): TypeNode | undefined {
13759            return mapDefined(filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), getEffectiveConstraintOfTypeParameter)[0];
13760        }
13761
13762        function getInferredTypeParameterConstraint(typeParameter: TypeParameter, omitTypeReferences?: boolean) {
13763            let inferences: Type[] | undefined;
13764            if (typeParameter.symbol?.declarations) {
13765                for (const declaration of typeParameter.symbol.declarations) {
13766                    if (declaration.parent.kind === SyntaxKind.InferType) {
13767                        // When an 'infer T' declaration is immediately contained in a type reference node
13768                        // (such as 'Foo<infer T>'), T's constraint is inferred from the constraint of the
13769                        // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are
13770                        // present, we form an intersection of the inferred constraint types.
13771                        const [childTypeParameter = declaration.parent, grandParent] = walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent);
13772                        if (grandParent.kind === SyntaxKind.TypeReference && !omitTypeReferences) {
13773                            const typeReference = grandParent as TypeReferenceNode;
13774                            const typeParameters = getTypeParametersForTypeReference(typeReference);
13775                            if (typeParameters) {
13776                                const index = typeReference.typeArguments!.indexOf(childTypeParameter as TypeNode);
13777                                if (index < typeParameters.length) {
13778                                    const declaredConstraint = getConstraintOfTypeParameter(typeParameters[index]);
13779                                    if (declaredConstraint) {
13780                                        // Type parameter constraints can reference other type parameters so
13781                                        // constraints need to be instantiated. If instantiation produces the
13782                                        // type parameter itself, we discard that inference. For example, in
13783                                        //   type Foo<T extends string, U extends T> = [T, U];
13784                                        //   type Bar<T> = T extends Foo<infer X, infer X> ? Foo<X, X> : T;
13785                                        // the instantiated constraint for U is X, so we discard that inference.
13786                                        const mapper = makeDeferredTypeMapper(typeParameters, typeParameters.map((_, index) => () => {
13787                                            return getEffectiveTypeArgumentAtIndex(typeReference, typeParameters, index);
13788                                        }));
13789                                        const constraint = instantiateType(declaredConstraint, mapper);
13790                                        if (constraint !== typeParameter) {
13791                                            inferences = append(inferences, constraint);
13792                                        }
13793                                    }
13794                                }
13795                            }
13796                        }
13797                        // When an 'infer T' declaration is immediately contained in a rest parameter declaration, a rest type
13798                        // or a named rest tuple element, we infer an 'unknown[]' constraint.
13799                        else if (grandParent.kind === SyntaxKind.Parameter && (grandParent as ParameterDeclaration).dotDotDotToken ||
13800                            grandParent.kind === SyntaxKind.RestType ||
13801                            grandParent.kind === SyntaxKind.NamedTupleMember && (grandParent as NamedTupleMember).dotDotDotToken) {
13802                            inferences = append(inferences, createArrayType(unknownType));
13803                        }
13804                        // When an 'infer T' declaration is immediately contained in a string template type, we infer a 'string'
13805                        // constraint.
13806                        else if (grandParent.kind === SyntaxKind.TemplateLiteralTypeSpan) {
13807                            inferences = append(inferences, stringType);
13808                        }
13809                        // When an 'infer T' declaration is in the constraint position of a mapped type, we infer a 'keyof any'
13810                        // constraint.
13811                        else if (grandParent.kind === SyntaxKind.TypeParameter && grandParent.parent.kind === SyntaxKind.MappedType) {
13812                            inferences = append(inferences, keyofConstraintType);
13813                        }
13814                        // When an 'infer T' declaration is the template of a mapped type, and that mapped type is the extends
13815                        // clause of a conditional whose check type is also a mapped type, give it a constraint equal to the template
13816                        // of the check type's mapped type
13817                        else if (grandParent.kind === SyntaxKind.MappedType && (grandParent as MappedTypeNode).type &&
13818                            skipParentheses((grandParent as MappedTypeNode).type!) === declaration.parent && grandParent.parent.kind === SyntaxKind.ConditionalType &&
13819                            (grandParent.parent as ConditionalTypeNode).extendsType === grandParent && (grandParent.parent as ConditionalTypeNode).checkType.kind === SyntaxKind.MappedType &&
13820                            ((grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode).type) {
13821                            const checkMappedType = (grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode;
13822                            const nodeType = getTypeFromTypeNode(checkMappedType.type!);
13823                            inferences = append(inferences, instantiateType(nodeType,
13824                                makeUnaryTypeMapper(getDeclaredTypeOfTypeParameter(getSymbolOfNode(checkMappedType.typeParameter)), checkMappedType.typeParameter.constraint ? getTypeFromTypeNode(checkMappedType.typeParameter.constraint) : keyofConstraintType)
13825                            ));
13826                        }
13827                    }
13828                }
13829            }
13830            return inferences && getIntersectionType(inferences);
13831        }
13832
13833        /** This is a worker function. Use getConstraintOfTypeParameter which guards against circular constraints. */
13834        function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type | undefined {
13835            if (!typeParameter.constraint) {
13836                if (typeParameter.target) {
13837                    const targetConstraint = getConstraintOfTypeParameter(typeParameter.target);
13838                    typeParameter.constraint = targetConstraint ? instantiateType(targetConstraint, typeParameter.mapper) : noConstraintType;
13839                }
13840                else {
13841                    const constraintDeclaration = getConstraintDeclaration(typeParameter);
13842                    if (!constraintDeclaration) {
13843                        typeParameter.constraint = getInferredTypeParameterConstraint(typeParameter) || noConstraintType;
13844                    }
13845                    else {
13846                        let type = getTypeFromTypeNode(constraintDeclaration);
13847                        if (type.flags & TypeFlags.Any && !isErrorType(type)) { // Allow errorType to propegate to keep downstream errors suppressed
13848                            // use keyofConstraintType as the base constraint for mapped type key constraints (unknown isn;t assignable to that, but `any` was),
13849                            // use unknown otherwise
13850                            type = constraintDeclaration.parent.parent.kind === SyntaxKind.MappedType ? keyofConstraintType : unknownType;
13851                        }
13852                        typeParameter.constraint = type;
13853                    }
13854                }
13855            }
13856            return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint;
13857        }
13858
13859        function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol | undefined {
13860            const tp = getDeclarationOfKind<TypeParameterDeclaration>(typeParameter.symbol, SyntaxKind.TypeParameter)!;
13861            const host = isJSDocTemplateTag(tp.parent) ? getEffectiveContainerForJSDocTemplateTag(tp.parent) : tp.parent;
13862            return host && getSymbolOfNode(host);
13863        }
13864
13865        function getTypeListId(types: readonly Type[] | undefined) {
13866            let result = "";
13867            if (types) {
13868                const length = types.length;
13869                let i = 0;
13870                while (i < length) {
13871                    const startId = types[i].id;
13872                    let count = 1;
13873                    while (i + count < length && types[i + count].id === startId + count) {
13874                        count++;
13875                    }
13876                    if (result.length) {
13877                        result += ",";
13878                    }
13879                    result += startId;
13880                    if (count > 1) {
13881                        result += ":" + count;
13882                    }
13883                    i += count;
13884                }
13885            }
13886            return result;
13887        }
13888
13889        function getAliasId(aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) {
13890            return aliasSymbol ? `@${getSymbolId(aliasSymbol)}` + (aliasTypeArguments ? `:${getTypeListId(aliasTypeArguments)}` : "") : "";
13891        }
13892
13893        // This function is used to propagate certain flags when creating new object type references and union types.
13894        // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type
13895        // of an object literal or a non-inferrable type. This is because there are operations in the type checker
13896        // that care about the presence of such types at arbitrary depth in a containing type.
13897        function getPropagatingFlagsOfTypes(types: readonly Type[], excludeKinds?: TypeFlags): ObjectFlags {
13898            let result: ObjectFlags = 0;
13899            for (const type of types) {
13900                if (excludeKinds === undefined || !(type.flags & excludeKinds)) {
13901                    result |= getObjectFlags(type);
13902                }
13903            }
13904            return result & ObjectFlags.PropagatingFlags;
13905        }
13906
13907        function createTypeReference(target: GenericType, typeArguments: readonly Type[] | undefined): TypeReference {
13908            const id = getTypeListId(typeArguments);
13909            let type = target.instantiations.get(id);
13910            if (!type) {
13911                type = createObjectType(ObjectFlags.Reference, target.symbol) as TypeReference;
13912                target.instantiations.set(id, type);
13913                type.objectFlags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments) : 0;
13914                type.target = target;
13915                type.resolvedTypeArguments = typeArguments;
13916            }
13917            return type;
13918        }
13919
13920        function cloneTypeReference(source: TypeReference): TypeReference {
13921            const type = createType(source.flags) as TypeReference;
13922            type.symbol = source.symbol;
13923            type.objectFlags = source.objectFlags;
13924            type.target = source.target;
13925            type.resolvedTypeArguments = source.resolvedTypeArguments;
13926            return type;
13927        }
13928
13929        function createDeferredTypeReference(target: GenericType, node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, mapper?: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): DeferredTypeReference {
13930            if (!aliasSymbol) {
13931                aliasSymbol = getAliasSymbolForTypeNode(node);
13932                const localAliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
13933                aliasTypeArguments = mapper ? instantiateTypes(localAliasTypeArguments, mapper) : localAliasTypeArguments;
13934            }
13935            const type = createObjectType(ObjectFlags.Reference, target.symbol) as DeferredTypeReference;
13936            type.target = target;
13937            type.node = node;
13938            type.mapper = mapper;
13939            type.aliasSymbol = aliasSymbol;
13940            type.aliasTypeArguments = aliasTypeArguments;
13941            return type;
13942        }
13943
13944        function getTypeArguments(type: TypeReference): readonly Type[] {
13945            if (!type.resolvedTypeArguments) {
13946                if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedTypeArguments)) {
13947                    return type.target.localTypeParameters?.map(() => errorType) || emptyArray;
13948                }
13949                const node = type.node;
13950                const typeArguments = !node ? emptyArray :
13951                    node.kind === SyntaxKind.TypeReference ? concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments(node, type.target.localTypeParameters!)) :
13952                    node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] :
13953                    map(node.elements, getTypeFromTypeNode);
13954                if (popTypeResolution()) {
13955                    type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments;
13956                }
13957                else {
13958                    type.resolvedTypeArguments = type.target.localTypeParameters?.map(() => errorType) || emptyArray;
13959                    error(
13960                        type.node || currentNode,
13961                        type.target.symbol ? Diagnostics.Type_arguments_for_0_circularly_reference_themselves : Diagnostics.Tuple_type_arguments_circularly_reference_themselves,
13962                        type.target.symbol && symbolToString(type.target.symbol)
13963                    );
13964                }
13965            }
13966            return type.resolvedTypeArguments;
13967        }
13968
13969        function getTypeReferenceArity(type: TypeReference): number {
13970            return length(type.target.typeParameters);
13971        }
13972
13973
13974        /**
13975         * Get type from type-reference that reference to class or interface
13976         */
13977        function getTypeFromClassOrInterfaceReference(node: NodeWithTypeArguments, symbol: Symbol): Type {
13978            const type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)) as InterfaceType;
13979            const typeParameters = type.localTypeParameters;
13980            if (typeParameters) {
13981                const numTypeArguments = length(node.typeArguments);
13982                const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
13983                const isJs = isInJSFile(node);
13984                const isJsImplicitAny = !noImplicitAny && isJs;
13985                if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) {
13986                    const missingAugmentsTag = isJs && isExpressionWithTypeArguments(node) && !isJSDocAugmentsTag(node.parent);
13987                    const diag = minTypeArgumentCount === typeParameters.length ?
13988                        missingAugmentsTag ?
13989                            Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag :
13990                            Diagnostics.Generic_type_0_requires_1_type_argument_s :
13991                        missingAugmentsTag ?
13992                            Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag :
13993                            Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments;
13994
13995                    const typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType);
13996                    error(node, diag, typeStr, minTypeArgumentCount, typeParameters.length);
13997                    if (!isJs) {
13998                        // TODO: Adopt same permissive behavior in TS as in JS to reduce follow-on editing experience failures (requires editing fillMissingTypeArguments)
13999                        return errorType;
14000                    }
14001                }
14002                if (node.kind === SyntaxKind.TypeReference && isDeferredTypeReferenceNode(node as TypeReferenceNode, length(node.typeArguments) !== typeParameters.length)) {
14003                    return createDeferredTypeReference(type as GenericType, node as TypeReferenceNode, /*mapper*/ undefined);
14004                }
14005                // In a type reference, the outer type parameters of the referenced class or interface are automatically
14006                // supplied as type arguments and the type reference only specifies arguments for the local type parameters
14007                // of the class or interface.
14008                const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgumentsFromTypeReferenceNode(node), typeParameters, minTypeArgumentCount, isJs));
14009                return createTypeReference(type as GenericType, typeArguments);
14010            }
14011            return checkNoTypeArguments(node, symbol) ? type : errorType;
14012        }
14013
14014        function getTypeAliasInstantiation(symbol: Symbol, typeArguments: readonly Type[] | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
14015            const type = getDeclaredTypeOfSymbol(symbol);
14016            if (type === intrinsicMarkerType && intrinsicTypeKinds.has(symbol.escapedName as string) && typeArguments && typeArguments.length === 1) {
14017                return getStringMappingType(symbol, typeArguments[0]);
14018            }
14019            const links = getSymbolLinks(symbol);
14020            const typeParameters = links.typeParameters!;
14021            const id = getTypeListId(typeArguments) + getAliasId(aliasSymbol, aliasTypeArguments);
14022            let instantiation = links.instantiations!.get(id);
14023            if (!instantiation) {
14024                links.instantiations!.set(id, instantiation = instantiateTypeWithAlias(type,
14025                    createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJSFile(symbol.valueDeclaration))),
14026                    aliasSymbol, aliasTypeArguments));
14027            }
14028            return instantiation;
14029        }
14030
14031        /**
14032         * Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include
14033         * references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the
14034         * declared type. Instantiations are cached using the type identities of the type arguments as the key.
14035         */
14036        function getTypeFromTypeAliasReference(node: NodeWithTypeArguments, symbol: Symbol): Type {
14037            if (getCheckFlags(symbol) & CheckFlags.Unresolved) {
14038                const typeArguments = typeArgumentsFromTypeReferenceNode(node);
14039                const id = getAliasId(symbol, typeArguments);
14040                let errorType = errorTypes.get(id);
14041                if (!errorType) {
14042                    errorType = createIntrinsicType(TypeFlags.Any, "error");
14043                    errorType.aliasSymbol = symbol;
14044                    errorType.aliasTypeArguments = typeArguments;
14045                    errorTypes.set(id, errorType);
14046                }
14047                return errorType;
14048            }
14049            const type = getDeclaredTypeOfSymbol(symbol);
14050            const typeParameters = getSymbolLinks(symbol).typeParameters;
14051            if (typeParameters) {
14052                const numTypeArguments = length(node.typeArguments);
14053                const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters);
14054                if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) {
14055                    error(node,
14056                        minTypeArgumentCount === typeParameters.length ?
14057                            Diagnostics.Generic_type_0_requires_1_type_argument_s :
14058                            Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments,
14059                        symbolToString(symbol),
14060                        minTypeArgumentCount,
14061                        typeParameters.length);
14062                    return errorType;
14063                }
14064                // We refrain from associating a local type alias with an instantiation of a top-level type alias
14065                // because the local alias may end up being referenced in an inferred return type where it is not
14066                // accessible--which in turn may lead to a large structural expansion of the type when generating
14067                // a .d.ts file. See #43622 for an example.
14068                const aliasSymbol = getAliasSymbolForTypeNode(node);
14069                const newAliasSymbol = aliasSymbol && (isLocalTypeAlias(symbol) || !isLocalTypeAlias(aliasSymbol)) ? aliasSymbol : undefined;
14070                return getTypeAliasInstantiation(symbol, typeArgumentsFromTypeReferenceNode(node), newAliasSymbol, getTypeArgumentsForAliasSymbol(newAliasSymbol));
14071            }
14072            return checkNoTypeArguments(node, symbol) ? type : errorType;
14073        }
14074
14075        function isLocalTypeAlias(symbol: Symbol) {
14076            const declaration = symbol.declarations?.find(isTypeAlias);
14077            return !!(declaration && getContainingFunction(declaration));
14078        }
14079
14080        function getTypeReferenceName(node: TypeReferenceType): EntityNameOrEntityNameExpression | undefined {
14081            switch (node.kind) {
14082                case SyntaxKind.TypeReference:
14083                    return node.typeName;
14084                case SyntaxKind.ExpressionWithTypeArguments:
14085                    // We only support expressions that are simple qualified names. For other
14086                    // expressions this produces undefined.
14087                    const expr = node.expression;
14088                    if (isEntityNameExpression(expr)) {
14089                        return expr;
14090                    }
14091                // fall through;
14092            }
14093
14094            return undefined;
14095        }
14096
14097        function getSymbolPath(symbol: Symbol): string {
14098            return symbol.parent ? `${getSymbolPath(symbol.parent)}.${symbol.escapedName}` : symbol.escapedName as string;
14099        }
14100
14101        function getUnresolvedSymbolForEntityName(name: EntityNameOrEntityNameExpression) {
14102            const identifier = name.kind === SyntaxKind.QualifiedName ? name.right :
14103                name.kind === SyntaxKind.PropertyAccessExpression ? name.name :
14104                name;
14105            const text = identifier.escapedText;
14106            if (text) {
14107                const parentSymbol = name.kind === SyntaxKind.QualifiedName ? getUnresolvedSymbolForEntityName(name.left) :
14108                    name.kind === SyntaxKind.PropertyAccessExpression ? getUnresolvedSymbolForEntityName(name.expression) :
14109                    undefined;
14110                const path = parentSymbol ? `${getSymbolPath(parentSymbol)}.${text}` : text as string;
14111                let result = unresolvedSymbols.get(path);
14112                if (!result) {
14113                    unresolvedSymbols.set(path, result = createSymbol(SymbolFlags.TypeAlias, text, CheckFlags.Unresolved));
14114                    result.parent = parentSymbol;
14115                    result.declaredType = unresolvedType;
14116                }
14117                return result;
14118            }
14119            return unknownSymbol;
14120        }
14121
14122        function resolveTypeReferenceName(typeReference: TypeReferenceType, meaning: SymbolFlags, ignoreErrors?: boolean) {
14123            const name = getTypeReferenceName(typeReference);
14124            if (!name) {
14125                return unknownSymbol;
14126            }
14127            const symbol = resolveEntityName(name, meaning, ignoreErrors);
14128            return symbol && symbol !== unknownSymbol ? symbol :
14129                ignoreErrors ? unknownSymbol : getUnresolvedSymbolForEntityName(name);
14130        }
14131
14132        function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol): Type {
14133            if (symbol === unknownSymbol) {
14134                return errorType;
14135            }
14136            symbol = getExpandoSymbol(symbol) || symbol;
14137            if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
14138                return getTypeFromClassOrInterfaceReference(node, symbol);
14139            }
14140            if (symbol.flags & SymbolFlags.TypeAlias) {
14141                return getTypeFromTypeAliasReference(node, symbol);
14142            }
14143            // Get type from reference to named type that cannot be generic (enum or type parameter)
14144            const res = tryGetDeclaredTypeOfSymbol(symbol);
14145            if (res) {
14146                return checkNoTypeArguments(node, symbol) ? getRegularTypeOfLiteralType(res) : errorType;
14147            }
14148            if (symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node)) {
14149                const jsdocType = getTypeFromJSDocValueReference(node, symbol);
14150                if (jsdocType) {
14151                    return jsdocType;
14152                }
14153                else {
14154                    // Resolve the type reference as a Type for the purpose of reporting errors.
14155                    resolveTypeReferenceName(node, SymbolFlags.Type);
14156                    return getTypeOfSymbol(symbol);
14157                }
14158            }
14159            return errorType;
14160        }
14161
14162        /**
14163         * A JSdoc TypeReference may be to a value, but resolve it as a type anyway.
14164         * Example: import('./b').ConstructorFunction
14165         */
14166        function getTypeFromJSDocValueReference(node: NodeWithTypeArguments, symbol: Symbol): Type | undefined {
14167            const links = getNodeLinks(node);
14168            if (!links.resolvedJSDocType) {
14169                const valueType = getTypeOfSymbol(symbol);
14170                let typeType = valueType;
14171                if (symbol.valueDeclaration) {
14172                    const isImportTypeWithQualifier = node.kind === SyntaxKind.ImportType && (node as ImportTypeNode).qualifier;
14173                    // valueType might not have a symbol, eg, {import('./b').STRING_LITERAL}
14174                    if (valueType.symbol && valueType.symbol !== symbol && isImportTypeWithQualifier) {
14175                        typeType = getTypeReferenceType(node, valueType.symbol);
14176                    }
14177                }
14178                links.resolvedJSDocType = typeType;
14179            }
14180            return links.resolvedJSDocType;
14181        }
14182
14183        function getSubstitutionType(baseType: Type, constraint: Type) {
14184            if (constraint.flags & TypeFlags.AnyOrUnknown || constraint === baseType ||
14185                !isGenericType(baseType) && !isGenericType(constraint)) {
14186                return baseType;
14187            }
14188            const id = `${getTypeId(baseType)}>${getTypeId(constraint)}`;
14189            const cached = substitutionTypes.get(id);
14190            if (cached) {
14191                return cached;
14192            }
14193            const result = createType(TypeFlags.Substitution) as SubstitutionType;
14194            result.baseType = baseType;
14195            result.constraint = constraint;
14196            substitutionTypes.set(id, result);
14197            return result;
14198        }
14199
14200        function getSubstitutionIntersection(substitutionType: SubstitutionType) {
14201            return getIntersectionType([substitutionType.constraint, substitutionType.baseType]);
14202        }
14203
14204        function isUnaryTupleTypeNode(node: TypeNode) {
14205            return node.kind === SyntaxKind.TupleType && (node as TupleTypeNode).elements.length === 1;
14206        }
14207
14208        function getImpliedConstraint(type: Type, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined {
14209            return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (checkNode as TupleTypeNode).elements[0], (extendsNode as TupleTypeNode).elements[0]) :
14210                getActualTypeVariable(getTypeFromTypeNode(checkNode)) === getActualTypeVariable(type) ? getTypeFromTypeNode(extendsNode) :
14211                undefined;
14212        }
14213
14214        function getConditionalFlowTypeOfType(type: Type, node: Node) {
14215            let constraints: Type[] | undefined;
14216            let covariant = true;
14217            while (node && !isStatement(node) && node.kind !== SyntaxKind.JSDoc) {
14218                const parent = node.parent;
14219                // only consider variance flipped by parameter locations - `keyof` types would usually be considered variance inverting, but
14220                // often get used in indexed accesses where they behave sortof invariantly, but our checking is lax
14221                if (parent.kind === SyntaxKind.Parameter) {
14222                    covariant = !covariant;
14223                }
14224                // Always substitute on type parameters, regardless of variance, since even
14225                // in contravariant positions, they may rely on substituted constraints to be valid
14226                if ((covariant || type.flags & TypeFlags.TypeVariable) && parent.kind === SyntaxKind.ConditionalType && node === (parent as ConditionalTypeNode).trueType) {
14227                    const constraint = getImpliedConstraint(type, (parent as ConditionalTypeNode).checkType, (parent as ConditionalTypeNode).extendsType);
14228                    if (constraint) {
14229                        constraints = append(constraints, constraint);
14230                    }
14231                }
14232                // Given a homomorphic mapped type { [K in keyof T]: XXX }, where T is constrained to an array or tuple type, in the
14233                // template type XXX, K has an added constraint of number | `${number}`.
14234                else if (type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType && node === (parent as MappedTypeNode).type) {
14235                    const mappedType = getTypeFromTypeNode(parent as TypeNode) as MappedType;
14236                    if (getTypeParameterFromMappedType(mappedType) === getActualTypeVariable(type)) {
14237                        const typeParameter = getHomomorphicTypeVariable(mappedType);
14238                        if (typeParameter) {
14239                            const constraint = getConstraintOfTypeParameter(typeParameter);
14240                            if (constraint && everyType(constraint, isArrayOrTupleType)) {
14241                                constraints = append(constraints, getUnionType([numberType, numericStringType]));
14242                            }
14243                        }
14244                    }
14245                }
14246                node = parent;
14247            }
14248            return constraints ? getSubstitutionType(type, getIntersectionType(constraints)) : type;
14249        }
14250
14251        function isJSDocTypeReference(node: Node): node is TypeReferenceNode {
14252            return !!(node.flags & NodeFlags.JSDoc) && (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ImportType);
14253        }
14254
14255        function checkNoTypeArguments(node: NodeWithTypeArguments, symbol?: Symbol) {
14256            if (node.typeArguments) {
14257                error(node, Diagnostics.Type_0_is_not_generic, symbol ? symbolToString(symbol) : (node as TypeReferenceNode).typeName ? declarationNameToString((node as TypeReferenceNode).typeName) : anon);
14258                return false;
14259            }
14260            return true;
14261        }
14262
14263        function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type | undefined {
14264            if (isIdentifier(node.typeName)) {
14265                const typeArgs = node.typeArguments;
14266                switch (node.typeName.escapedText) {
14267                    case "String":
14268                        checkNoTypeArguments(node);
14269                        return stringType;
14270                    case "Number":
14271                        checkNoTypeArguments(node);
14272                        return numberType;
14273                    case "Boolean":
14274                        checkNoTypeArguments(node);
14275                        return booleanType;
14276                    case "Void":
14277                        checkNoTypeArguments(node);
14278                        return voidType;
14279                    case "Undefined":
14280                        checkNoTypeArguments(node);
14281                        return undefinedType;
14282                    case "Null":
14283                        checkNoTypeArguments(node);
14284                        return nullType;
14285                    case "Function":
14286                    case "function":
14287                        checkNoTypeArguments(node);
14288                        return globalFunctionType;
14289                    case "array":
14290                        return (!typeArgs || !typeArgs.length) && !noImplicitAny ? anyArrayType : undefined;
14291                    case "promise":
14292                        return (!typeArgs || !typeArgs.length) && !noImplicitAny ? createPromiseType(anyType) : undefined;
14293                    case "Object":
14294                        if (typeArgs && typeArgs.length === 2) {
14295                            if (isJSDocIndexSignature(node)) {
14296                                const indexed = getTypeFromTypeNode(typeArgs[0]);
14297                                const target = getTypeFromTypeNode(typeArgs[1]);
14298                                const indexInfo = indexed === stringType || indexed === numberType ? [createIndexInfo(indexed, target, /*isReadonly*/ false)] : emptyArray;
14299                                return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexInfo);
14300                            }
14301                            return anyType;
14302                        }
14303                        checkNoTypeArguments(node);
14304                        return !noImplicitAny ? anyType : undefined;
14305                }
14306            }
14307        }
14308
14309        function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) {
14310            const type = getTypeFromTypeNode(node.type);
14311            return strictNullChecks ? getNullableType(type, TypeFlags.Null) : type;
14312        }
14313
14314        function getTypeFromTypeReference(node: TypeReferenceType): Type {
14315            const links = getNodeLinks(node);
14316            if (!links.resolvedType) {
14317                // handle LS queries on the `const` in `x as const` by resolving to the type of `x`
14318                if (isConstTypeReference(node) && isAssertionExpression(node.parent)) {
14319                    links.resolvedSymbol = unknownSymbol;
14320                    return links.resolvedType = checkExpressionCached(node.parent.expression);
14321                }
14322                let symbol: Symbol | undefined;
14323                let type: Type | undefined;
14324                const meaning = SymbolFlags.Type;
14325                if (isJSDocTypeReference(node)) {
14326                    type = getIntendedTypeFromJSDocTypeReference(node);
14327                    if (!type) {
14328                        symbol = resolveTypeReferenceName(node, meaning, /*ignoreErrors*/ true);
14329                        if (symbol === unknownSymbol) {
14330                            symbol = resolveTypeReferenceName(node, meaning | SymbolFlags.Value);
14331                        }
14332                        else {
14333                            resolveTypeReferenceName(node, meaning); // Resolve again to mark errors, if any
14334                        }
14335                        type = getTypeReferenceType(node, symbol);
14336                    }
14337                }
14338                if (!type) {
14339                    symbol = resolveTypeReferenceName(node, meaning);
14340                    type = getTypeReferenceType(node, symbol);
14341                }
14342                // Cache both the resolved symbol and the resolved type. The resolved symbol is needed when we check the
14343                // type reference in checkTypeReferenceNode.
14344                links.resolvedSymbol = symbol;
14345                links.resolvedType = type;
14346            }
14347            return links.resolvedType;
14348        }
14349
14350        function typeArgumentsFromTypeReferenceNode(node: NodeWithTypeArguments): Type[] | undefined {
14351            return map(node.typeArguments, getTypeFromTypeNode);
14352        }
14353
14354        function getTypeFromTypeQueryNode(node: TypeQueryNode): Type {
14355            const links = getNodeLinks(node);
14356            if (!links.resolvedType) {
14357                // TypeScript 1.0 spec (April 2014): 3.6.3
14358                // The expression is processed as an identifier expression (section 4.3)
14359                // or property access expression(section 4.10),
14360                // the widened type(section 3.9) of which becomes the result.
14361                const type = checkExpressionWithTypeArguments(node);
14362                links.resolvedType = getRegularTypeOfLiteralType(getWidenedType(type));
14363            }
14364            return links.resolvedType;
14365        }
14366
14367        function getTypeOfGlobalSymbol(symbol: Symbol | undefined, arity: number): ObjectType {
14368
14369            function getTypeDeclaration(symbol: Symbol): Declaration | undefined {
14370                const declarations = symbol.declarations;
14371                if (declarations) {
14372                    for (const declaration of declarations) {
14373                        switch (declaration.kind) {
14374                            case SyntaxKind.ClassDeclaration:
14375                            case SyntaxKind.InterfaceDeclaration:
14376                            case SyntaxKind.EnumDeclaration:
14377                                return declaration;
14378                        }
14379                    }
14380                }
14381            }
14382
14383            if (!symbol) {
14384                return arity ? emptyGenericType : emptyObjectType;
14385            }
14386            const type = getDeclaredTypeOfSymbol(symbol);
14387            if (!(type.flags & TypeFlags.Object)) {
14388                error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbolName(symbol));
14389                return arity ? emptyGenericType : emptyObjectType;
14390            }
14391            if (length((type as InterfaceType).typeParameters) !== arity) {
14392                error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbolName(symbol), arity);
14393                return arity ? emptyGenericType : emptyObjectType;
14394            }
14395            return type as ObjectType;
14396        }
14397
14398        function getGlobalValueSymbol(name: __String, reportErrors: boolean): Symbol | undefined {
14399            return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined);
14400        }
14401
14402        function getGlobalTypeSymbol(name: __String, reportErrors: boolean): Symbol | undefined {
14403            return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined);
14404        }
14405
14406        function getGlobalTypeAliasSymbol(name: __String, arity: number, reportErrors: boolean): Symbol | undefined {
14407            const symbol = getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined);
14408            if (symbol) {
14409                // Resolve the declared type of the symbol. This resolves type parameters for the type
14410                // alias so that we can check arity.
14411                getDeclaredTypeOfSymbol(symbol);
14412                if (length(getSymbolLinks(symbol).typeParameters) !== arity) {
14413                    const decl = symbol.declarations && find(symbol.declarations, isTypeAliasDeclaration);
14414                    error(decl, Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbolName(symbol), arity);
14415                    return undefined;
14416                }
14417            }
14418            return symbol;
14419        }
14420
14421        function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage | undefined): Symbol | undefined {
14422            // Don't track references for global symbols anyway, so value if `isReference` is arbitrary
14423            return resolveName(undefined, name, meaning, diagnostic, name, /*isUse*/ false, /*excludeGlobals*/ false, /*getSpellingSuggestions*/ false);
14424        }
14425
14426        function getGlobalType(name: __String, arity: 0, reportErrors: true): ObjectType;
14427        function getGlobalType(name: __String, arity: 0, reportErrors: boolean): ObjectType | undefined;
14428        function getGlobalType(name: __String, arity: number, reportErrors: true): GenericType;
14429        function getGlobalType(name: __String, arity: number, reportErrors: boolean): GenericType | undefined;
14430        function getGlobalType(name: __String, arity: number, reportErrors: boolean): ObjectType | undefined {
14431            const symbol = getGlobalTypeSymbol(name, reportErrors);
14432            return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined;
14433        }
14434
14435        function getGlobalTypedPropertyDescriptorType() {
14436            // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
14437            return deferredGlobalTypedPropertyDescriptorType ||= getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true) || emptyGenericType;
14438        }
14439
14440        function getGlobalTemplateStringsArrayType() {
14441            // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
14442            return deferredGlobalTemplateStringsArrayType ||= getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType;
14443        }
14444
14445        function getGlobalImportMetaType() {
14446            // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
14447            return deferredGlobalImportMetaType ||= getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType;
14448        }
14449
14450        function getGlobalImportMetaExpressionType() {
14451            if (!deferredGlobalImportMetaExpressionType) {
14452                // Create a synthetic type `ImportMetaExpression { meta: MetaProperty }`
14453                const symbol = createSymbol(SymbolFlags.None, "ImportMetaExpression" as __String);
14454                const importMetaType = getGlobalImportMetaType();
14455
14456                const metaPropertySymbol = createSymbol(SymbolFlags.Property, "meta" as __String, CheckFlags.Readonly);
14457                metaPropertySymbol.parent = symbol;
14458                metaPropertySymbol.type = importMetaType;
14459
14460                const members = createSymbolTable([metaPropertySymbol]);
14461                symbol.members = members;
14462
14463                deferredGlobalImportMetaExpressionType = createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray);
14464            }
14465            return deferredGlobalImportMetaExpressionType;
14466        }
14467
14468        function getGlobalImportCallOptionsType(reportErrors: boolean) {
14469            return (deferredGlobalImportCallOptionsType ||= getGlobalType("ImportCallOptions" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
14470        }
14471
14472        function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): Symbol | undefined {
14473            return deferredGlobalESSymbolConstructorSymbol ||= getGlobalValueSymbol("Symbol" as __String, reportErrors);
14474        }
14475
14476        function getGlobalESSymbolConstructorTypeSymbol(reportErrors: boolean): Symbol | undefined {
14477            return deferredGlobalESSymbolConstructorTypeSymbol ||= getGlobalTypeSymbol("SymbolConstructor" as __String, reportErrors);
14478        }
14479
14480        function getGlobalESSymbolType() {
14481            return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType;
14482        }
14483
14484        function getGlobalPromiseType(reportErrors: boolean) {
14485            return (deferredGlobalPromiseType ||= getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14486        }
14487
14488        function getGlobalPromiseLikeType(reportErrors: boolean) {
14489            return (deferredGlobalPromiseLikeType ||= getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14490        }
14491
14492        function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined {
14493            return deferredGlobalPromiseConstructorSymbol ||= getGlobalValueSymbol("Promise" as __String, reportErrors);
14494        }
14495
14496        function getGlobalPromiseConstructorLikeType(reportErrors: boolean) {
14497            return (deferredGlobalPromiseConstructorLikeType ||= getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
14498        }
14499
14500        function getGlobalAsyncIterableType(reportErrors: boolean) {
14501            return (deferredGlobalAsyncIterableType ||= getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14502        }
14503
14504        function getGlobalAsyncIteratorType(reportErrors: boolean) {
14505            return (deferredGlobalAsyncIteratorType ||= getGlobalType("AsyncIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
14506        }
14507
14508        function getGlobalAsyncIterableIteratorType(reportErrors: boolean) {
14509            return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14510        }
14511
14512        function getGlobalAsyncGeneratorType(reportErrors: boolean) {
14513            return (deferredGlobalAsyncGeneratorType ||= getGlobalType("AsyncGenerator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
14514        }
14515
14516        function getGlobalIterableType(reportErrors: boolean) {
14517            return (deferredGlobalIterableType ||= getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14518        }
14519
14520        function getGlobalIteratorType(reportErrors: boolean) {
14521            return (deferredGlobalIteratorType ||= getGlobalType("Iterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
14522        }
14523
14524        function getGlobalIterableIteratorType(reportErrors: boolean) {
14525            return (deferredGlobalIterableIteratorType ||= getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14526        }
14527
14528        function getGlobalGeneratorType(reportErrors: boolean) {
14529            return (deferredGlobalGeneratorType ||= getGlobalType("Generator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
14530        }
14531
14532        function getGlobalIteratorYieldResultType(reportErrors: boolean) {
14533            return (deferredGlobalIteratorYieldResultType ||= getGlobalType("IteratorYieldResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14534        }
14535
14536        function getGlobalIteratorReturnResultType(reportErrors: boolean) {
14537            return (deferredGlobalIteratorReturnResultType ||= getGlobalType("IteratorReturnResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
14538        }
14539
14540        function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType | undefined {
14541            const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined);
14542            return symbol && getTypeOfGlobalSymbol(symbol, arity) as GenericType;
14543        }
14544
14545        function getGlobalExtractSymbol(): Symbol | undefined {
14546            // We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times
14547            deferredGlobalExtractSymbol ||= getGlobalTypeAliasSymbol("Extract" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
14548            return deferredGlobalExtractSymbol === unknownSymbol ? undefined : deferredGlobalExtractSymbol;
14549        }
14550
14551        function getGlobalOmitSymbol(): Symbol | undefined {
14552            // We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times
14553            deferredGlobalOmitSymbol ||= getGlobalTypeAliasSymbol("Omit" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
14554            return deferredGlobalOmitSymbol === unknownSymbol ? undefined : deferredGlobalOmitSymbol;
14555        }
14556
14557        function getGlobalAwaitedSymbol(reportErrors: boolean): Symbol | undefined {
14558            // Only cache `unknownSymbol` if we are reporting errors so that we don't report the error more than once.
14559            deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined);
14560            return deferredGlobalAwaitedSymbol === unknownSymbol ? undefined : deferredGlobalAwaitedSymbol;
14561        }
14562
14563        function getGlobalBigIntType() {
14564            return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType;
14565        }
14566
14567        function getGlobalNaNSymbol(): Symbol | undefined {
14568            return (deferredGlobalNaNSymbol ||= getGlobalValueSymbol("NaN" as __String, /*reportErrors*/ false));
14569        }
14570
14571        function getGlobalRecordSymbol(): Symbol | undefined {
14572            deferredGlobalRecordSymbol ||= getGlobalTypeAliasSymbol("Record" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
14573            return deferredGlobalRecordSymbol === unknownSymbol ? undefined : deferredGlobalRecordSymbol;
14574        }
14575
14576        /**
14577         * Instantiates a global type that is generic with some element type, and returns that instantiation.
14578         */
14579        function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: readonly Type[]): ObjectType {
14580            return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType;
14581        }
14582
14583        function createTypedPropertyDescriptorType(propertyType: Type): Type {
14584            return createTypeFromGenericGlobalType(getGlobalTypedPropertyDescriptorType(), [propertyType]);
14585        }
14586
14587        function createIterableType(iteratedType: Type): Type {
14588            return createTypeFromGenericGlobalType(getGlobalIterableType(/*reportErrors*/ true), [iteratedType]);
14589        }
14590
14591        function createArrayType(elementType: Type, readonly?: boolean): ObjectType {
14592            return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]);
14593        }
14594
14595        function getTupleElementFlags(node: TypeNode) {
14596            switch (node.kind) {
14597                case SyntaxKind.OptionalType:
14598                    return ElementFlags.Optional;
14599                case SyntaxKind.RestType:
14600                    return getRestTypeElementFlags(node as RestTypeNode);
14601                case SyntaxKind.NamedTupleMember:
14602                    return (node as NamedTupleMember).questionToken ? ElementFlags.Optional :
14603                        (node as NamedTupleMember).dotDotDotToken ? getRestTypeElementFlags(node as NamedTupleMember) :
14604                        ElementFlags.Required;
14605                default:
14606                    return ElementFlags.Required;
14607            }
14608        }
14609
14610        function getRestTypeElementFlags(node: RestTypeNode | NamedTupleMember) {
14611            return getArrayElementTypeNode(node.type) ? ElementFlags.Rest : ElementFlags.Variadic;
14612        }
14613
14614        function getArrayOrTupleTargetType(node: ArrayTypeNode | TupleTypeNode): GenericType {
14615            const readonly = isReadonlyTypeOperator(node.parent);
14616            const elementType = getArrayElementTypeNode(node);
14617            if (elementType) {
14618                return readonly ? globalReadonlyArrayType : globalArrayType;
14619            }
14620            const elementFlags = map((node as TupleTypeNode).elements, getTupleElementFlags);
14621            const missingName = some((node as TupleTypeNode).elements, e => e.kind !== SyntaxKind.NamedTupleMember);
14622            return getTupleTargetType(elementFlags, readonly, /*associatedNames*/ missingName ? undefined : (node as TupleTypeNode).elements as readonly NamedTupleMember[]);
14623        }
14624
14625        // Return true if the given type reference node is directly aliased or if it needs to be deferred
14626        // because it is possibly contained in a circular chain of eagerly resolved types.
14627        function isDeferredTypeReferenceNode(node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, hasDefaultTypeArguments?: boolean) {
14628            return !!getAliasSymbolForTypeNode(node) || isResolvedByTypeAlias(node) && (
14629                node.kind === SyntaxKind.ArrayType ? mayResolveTypeAlias(node.elementType) :
14630                node.kind === SyntaxKind.TupleType ? some(node.elements, mayResolveTypeAlias) :
14631                hasDefaultTypeArguments || some(node.typeArguments, mayResolveTypeAlias));
14632        }
14633
14634        // Return true when the given node is transitively contained in type constructs that eagerly
14635        // resolve their constituent types. We include SyntaxKind.TypeReference because type arguments
14636        // of type aliases are eagerly resolved.
14637        function isResolvedByTypeAlias(node: Node): boolean {
14638            const parent = node.parent;
14639            switch (parent.kind) {
14640                case SyntaxKind.ParenthesizedType:
14641                case SyntaxKind.NamedTupleMember:
14642                case SyntaxKind.TypeReference:
14643                case SyntaxKind.UnionType:
14644                case SyntaxKind.IntersectionType:
14645                case SyntaxKind.IndexedAccessType:
14646                case SyntaxKind.ConditionalType:
14647                case SyntaxKind.TypeOperator:
14648                case SyntaxKind.ArrayType:
14649                case SyntaxKind.TupleType:
14650                    return isResolvedByTypeAlias(parent);
14651                case SyntaxKind.TypeAliasDeclaration:
14652                    return true;
14653            }
14654            return false;
14655        }
14656
14657        // Return true if resolving the given node (i.e. getTypeFromTypeNode) possibly causes resolution
14658        // of a type alias.
14659        function mayResolveTypeAlias(node: Node): boolean {
14660            switch (node.kind) {
14661                case SyntaxKind.TypeReference:
14662                    return isJSDocTypeReference(node) || !!(resolveTypeReferenceName(node as TypeReferenceNode, SymbolFlags.Type).flags & SymbolFlags.TypeAlias);
14663                case SyntaxKind.TypeQuery:
14664                    return true;
14665                case SyntaxKind.TypeOperator:
14666                    return (node as TypeOperatorNode).operator !== SyntaxKind.UniqueKeyword && mayResolveTypeAlias((node as TypeOperatorNode).type);
14667                case SyntaxKind.ParenthesizedType:
14668                case SyntaxKind.OptionalType:
14669                case SyntaxKind.NamedTupleMember:
14670                case SyntaxKind.JSDocOptionalType:
14671                case SyntaxKind.JSDocNullableType:
14672                case SyntaxKind.JSDocNonNullableType:
14673                case SyntaxKind.JSDocTypeExpression:
14674                    return mayResolveTypeAlias((node as ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode | NamedTupleMember).type);
14675                case SyntaxKind.RestType:
14676                    return (node as RestTypeNode).type.kind !== SyntaxKind.ArrayType || mayResolveTypeAlias(((node as RestTypeNode).type as ArrayTypeNode).elementType);
14677                case SyntaxKind.UnionType:
14678                case SyntaxKind.IntersectionType:
14679                    return some((node as UnionOrIntersectionTypeNode).types, mayResolveTypeAlias);
14680                case SyntaxKind.IndexedAccessType:
14681                    return mayResolveTypeAlias((node as IndexedAccessTypeNode).objectType) || mayResolveTypeAlias((node as IndexedAccessTypeNode).indexType);
14682                case SyntaxKind.ConditionalType:
14683                    return mayResolveTypeAlias((node as ConditionalTypeNode).checkType) || mayResolveTypeAlias((node as ConditionalTypeNode).extendsType) ||
14684                        mayResolveTypeAlias((node as ConditionalTypeNode).trueType) || mayResolveTypeAlias((node as ConditionalTypeNode).falseType);
14685            }
14686            return false;
14687        }
14688
14689        function getTypeFromArrayOrTupleTypeNode(node: ArrayTypeNode | TupleTypeNode): Type {
14690            const links = getNodeLinks(node);
14691            if (!links.resolvedType) {
14692                const target = getArrayOrTupleTargetType(node);
14693                if (target === emptyGenericType) {
14694                    links.resolvedType = emptyObjectType;
14695                }
14696                else if (!(node.kind === SyntaxKind.TupleType && some(node.elements, e => !!(getTupleElementFlags(e) & ElementFlags.Variadic))) && isDeferredTypeReferenceNode(node)) {
14697                    links.resolvedType = node.kind === SyntaxKind.TupleType && node.elements.length === 0 ? target :
14698                        createDeferredTypeReference(target, node, /*mapper*/ undefined);
14699                }
14700                else {
14701                    const elementTypes = node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : map(node.elements, getTypeFromTypeNode);
14702                    links.resolvedType = createNormalizedTypeReference(target, elementTypes);
14703                }
14704            }
14705            return links.resolvedType;
14706        }
14707
14708        function isReadonlyTypeOperator(node: Node) {
14709            return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword;
14710        }
14711
14712        function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]) {
14713            const tupleTarget = getTupleTargetType(elementFlags || map(elementTypes, _ => ElementFlags.Required), readonly, namedMemberDeclarations);
14714            return tupleTarget === emptyGenericType ? emptyObjectType :
14715                elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) :
14716                tupleTarget;
14717        }
14718
14719        function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]): GenericType {
14720            if (elementFlags.length === 1 && elementFlags[0] & ElementFlags.Rest) {
14721                // [...X[]] is equivalent to just X[]
14722                return readonly ? globalReadonlyArrayType : globalArrayType;
14723            }
14724            const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() +
14725                (readonly ? "R" : "") +
14726                (namedMemberDeclarations && namedMemberDeclarations.length ? "," + map(namedMemberDeclarations, getNodeId).join(",") : "");
14727            let type = tupleTypes.get(key);
14728            if (!type) {
14729                tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations));
14730            }
14731            return type;
14732        }
14733
14734        // We represent tuple types as type references to synthesized generic interface types created by
14735        // this function. The types are of the form:
14736        //
14737        //   interface Tuple<T0, T1, T2, ...> extends Array<T0 | T1 | T2 | ...> { 0: T0, 1: T1, 2: T2, ... }
14738        //
14739        // Note that the generic type created by this function has no symbol associated with it. The same
14740        // is true for each of the synthesized type parameters.
14741        function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType {
14742            const arity = elementFlags.length;
14743            const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic)));
14744            let typeParameters: TypeParameter[] | undefined;
14745            const properties: Symbol[] = [];
14746            let combinedFlags: ElementFlags = 0;
14747            if (arity) {
14748                typeParameters = new Array(arity);
14749                for (let i = 0; i < arity; i++) {
14750                    const typeParameter = typeParameters[i] = createTypeParameter();
14751                    const flags = elementFlags[i];
14752                    combinedFlags |= flags;
14753                    if (!(combinedFlags & ElementFlags.Variable)) {
14754                        const property = createSymbol(SymbolFlags.Property | (flags & ElementFlags.Optional ? SymbolFlags.Optional : 0),
14755                            "" + i as __String, readonly ? CheckFlags.Readonly : 0);
14756                        property.tupleLabelDeclaration = namedMemberDeclarations?.[i];
14757                        property.type = typeParameter;
14758                        properties.push(property);
14759                    }
14760                }
14761            }
14762            const fixedLength = properties.length;
14763            const lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String, readonly ? CheckFlags.Readonly : 0);
14764            if (combinedFlags & ElementFlags.Variable) {
14765                lengthSymbol.type = numberType;
14766            }
14767            else {
14768                const literalTypes = [];
14769                for (let i = minLength; i <= arity; i++) literalTypes.push(getNumberLiteralType(i));
14770                lengthSymbol.type = getUnionType(literalTypes);
14771            }
14772            properties.push(lengthSymbol);
14773            const type = createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference) as TupleType & InterfaceTypeWithDeclaredMembers;
14774            type.typeParameters = typeParameters;
14775            type.outerTypeParameters = undefined;
14776            type.localTypeParameters = typeParameters;
14777            type.instantiations = new Map<string, TypeReference>();
14778            type.instantiations.set(getTypeListId(type.typeParameters), type as GenericType);
14779            type.target = type as GenericType;
14780            type.resolvedTypeArguments = type.typeParameters;
14781            type.thisType = createTypeParameter();
14782            type.thisType.isThisType = true;
14783            type.thisType.constraint = type;
14784            type.declaredProperties = properties;
14785            type.declaredCallSignatures = emptyArray;
14786            type.declaredConstructSignatures = emptyArray;
14787            type.declaredIndexInfos = emptyArray;
14788            type.elementFlags = elementFlags;
14789            type.minLength = minLength;
14790            type.fixedLength = fixedLength;
14791            type.hasRestElement = !!(combinedFlags & ElementFlags.Variable);
14792            type.combinedFlags = combinedFlags;
14793            type.readonly = readonly;
14794            type.labeledElementDeclarations = namedMemberDeclarations;
14795            return type;
14796        }
14797
14798        function createNormalizedTypeReference(target: GenericType, typeArguments: readonly Type[] | undefined) {
14799            return target.objectFlags & ObjectFlags.Tuple ? createNormalizedTupleType(target as TupleType, typeArguments!) : createTypeReference(target, typeArguments);
14800        }
14801
14802        function createNormalizedTupleType(target: TupleType, elementTypes: readonly Type[]): Type {
14803            if (!(target.combinedFlags & ElementFlags.NonRequired)) {
14804                // No need to normalize when we only have regular required elements
14805                return createTypeReference(target, elementTypes);
14806            }
14807            if (target.combinedFlags & ElementFlags.Variadic) {
14808                // Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z]
14809                const unionIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union)));
14810                if (unionIndex >= 0) {
14811                    return checkCrossProductUnion(map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType)) ?
14812                        mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))) :
14813                        errorType;
14814                }
14815            }
14816            // We have optional, rest, or variadic elements that may need normalizing. Normalization ensures that all variadic
14817            // elements are generic and that the tuple type has one of the following layouts, disregarding variadic elements:
14818            // (1) Zero or more required elements, followed by zero or more optional elements, followed by zero or one rest element.
14819            // (2) Zero or more required elements, followed by a rest element, followed by zero or more required elements.
14820            // In either layout, zero or more generic variadic elements may be present at any location.
14821            const expandedTypes: Type[] = [];
14822            const expandedFlags: ElementFlags[] = [];
14823            let expandedDeclarations: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
14824            let lastRequiredIndex = -1;
14825            let firstRestIndex = -1;
14826            let lastOptionalOrRestIndex = -1;
14827            for (let i = 0; i < elementTypes.length; i++) {
14828                const type = elementTypes[i];
14829                const flags = target.elementFlags[i];
14830                if (flags & ElementFlags.Variadic) {
14831                    if (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type)) {
14832                        // Generic variadic elements stay as they are.
14833                        addElement(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]);
14834                    }
14835                    else if (isTupleType(type)) {
14836                        const elements = getTypeArguments(type);
14837                        if (elements.length + expandedTypes.length >= 10_000) {
14838                            error(currentNode, isPartOfTypeNode(currentNode!)
14839                                ? Diagnostics.Type_produces_a_tuple_type_that_is_too_large_to_represent
14840                                : Diagnostics.Expression_produces_a_tuple_type_that_is_too_large_to_represent);
14841                            return errorType;
14842                        }
14843                        // Spread variadic elements with tuple types into the resulting tuple.
14844                        forEach(elements, (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n]));
14845                    }
14846                    else {
14847                        // Treat everything else as an array type and create a rest element.
14848                        addElement(isArrayLikeType(type) && getIndexTypeOfType(type, numberType) || errorType, ElementFlags.Rest, target.labeledElementDeclarations?.[i]);
14849                    }
14850                }
14851                else {
14852                    // Copy other element kinds with no change.
14853                    addElement(type, flags, target.labeledElementDeclarations?.[i]);
14854                }
14855            }
14856            // Turn optional elements preceding the last required element into required elements
14857            for (let i = 0; i < lastRequiredIndex; i++) {
14858                if (expandedFlags[i] & ElementFlags.Optional) expandedFlags[i] = ElementFlags.Required;
14859            }
14860            if (firstRestIndex >= 0 && firstRestIndex < lastOptionalOrRestIndex) {
14861                // Turn elements between first rest and last optional/rest into a single rest element
14862                expandedTypes[firstRestIndex] = getUnionType(sameMap(expandedTypes.slice(firstRestIndex, lastOptionalOrRestIndex + 1),
14863                    (t, i) => expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t));
14864                expandedTypes.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
14865                expandedFlags.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
14866                expandedDeclarations?.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex);
14867            }
14868            const tupleTarget = getTupleTargetType(expandedFlags, target.readonly, expandedDeclarations);
14869            return tupleTarget === emptyGenericType ? emptyObjectType :
14870                expandedFlags.length ? createTypeReference(tupleTarget, expandedTypes) :
14871                tupleTarget;
14872
14873            function addElement(type: Type, flags: ElementFlags, declaration: NamedTupleMember | ParameterDeclaration | undefined) {
14874                if (flags & ElementFlags.Required) {
14875                    lastRequiredIndex = expandedFlags.length;
14876                }
14877                if (flags & ElementFlags.Rest && firstRestIndex < 0) {
14878                    firstRestIndex = expandedFlags.length;
14879                }
14880                if (flags & (ElementFlags.Optional | ElementFlags.Rest)) {
14881                    lastOptionalOrRestIndex = expandedFlags.length;
14882                }
14883                expandedTypes.push(flags & ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type);
14884                expandedFlags.push(flags);
14885                if (expandedDeclarations && declaration) {
14886                    expandedDeclarations.push(declaration);
14887                }
14888                else {
14889                    expandedDeclarations = undefined;
14890                }
14891            }
14892        }
14893
14894        function sliceTupleType(type: TupleTypeReference, index: number, endSkipCount = 0) {
14895            const target = type.target;
14896            const endIndex = getTypeReferenceArity(type) - endSkipCount;
14897            return index > target.fixedLength ? getRestArrayTypeOfTupleType(type) || createTupleType(emptyArray) :
14898                createTupleType(getTypeArguments(type).slice(index, endIndex), target.elementFlags.slice(index, endIndex),
14899                    /*readonly*/ false, target.labeledElementDeclarations && target.labeledElementDeclarations.slice(index, endIndex));
14900        }
14901
14902        function getKnownKeysOfTupleType(type: TupleTypeReference) {
14903            return getUnionType(append(arrayOf(type.target.fixedLength, i => getStringLiteralType("" + i)),
14904                getIndexType(type.target.readonly ? globalReadonlyArrayType : globalArrayType)));
14905        }
14906
14907        // Return count of starting consecutive tuple elements of the given kind(s)
14908        function getStartElementCount(type: TupleType, flags: ElementFlags) {
14909            const index = findIndex(type.elementFlags, f => !(f & flags));
14910            return index >= 0 ? index : type.elementFlags.length;
14911        }
14912
14913        // Return count of ending consecutive tuple elements of the given kind(s)
14914        function getEndElementCount(type: TupleType, flags: ElementFlags) {
14915            return type.elementFlags.length - findLastIndex(type.elementFlags, f => !(f & flags)) - 1;
14916        }
14917
14918        function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type {
14919            return addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true);
14920        }
14921
14922        function getTypeId(type: Type): TypeId {
14923            return type.id;
14924        }
14925
14926        function containsType(types: readonly Type[], type: Type): boolean {
14927            return binarySearch(types, type, getTypeId, compareValues) >= 0;
14928        }
14929
14930        function insertType(types: Type[], type: Type): boolean {
14931            const index = binarySearch(types, type, getTypeId, compareValues);
14932            if (index < 0) {
14933                types.splice(~index, 0, type);
14934                return true;
14935            }
14936            return false;
14937        }
14938
14939        function addTypeToUnion(typeSet: Type[], includes: TypeFlags, type: Type) {
14940            const flags = type.flags;
14941            if (flags & TypeFlags.Union) {
14942                return addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types);
14943            }
14944            // We ignore 'never' types in unions
14945            if (!(flags & TypeFlags.Never)) {
14946                includes |= flags & TypeFlags.IncludesMask;
14947                if (flags & TypeFlags.Instantiable) includes |= TypeFlags.IncludesInstantiable;
14948                if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
14949                if (!strictNullChecks && flags & TypeFlags.Nullable) {
14950                    if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType;
14951                }
14952                else {
14953                    const len = typeSet.length;
14954                    const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues);
14955                    if (index < 0) {
14956                        typeSet.splice(~index, 0, type);
14957                    }
14958                }
14959            }
14960            return includes;
14961        }
14962
14963        // Add the given types to the given type set. Order is preserved, duplicates are removed,
14964        // and nested types of the given kind are flattened into the set.
14965        function addTypesToUnion(typeSet: Type[], includes: TypeFlags, types: readonly Type[]): TypeFlags {
14966            for (const type of types) {
14967                includes = addTypeToUnion(typeSet, includes, type);
14968            }
14969            return includes;
14970        }
14971
14972        function removeSubtypes(types: Type[], hasObjectTypes: boolean): Type[] | undefined {
14973            // [] and [T] immediately reduce to [] and [T] respectively
14974            if (types.length < 2) {
14975                return types;
14976            }
14977
14978            const id = getTypeListId(types);
14979            const match = subtypeReductionCache.get(id);
14980            if (match) {
14981                return match;
14982            }
14983
14984            // We assume that redundant primitive types have already been removed from the types array and that there
14985            // are no any and unknown types in the array. Thus, the only possible supertypes for primitive types are empty
14986            // object types, and if none of those are present we can exclude primitive types from the subtype check.
14987            const hasEmptyObject = hasObjectTypes && some(types, t => !!(t.flags & TypeFlags.Object) && !isGenericMappedType(t) && isEmptyResolvedType(resolveStructuredTypeMembers(t as ObjectType)));
14988            const len = types.length;
14989            let i = len;
14990            let count = 0;
14991            while (i > 0) {
14992                i--;
14993                const source = types[i];
14994                if (hasEmptyObject || source.flags & TypeFlags.StructuredOrInstantiable) {
14995                    // Find the first property with a unit type, if any. When constituents have a property by the same name
14996                    // but of a different unit type, we can quickly disqualify them from subtype checks. This helps subtype
14997                    // reduction of large discriminated union types.
14998                    const keyProperty = source.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive) ?
14999                        find(getPropertiesOfType(source), p => isUnitType(getTypeOfSymbol(p))) :
15000                        undefined;
15001                    const keyPropertyType = keyProperty && getRegularTypeOfLiteralType(getTypeOfSymbol(keyProperty));
15002                    for (const target of types) {
15003                        if (source !== target) {
15004                            if (count === 100000) {
15005                                // After 100000 subtype checks we estimate the remaining amount of work by assuming the
15006                                // same ratio of checks per element. If the estimated number of remaining type checks is
15007                                // greater than 1M we deem the union type too complex to represent. This for example
15008                                // caps union types at 1000 unique object types.
15009                                const estimatedCount = (count / (len - i)) * len;
15010                                if (estimatedCount > 1000000) {
15011                                    tracing?.instant(tracing.Phase.CheckTypes, "removeSubtypes_DepthLimit", { typeIds: types.map(t => t.id) });
15012                                    error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
15013                                    return undefined;
15014                                }
15015                            }
15016                            count++;
15017                            if (keyProperty && target.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) {
15018                                const t = getTypeOfPropertyOfType(target, keyProperty.escapedName);
15019                                if (t && isUnitType(t) && getRegularTypeOfLiteralType(t) !== keyPropertyType) {
15020                                    continue;
15021                                }
15022                            }
15023                            if (isTypeRelatedTo(source, target, strictSubtypeRelation) && (
15024                                !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) ||
15025                                !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) ||
15026                                isTypeDerivedFrom(source, target))) {
15027                                orderedRemoveItemAt(types, i);
15028                                break;
15029                            }
15030                        }
15031                    }
15032                }
15033            }
15034            subtypeReductionCache.set(id, types);
15035            return types;
15036        }
15037
15038        function removeRedundantLiteralTypes(types: Type[], includes: TypeFlags, reduceVoidUndefined: boolean) {
15039            let i = types.length;
15040            while (i > 0) {
15041                i--;
15042                const t = types[i];
15043                const flags = t.flags;
15044                const remove =
15045                    flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && includes & TypeFlags.String ||
15046                    flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number ||
15047                    flags & TypeFlags.BigIntLiteral && includes & TypeFlags.BigInt ||
15048                    flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol ||
15049                    reduceVoidUndefined && flags & TypeFlags.Undefined && includes & TypeFlags.Void ||
15050                    isFreshLiteralType(t) && containsType(types, (t as LiteralType).regularType);
15051                if (remove) {
15052                    orderedRemoveItemAt(types, i);
15053                }
15054            }
15055        }
15056
15057        function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]) {
15058            const templates = filter(types, isPatternLiteralType) as TemplateLiteralType[];
15059            if (templates.length) {
15060                let i = types.length;
15061                while (i > 0) {
15062                    i--;
15063                    const t = types[i];
15064                    if (t.flags & TypeFlags.StringLiteral && some(templates, template => isTypeMatchedByTemplateLiteralType(t, template))) {
15065                        orderedRemoveItemAt(types, i);
15066                    }
15067                }
15068            }
15069        }
15070
15071        function isNamedUnionType(type: Type) {
15072            return !!(type.flags & TypeFlags.Union && (type.aliasSymbol || (type as UnionType).origin));
15073        }
15074
15075        function addNamedUnions(namedUnions: Type[], types: readonly Type[]) {
15076            for (const t of types) {
15077                if (t.flags & TypeFlags.Union) {
15078                    const origin = (t as UnionType).origin;
15079                    if (t.aliasSymbol || origin && !(origin.flags & TypeFlags.Union)) {
15080                        pushIfUnique(namedUnions, t);
15081                    }
15082                    else if (origin && origin.flags & TypeFlags.Union) {
15083                        addNamedUnions(namedUnions, (origin as UnionType).types);
15084                    }
15085                }
15086            }
15087        }
15088
15089        function createOriginUnionOrIntersectionType(flags: TypeFlags, types: Type[]) {
15090            const result = createOriginType(flags) as UnionOrIntersectionType;
15091            result.types = types;
15092            return result;
15093        }
15094
15095        // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction
15096        // flag is specified we also reduce the constituent type set to only include types that aren't subtypes
15097        // of other types. Subtype reduction is expensive for large union types and is possible only when union
15098        // types are known not to circularly reference themselves (as is the case with union types created by
15099        // expression constructs such as array literals and the || and ?: operators). Named types can
15100        // circularly reference themselves and therefore cannot be subtype reduced during their declaration.
15101        // For example, "type Item = string | (() => Item" is a named type that circularly references itself.
15102        function getUnionType(types: readonly Type[], unionReduction: UnionReduction = UnionReduction.Literal, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type {
15103            if (types.length === 0) {
15104                return neverType;
15105            }
15106            if (types.length === 1) {
15107                return types[0];
15108            }
15109            let typeSet: Type[] | undefined = [];
15110            const includes = addTypesToUnion(typeSet, 0, types);
15111            if (unionReduction !== UnionReduction.None) {
15112                if (includes & TypeFlags.AnyOrUnknown) {
15113                    return includes & TypeFlags.Any ?
15114                        includes & TypeFlags.IncludesWildcard ? wildcardType : anyType :
15115                        includes & TypeFlags.Null || containsType(typeSet, unknownType) ? unknownType : nonNullUnknownType;
15116                }
15117                if (exactOptionalPropertyTypes && includes & TypeFlags.Undefined) {
15118                    const missingIndex = binarySearch(typeSet, missingType, getTypeId, compareValues);
15119                    if (missingIndex >= 0 && containsType(typeSet, undefinedType)) {
15120                        orderedRemoveItemAt(typeSet, missingIndex);
15121                    }
15122                }
15123                if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) {
15124                    removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype));
15125                }
15126                if (includes & TypeFlags.StringLiteral && includes & TypeFlags.TemplateLiteral) {
15127                    removeStringLiteralsMatchedByTemplateLiterals(typeSet);
15128                }
15129                if (unionReduction === UnionReduction.Subtype) {
15130                    typeSet = removeSubtypes(typeSet, !!(includes & TypeFlags.Object));
15131                    if (!typeSet) {
15132                        return errorType;
15133                    }
15134                }
15135                if (typeSet.length === 0) {
15136                    return includes & TypeFlags.Null ? includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType :
15137                        includes & TypeFlags.Undefined ? includes & TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType :
15138                        neverType;
15139                }
15140            }
15141            if (!origin && includes & TypeFlags.Union) {
15142                const namedUnions: Type[] = [];
15143                addNamedUnions(namedUnions, types);
15144                const reducedTypes: Type[] = [];
15145                for (const t of typeSet) {
15146                    if (!some(namedUnions, union => containsType((union as UnionType).types, t))) {
15147                        reducedTypes.push(t);
15148                    }
15149                }
15150                if (!aliasSymbol && namedUnions.length === 1 && reducedTypes.length === 0) {
15151                    return namedUnions[0];
15152                }
15153                // We create a denormalized origin type only when the union was created from one or more named unions
15154                // (unions with alias symbols or origins) and when there is no overlap between those named unions.
15155                const namedTypesCount = reduceLeft(namedUnions, (sum, union) => sum + (union as UnionType).types.length, 0);
15156                if (namedTypesCount + reducedTypes.length === typeSet.length) {
15157                    for (const t of namedUnions) {
15158                        insertType(reducedTypes, t);
15159                    }
15160                    origin = createOriginUnionOrIntersectionType(TypeFlags.Union, reducedTypes);
15161                }
15162            }
15163            const objectFlags = (includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion) |
15164                (includes & TypeFlags.Intersection ? ObjectFlags.ContainsIntersections : 0);
15165            return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin);
15166        }
15167
15168        function getUnionOrIntersectionTypePredicate(signatures: readonly Signature[], kind: TypeFlags | undefined): TypePredicate | undefined {
15169            let first: TypePredicate | undefined;
15170            const types: Type[] = [];
15171            for (const sig of signatures) {
15172                const pred = getTypePredicateOfSignature(sig);
15173                if (!pred || pred.kind === TypePredicateKind.AssertsThis || pred.kind === TypePredicateKind.AssertsIdentifier) {
15174                    if (kind !== TypeFlags.Intersection) {
15175                        continue;
15176                    }
15177                    else {
15178                        return; // intersections demand all members be type predicates for the result to have a predicate
15179                    }
15180                }
15181
15182                if (first) {
15183                    if (!typePredicateKindsMatch(first, pred)) {
15184                        // No common type predicate.
15185                        return undefined;
15186                    }
15187                }
15188                else {
15189                    first = pred;
15190                }
15191                types.push(pred.type);
15192            }
15193            if (!first) {
15194                // No signatures had a type predicate.
15195                return undefined;
15196            }
15197            const compositeType = getUnionOrIntersectionType(types, kind);
15198            return createTypePredicate(first.kind, first.parameterName, first.parameterIndex, compositeType);
15199        }
15200
15201        function typePredicateKindsMatch(a: TypePredicate, b: TypePredicate): boolean {
15202            return a.kind === b.kind && a.parameterIndex === b.parameterIndex;
15203        }
15204
15205        // This function assumes the constituent type list is sorted and deduplicated.
15206        function getUnionTypeFromSortedList(types: Type[], objectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type {
15207            if (types.length === 0) {
15208                return neverType;
15209            }
15210            if (types.length === 1) {
15211                return types[0];
15212            }
15213            const typeKey = !origin ? getTypeListId(types) :
15214                origin.flags & TypeFlags.Union ? `|${getTypeListId((origin as UnionType).types)}` :
15215                origin.flags & TypeFlags.Intersection ? `&${getTypeListId((origin as IntersectionType).types)}` :
15216                `#${(origin as IndexType).type.id}|${getTypeListId(types)}`; // origin type id alone is insufficient, as `keyof x` may resolve to multiple WIP values while `x` is still resolving
15217            const id = typeKey + getAliasId(aliasSymbol, aliasTypeArguments);
15218            let type = unionTypes.get(id);
15219            if (!type) {
15220                type = createType(TypeFlags.Union) as UnionType;
15221                type.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
15222                type.types = types;
15223                type.origin = origin;
15224                type.aliasSymbol = aliasSymbol;
15225                type.aliasTypeArguments = aliasTypeArguments;
15226                if (types.length === 2 && types[0].flags & TypeFlags.BooleanLiteral && types[1].flags & TypeFlags.BooleanLiteral) {
15227                    type.flags |= TypeFlags.Boolean;
15228                    (type as UnionType & IntrinsicType).intrinsicName = "boolean";
15229                }
15230                unionTypes.set(id, type);
15231            }
15232            return type;
15233        }
15234
15235        function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
15236            const links = getNodeLinks(node);
15237            if (!links.resolvedType) {
15238                const aliasSymbol = getAliasSymbolForTypeNode(node);
15239                links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), UnionReduction.Literal,
15240                    aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol));
15241            }
15242            return links.resolvedType;
15243        }
15244
15245        function addTypeToIntersection(typeSet: ESMap<string, Type>, includes: TypeFlags, type: Type) {
15246            const flags = type.flags;
15247            if (flags & TypeFlags.Intersection) {
15248                return addTypesToIntersection(typeSet, includes, (type as IntersectionType).types);
15249            }
15250            if (isEmptyAnonymousObjectType(type)) {
15251                if (!(includes & TypeFlags.IncludesEmptyObject)) {
15252                    includes |= TypeFlags.IncludesEmptyObject;
15253                    typeSet.set(type.id.toString(), type);
15254                }
15255            }
15256            else {
15257                if (flags & TypeFlags.AnyOrUnknown) {
15258                    if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
15259                }
15260                else if (strictNullChecks || !(flags & TypeFlags.Nullable)) {
15261                    if (exactOptionalPropertyTypes && type === missingType) {
15262                        includes |= TypeFlags.IncludesMissingType;
15263                        type = undefinedType;
15264                    }
15265                    if (!typeSet.has(type.id.toString())) {
15266                        if (type.flags & TypeFlags.Unit && includes & TypeFlags.Unit) {
15267                            // We have seen two distinct unit types which means we should reduce to an
15268                            // empty intersection. Adding TypeFlags.NonPrimitive causes that to happen.
15269                            includes |= TypeFlags.NonPrimitive;
15270                        }
15271                        typeSet.set(type.id.toString(), type);
15272                    }
15273                }
15274                includes |= flags & TypeFlags.IncludesMask;
15275            }
15276            return includes;
15277        }
15278
15279        // Add the given types to the given type set. Order is preserved, freshness is removed from literal
15280        // types, duplicates are removed, and nested types of the given kind are flattened into the set.
15281        function addTypesToIntersection(typeSet: ESMap<string, Type>, includes: TypeFlags, types: readonly Type[]) {
15282            for (const type of types) {
15283                includes = addTypeToIntersection(typeSet, includes, getRegularTypeOfLiteralType(type));
15284            }
15285            return includes;
15286        }
15287
15288        function removeRedundantSupertypes(types: Type[], includes: TypeFlags) {
15289            let i = types.length;
15290            while (i > 0) {
15291                i--;
15292                const t = types[i];
15293                const remove =
15294                    t.flags & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ||
15295                    t.flags & TypeFlags.Number && includes & TypeFlags.NumberLiteral ||
15296                    t.flags & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral ||
15297                    t.flags & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol ||
15298                    t.flags & TypeFlags.Void && includes & TypeFlags.Undefined ||
15299                    isEmptyAnonymousObjectType(t) && includes & TypeFlags.DefinitelyNonNullable;
15300                if (remove) {
15301                    orderedRemoveItemAt(types, i);
15302                }
15303            }
15304        }
15305
15306        // Check that the given type has a match in every union. A given type is matched by
15307        // an identical type, and a literal type is additionally matched by its corresponding
15308        // primitive type.
15309        function eachUnionContains(unionTypes: UnionType[], type: Type) {
15310            for (const u of unionTypes) {
15311                if (!containsType(u.types, type)) {
15312                    const primitive = type.flags & TypeFlags.StringLiteral ? stringType :
15313                        type.flags & TypeFlags.NumberLiteral ? numberType :
15314                        type.flags & TypeFlags.BigIntLiteral ? bigintType :
15315                        type.flags & TypeFlags.UniqueESSymbol ? esSymbolType :
15316                        undefined;
15317                    if (!primitive || !containsType(u.types, primitive)) {
15318                        return false;
15319                    }
15320                }
15321            }
15322            return true;
15323        }
15324
15325        /**
15326         * Returns `true` if the intersection of the template literals and string literals is the empty set, eg `get${string}` & "setX", and should reduce to `never`
15327         */
15328        function extractRedundantTemplateLiterals(types: Type[]): boolean {
15329            let i = types.length;
15330            const literals = filter(types, t => !!(t.flags & TypeFlags.StringLiteral));
15331            while (i > 0) {
15332                i--;
15333                const t = types[i];
15334                if (!(t.flags & TypeFlags.TemplateLiteral)) continue;
15335                for (const t2 of literals) {
15336                    if (isTypeSubtypeOf(t2, t)) {
15337                        // eg, ``get${T}` & "getX"` is just `"getX"`
15338                        orderedRemoveItemAt(types, i);
15339                        break;
15340                    }
15341                    else if (isPatternLiteralType(t)) {
15342                        return true;
15343                    }
15344                }
15345            }
15346            return false;
15347        }
15348
15349        function eachIsUnionContaining(types: Type[], flag: TypeFlags) {
15350            return every(types, t => !!(t.flags & TypeFlags.Union) && some((t as UnionType).types, tt => !!(tt.flags & flag)));
15351        }
15352
15353        function removeFromEach(types: Type[], flag: TypeFlags) {
15354            for (let i = 0; i < types.length; i++) {
15355                types[i] = filterType(types[i], t => !(t.flags & flag));
15356            }
15357        }
15358
15359        // If the given list of types contains more than one union of primitive types, replace the
15360        // first with a union containing an intersection of those primitive types, then remove the
15361        // other unions and return true. Otherwise, do nothing and return false.
15362        function intersectUnionsOfPrimitiveTypes(types: Type[]) {
15363            let unionTypes: UnionType[] | undefined;
15364            const index = findIndex(types, t => !!(getObjectFlags(t) & ObjectFlags.PrimitiveUnion));
15365            if (index < 0) {
15366                return false;
15367            }
15368            let i = index + 1;
15369            // Remove all but the first union of primitive types and collect them in
15370            // the unionTypes array.
15371            while (i < types.length) {
15372                const t = types[i];
15373                if (getObjectFlags(t) & ObjectFlags.PrimitiveUnion) {
15374                    (unionTypes || (unionTypes = [types[index] as UnionType])).push(t as UnionType);
15375                    orderedRemoveItemAt(types, i);
15376                }
15377                else {
15378                    i++;
15379                }
15380            }
15381            // Return false if there was only one union of primitive types
15382            if (!unionTypes) {
15383                return false;
15384            }
15385            // We have more than one union of primitive types, now intersect them. For each
15386            // type in each union we check if the type is matched in every union and if so
15387            // we include it in the result.
15388            const checked: Type[] = [];
15389            const result: Type[] = [];
15390            for (const u of unionTypes) {
15391                for (const t of u.types) {
15392                    if (insertType(checked, t)) {
15393                        if (eachUnionContains(unionTypes, t)) {
15394                            insertType(result, t);
15395                        }
15396                    }
15397                }
15398            }
15399            // Finally replace the first union with the result
15400            types[index] = getUnionTypeFromSortedList(result, ObjectFlags.PrimitiveUnion);
15401            return true;
15402        }
15403
15404        function createIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) {
15405            const result = createType(TypeFlags.Intersection) as IntersectionType;
15406            result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
15407            result.types = types;
15408            result.aliasSymbol = aliasSymbol;
15409            result.aliasTypeArguments = aliasTypeArguments;
15410            return result;
15411        }
15412
15413        // We normalize combinations of intersection and union types based on the distributive property of the '&'
15414        // operator. Specifically, because X & (A | B) is equivalent to X & A | X & B, we can transform intersection
15415        // types with union type constituents into equivalent union types with intersection type constituents and
15416        // effectively ensure that union types are always at the top level in type representations.
15417        //
15418        // We do not perform structural deduplication on intersection types. Intersection types are created only by the &
15419        // type operator and we can't reduce those because we want to support recursive intersection types. For example,
15420        // a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
15421        // Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
15422        // for intersections of types with signatures can be deterministic.
15423        function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type {
15424            const typeMembershipMap: ESMap<string, Type> = new Map();
15425            const includes = addTypesToIntersection(typeMembershipMap, 0, types);
15426            const typeSet: Type[] = arrayFrom(typeMembershipMap.values());
15427            // An intersection type is considered empty if it contains
15428            // the type never, or
15429            // more than one unit type or,
15430            // an object type and a nullable type (null or undefined), or
15431            // a string-like type and a type known to be non-string-like, or
15432            // a number-like type and a type known to be non-number-like, or
15433            // a symbol-like type and a type known to be non-symbol-like, or
15434            // a void-like type and a type known to be non-void-like, or
15435            // a non-primitive type and a type known to be primitive.
15436            if (includes & TypeFlags.Never) {
15437                return contains(typeSet, silentNeverType) ? silentNeverType : neverType;
15438            }
15439            if (strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) ||
15440                includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) ||
15441                includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) ||
15442                includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) ||
15443                includes & TypeFlags.BigIntLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) ||
15444                includes & TypeFlags.ESSymbolLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) ||
15445                includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike)) {
15446                return neverType;
15447            }
15448            if (includes & TypeFlags.TemplateLiteral && includes & TypeFlags.StringLiteral && extractRedundantTemplateLiterals(typeSet)) {
15449                return neverType;
15450            }
15451            if (includes & TypeFlags.Any) {
15452                return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType;
15453            }
15454            if (!strictNullChecks && includes & TypeFlags.Nullable) {
15455                return includes & TypeFlags.IncludesEmptyObject ? neverType : includes & TypeFlags.Undefined ? undefinedType : nullType;
15456            }
15457            if (includes & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ||
15458                includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral ||
15459                includes & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral ||
15460                includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol ||
15461                includes & TypeFlags.Void && includes & TypeFlags.Undefined ||
15462                includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.DefinitelyNonNullable) {
15463                if (!noSupertypeReduction) removeRedundantSupertypes(typeSet, includes);
15464            }
15465            if (includes & TypeFlags.IncludesMissingType) {
15466                typeSet[typeSet.indexOf(undefinedType)] = missingType;
15467            }
15468            if (typeSet.length === 0) {
15469                return unknownType;
15470            }
15471            if (typeSet.length === 1) {
15472                return typeSet[0];
15473            }
15474            const id = getTypeListId(typeSet) + getAliasId(aliasSymbol, aliasTypeArguments);
15475            let result = intersectionTypes.get(id);
15476            if (!result) {
15477                if (includes & TypeFlags.Union) {
15478                    if (intersectUnionsOfPrimitiveTypes(typeSet)) {
15479                        // When the intersection creates a reduced set (which might mean that *all* union types have
15480                        // disappeared), we restart the operation to get a new set of combined flags. Once we have
15481                        // reduced we'll never reduce again, so this occurs at most once.
15482                        result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
15483                    }
15484                    else if (eachIsUnionContaining(typeSet, TypeFlags.Undefined)) {
15485                        const undefinedOrMissingType = exactOptionalPropertyTypes && some(typeSet, t => containsType((t as UnionType).types, missingType)) ? missingType : undefinedType;
15486                        removeFromEach(typeSet, TypeFlags.Undefined);
15487                        result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
15488                    }
15489                    else if (eachIsUnionContaining(typeSet, TypeFlags.Null)) {
15490                        removeFromEach(typeSet, TypeFlags.Null);
15491                        result = getUnionType([getIntersectionType(typeSet), nullType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
15492                    }
15493                    else {
15494                        // We are attempting to construct a type of the form X & (A | B) & (C | D). Transform this into a type of
15495                        // the form X & A & C | X & A & D | X & B & C | X & B & D. If the estimated size of the resulting union type
15496                        // exceeds 100000 constituents, report an error.
15497                        if (!checkCrossProductUnion(typeSet)) {
15498                            return errorType;
15499                        }
15500                        const constituents = getCrossProductIntersections(typeSet);
15501                        // We attach a denormalized origin type when at least one constituent of the cross-product union is an
15502                        // intersection (i.e. when the intersection didn't just reduce one or more unions to smaller unions) and
15503                        // the denormalized origin has fewer constituents than the union itself.
15504                        const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) && getConstituentCountOfTypes(constituents) > getConstituentCountOfTypes(typeSet) ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined;
15505                        result = getUnionType(constituents, UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin);
15506                    }
15507                }
15508                else {
15509                    result = createIntersectionType(typeSet, aliasSymbol, aliasTypeArguments);
15510                }
15511                intersectionTypes.set(id, result);
15512            }
15513            return result;
15514        }
15515
15516        function getCrossProductUnionSize(types: readonly Type[]) {
15517            return reduceLeft(types, (n, t) => t.flags & TypeFlags.Union ? n * (t as UnionType).types.length : t.flags & TypeFlags.Never ? 0 : n, 1);
15518        }
15519
15520        function checkCrossProductUnion(types: readonly Type[]) {
15521            const size = getCrossProductUnionSize(types);
15522            if (size >= 100000) {
15523                tracing?.instant(tracing.Phase.CheckTypes, "checkCrossProductUnion_DepthLimit", { typeIds: types.map(t => t.id), size });
15524                error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
15525                return false;
15526            }
15527            return true;
15528        }
15529
15530        function getCrossProductIntersections(types: readonly Type[]) {
15531            const count = getCrossProductUnionSize(types);
15532            const intersections: Type[] = [];
15533            for (let i = 0; i < count; i++) {
15534                const constituents = types.slice();
15535                let n = i;
15536                for (let j = types.length - 1; j >= 0; j--) {
15537                    if (types[j].flags & TypeFlags.Union) {
15538                        const sourceTypes = (types[j] as UnionType).types;
15539                        const length = sourceTypes.length;
15540                        constituents[j] = sourceTypes[n % length];
15541                        n = Math.floor(n / length);
15542                    }
15543                }
15544                const t = getIntersectionType(constituents);
15545                if (!(t.flags & TypeFlags.Never)) intersections.push(t);
15546            }
15547            return intersections;
15548        }
15549
15550        function getConstituentCount(type: Type): number {
15551            return !(type.flags & TypeFlags.UnionOrIntersection) || type.aliasSymbol ? 1 :
15552                type.flags & TypeFlags.Union && (type as UnionType).origin ? getConstituentCount((type as UnionType).origin!) :
15553                getConstituentCountOfTypes((type as UnionOrIntersectionType).types);
15554        }
15555
15556        function getConstituentCountOfTypes(types: Type[]): number {
15557            return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0);
15558        }
15559
15560        function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
15561            const links = getNodeLinks(node);
15562            if (!links.resolvedType) {
15563                const aliasSymbol = getAliasSymbolForTypeNode(node);
15564                const types = map(node.types, getTypeFromTypeNode);
15565                const noSupertypeReduction = types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType;
15566                links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction);
15567            }
15568            return links.resolvedType;
15569        }
15570
15571        function createIndexType(type: InstantiableType | UnionOrIntersectionType, stringsOnly: boolean) {
15572            const result = createType(TypeFlags.Index) as IndexType;
15573            result.type = type;
15574            result.stringsOnly = stringsOnly;
15575            return result;
15576        }
15577
15578        function createOriginIndexType(type: InstantiableType | UnionOrIntersectionType) {
15579            const result = createOriginType(TypeFlags.Index) as IndexType;
15580            result.type = type;
15581            return result;
15582        }
15583
15584        function getIndexTypeForGenericType(type: InstantiableType | UnionOrIntersectionType, stringsOnly: boolean) {
15585            return stringsOnly ?
15586                type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, /*stringsOnly*/ true)) :
15587                type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false));
15588        }
15589
15590        /**
15591         * This roughly mirrors `resolveMappedTypeMembers` in the nongeneric case, except only reports a union of the keys calculated,
15592         * rather than manufacturing the properties. We can't just fetch the `constraintType` since that would ignore mappings
15593         * and mapping the `constraintType` directly ignores how mapped types map _properties_ and not keys (thus ignoring subtype
15594         * reduction in the constraintType) when possible.
15595         * @param noIndexSignatures Indicates if _string_ index signatures should be elided. (other index signatures are always reported)
15596         */
15597        function getIndexTypeForMappedType(type: MappedType, stringsOnly: boolean, noIndexSignatures: boolean | undefined) {
15598            const typeParameter = getTypeParameterFromMappedType(type);
15599            const constraintType = getConstraintTypeFromMappedType(type);
15600            const nameType = getNameTypeFromMappedType(type.target as MappedType || type);
15601            if (!nameType && !noIndexSignatures) {
15602                // no mapping and no filtering required, just quickly bail to returning the constraint in the common case
15603                return constraintType;
15604            }
15605            const keyTypes: Type[] = [];
15606            if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
15607                // We have a { [P in keyof T]: X }
15608
15609                // `getApparentType` on the T in a generic mapped type can trigger a circularity
15610                // (conditionals and `infer` types create a circular dependency in the constraint resolution)
15611                // so we only eagerly manifest the keys if the constraint is nongeneric
15612                if (!isGenericIndexType(constraintType)) {
15613                    const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
15614                    forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, stringsOnly, addMemberForKeyType);
15615                }
15616                else {
15617                    // we have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer the whole `keyof whatever` for later
15618                    // since it's not safe to resolve the shape of modifier type
15619                    return getIndexTypeForGenericType(type, stringsOnly);
15620                }
15621            }
15622            else {
15623                forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
15624            }
15625            if (isGenericIndexType(constraintType)) { // include the generic component in the resulting type
15626                forEachType(constraintType, addMemberForKeyType);
15627            }
15628            // we had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the original constraintType,
15629            // so we can return the union that preserves aliases/origin data if possible
15630            const result = noIndexSignatures ? filterType(getUnionType(keyTypes), t => !(t.flags & (TypeFlags.Any | TypeFlags.String))) : getUnionType(keyTypes);
15631            if (result.flags & TypeFlags.Union && constraintType.flags & TypeFlags.Union && getTypeListId((result as UnionType).types) === getTypeListId((constraintType as UnionType).types)){
15632                return constraintType;
15633            }
15634            return result;
15635
15636            function addMemberForKeyType(keyType: Type) {
15637                const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType;
15638                // `keyof` currently always returns `string | number` for concrete `string` index signatures - the below ternary keeps that behavior for mapped types
15639                // See `getLiteralTypeFromProperties` where there's a similar ternary to cause the same behavior.
15640                keyTypes.push(propNameType === stringType ? stringOrNumberType : propNameType);
15641            }
15642        }
15643
15644        // Ordinarily we reduce a keyof M, where M is a mapped type { [P in K as N<P>]: X }, to simply N<K>. This however presumes
15645        // that N distributes over union types, i.e. that N<A | B | C> is equivalent to N<A> | N<B> | N<C>. Specifically, we only
15646        // want to perform the reduction when the name type of a mapped type is distributive with respect to the type variable
15647        // introduced by the 'in' clause of the mapped type. Note that non-generic types are considered to be distributive because
15648        // they're the same type regardless of what's being distributed over.
15649        function hasDistributiveNameType(mappedType: MappedType) {
15650            const typeVariable = getTypeParameterFromMappedType(mappedType);
15651            return isDistributive(getNameTypeFromMappedType(mappedType) || typeVariable);
15652            function isDistributive(type: Type): boolean {
15653                return type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Primitive | TypeFlags.Never | TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.NonPrimitive) ? true :
15654                    type.flags & TypeFlags.Conditional ? (type as ConditionalType).root.isDistributive && (type as ConditionalType).checkType === typeVariable :
15655                    type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) ? every((type as UnionOrIntersectionType | TemplateLiteralType).types, isDistributive) :
15656                    type.flags & TypeFlags.IndexedAccess ? isDistributive((type as IndexedAccessType).objectType) && isDistributive((type as IndexedAccessType).indexType) :
15657                    type.flags & TypeFlags.Substitution ? isDistributive((type as SubstitutionType).baseType) && isDistributive((type as SubstitutionType).constraint):
15658                    type.flags & TypeFlags.StringMapping ? isDistributive((type as StringMappingType).type) :
15659                    false;
15660            }
15661        }
15662
15663        function getLiteralTypeFromPropertyName(name: PropertyName) {
15664            if (isPrivateIdentifier(name)) {
15665                return neverType;
15666            }
15667            return isIdentifier(name) ? getStringLiteralType(unescapeLeadingUnderscores(name.escapedText)) :
15668                getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name));
15669        }
15670
15671        function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags, includeNonPublic?: boolean) {
15672            if (includeNonPublic || !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) {
15673                let type = getSymbolLinks(getLateBoundSymbol(prop)).nameType;
15674                if (!type) {
15675                    const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName;
15676                    type = prop.escapedName === InternalSymbolName.Default ? getStringLiteralType("default") :
15677                        name && getLiteralTypeFromPropertyName(name) || (!isKnownSymbol(prop) ? getStringLiteralType(symbolName(prop)) : undefined);
15678                }
15679                if (type && type.flags & include) {
15680                    return type;
15681                }
15682            }
15683            return neverType;
15684        }
15685
15686        function isKeyTypeIncluded(keyType: Type, include: TypeFlags): boolean {
15687            return !!(keyType.flags & include || keyType.flags & TypeFlags.Intersection && some((keyType as IntersectionType).types, t => isKeyTypeIncluded(t, include)));
15688        }
15689
15690        function getLiteralTypeFromProperties(type: Type, include: TypeFlags, includeOrigin: boolean) {
15691            const origin = includeOrigin && (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference) || type.aliasSymbol) ? createOriginIndexType(type) : undefined;
15692            const propertyTypes = map(getPropertiesOfType(type), prop => getLiteralTypeFromProperty(prop, include));
15693            const indexKeyTypes = map(getIndexInfosOfType(type), info => info !== enumNumberIndexInfo && isKeyTypeIncluded(info.keyType, include) ?
15694                info.keyType === stringType && include & TypeFlags.Number ? stringOrNumberType : info.keyType : neverType);
15695            return getUnionType(concatenate(propertyTypes, indexKeyTypes), UnionReduction.Literal,
15696                /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, origin);
15697        }
15698
15699        /**
15700         * A union type which is reducible upon instantiation (meaning some members are removed under certain instantiations)
15701         * must be kept generic, as that instantiation information needs to flow through the type system. By replacing all
15702         * type parameters in the union with a special never type that is treated as a literal in `getReducedType`, we can cause the `getReducedType` logic
15703         * to reduce the resulting type if possible (since only intersections with conflicting literal-typed properties are reducible).
15704         */
15705        function isPossiblyReducibleByInstantiation(type: Type): boolean {
15706            const uniqueFilled = getUniqueLiteralFilledInstantiation(type);
15707            return getReducedType(uniqueFilled) !== uniqueFilled;
15708        }
15709
15710        function shouldDeferIndexType(type: Type) {
15711            return !!(type.flags & TypeFlags.InstantiableNonPrimitive ||
15712                isGenericTupleType(type) ||
15713                isGenericMappedType(type) && !hasDistributiveNameType(type) ||
15714                type.flags & TypeFlags.Union && some((type as UnionType).types, isPossiblyReducibleByInstantiation) ||
15715                type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType));
15716        }
15717
15718        function getIndexType(type: Type, stringsOnly = keyofStringsOnly, noIndexSignatures?: boolean): Type {
15719            type = getReducedType(type);
15720            return shouldDeferIndexType(type) ? getIndexTypeForGenericType(type as InstantiableType | UnionOrIntersectionType, stringsOnly) :
15721                type.flags & TypeFlags.Union ? getIntersectionType(map((type as UnionType).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
15722                type.flags & TypeFlags.Intersection ? getUnionType(map((type as IntersectionType).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
15723                getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(type as MappedType, stringsOnly, noIndexSignatures) :
15724                type === wildcardType ? wildcardType :
15725                type.flags & TypeFlags.Unknown ? neverType :
15726                type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType :
15727                getLiteralTypeFromProperties(type, (noIndexSignatures ? TypeFlags.StringLiteral : TypeFlags.StringLike) | (stringsOnly ? 0 : TypeFlags.NumberLike | TypeFlags.ESSymbolLike),
15728                    stringsOnly === keyofStringsOnly && !noIndexSignatures);
15729        }
15730
15731        function getExtractStringType(type: Type) {
15732            if (keyofStringsOnly) {
15733                return type;
15734            }
15735            const extractTypeAlias = getGlobalExtractSymbol();
15736            return extractTypeAlias ? getTypeAliasInstantiation(extractTypeAlias, [type, stringType]) : stringType;
15737        }
15738
15739        function getIndexTypeOrString(type: Type): Type {
15740            const indexType = getExtractStringType(getIndexType(type));
15741            return indexType.flags & TypeFlags.Never ? stringType : indexType;
15742        }
15743
15744        function getTypeFromTypeOperatorNode(node: TypeOperatorNode): Type {
15745            const links = getNodeLinks(node);
15746            if (!links.resolvedType) {
15747                switch (node.operator) {
15748                    case SyntaxKind.KeyOfKeyword:
15749                        links.resolvedType = getIndexType(getTypeFromTypeNode(node.type));
15750                        break;
15751                    case SyntaxKind.UniqueKeyword:
15752                        links.resolvedType = node.type.kind === SyntaxKind.SymbolKeyword
15753                            ? getESSymbolLikeTypeForNode(walkUpParenthesizedTypes(node.parent))
15754                            : errorType;
15755                        break;
15756                    case SyntaxKind.ReadonlyKeyword:
15757                        links.resolvedType = getTypeFromTypeNode(node.type);
15758                        break;
15759                    default:
15760                        throw Debug.assertNever(node.operator);
15761                }
15762            }
15763            return links.resolvedType;
15764        }
15765
15766        function getTypeFromTemplateTypeNode(node: TemplateLiteralTypeNode) {
15767            const links = getNodeLinks(node);
15768            if (!links.resolvedType) {
15769                links.resolvedType = getTemplateLiteralType(
15770                    [node.head.text, ...map(node.templateSpans, span => span.literal.text)],
15771                    map(node.templateSpans, span => getTypeFromTypeNode(span.type)));
15772            }
15773            return links.resolvedType;
15774        }
15775
15776        function getTemplateLiteralType(texts: readonly string[], types: readonly Type[]): Type {
15777            const unionIndex = findIndex(types, t => !!(t.flags & (TypeFlags.Never | TypeFlags.Union)));
15778            if (unionIndex >= 0) {
15779                return checkCrossProductUnion(types) ?
15780                    mapType(types[unionIndex], t => getTemplateLiteralType(texts, replaceElement(types, unionIndex, t))) :
15781                    errorType;
15782            }
15783            if (contains(types, wildcardType)) {
15784                return wildcardType;
15785            }
15786            const newTypes: Type[] = [];
15787            const newTexts: string[] = [];
15788            let text = texts[0];
15789            if (!addSpans(texts, types)) {
15790                return stringType;
15791            }
15792            if (newTypes.length === 0) {
15793                return getStringLiteralType(text);
15794            }
15795            newTexts.push(text);
15796            if (every(newTexts, t => t === "")) {
15797                if (every(newTypes, t => !!(t.flags & TypeFlags.String))) {
15798                    return stringType;
15799                }
15800                // Normalize `${Mapping<xxx>}` into Mapping<xxx>
15801                if (newTypes.length === 1 && isPatternLiteralType(newTypes[0])) {
15802                    return newTypes[0];
15803                }
15804            }
15805            const id = `${getTypeListId(newTypes)}|${map(newTexts, t => t.length).join(",")}|${newTexts.join("")}`;
15806            let type = templateLiteralTypes.get(id);
15807            if (!type) {
15808                templateLiteralTypes.set(id, type = createTemplateLiteralType(newTexts, newTypes));
15809            }
15810            return type;
15811
15812            function addSpans(texts: readonly string[] | string, types: readonly Type[]): boolean {
15813                const isTextsArray = isArray(texts);
15814                for (let i = 0; i < types.length; i++) {
15815                    const t = types[i];
15816                    const addText = isTextsArray ? texts[i + 1] : texts;
15817                    if (t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) {
15818                        text += getTemplateStringForType(t) || "";
15819                        text += addText;
15820                        if (!isTextsArray) return true;
15821                    }
15822                    else if (t.flags & TypeFlags.TemplateLiteral) {
15823                        text += (t as TemplateLiteralType).texts[0];
15824                        if (!addSpans((t as TemplateLiteralType).texts, (t as TemplateLiteralType).types)) return false;
15825                        text += addText;
15826                        if (!isTextsArray) return true;
15827                    }
15828                    else if (isGenericIndexType(t) || isPatternLiteralPlaceholderType(t)) {
15829                        newTypes.push(t);
15830                        newTexts.push(text);
15831                        text = addText;
15832                    }
15833                    else if (t.flags & TypeFlags.Intersection) {
15834                        const added = addSpans(texts[i + 1], (t as IntersectionType).types);
15835                        if (!added) return false;
15836                    }
15837                    else if (isTextsArray) {
15838                        return false;
15839                    }
15840                }
15841                return true;
15842            }
15843        }
15844
15845        function getTemplateStringForType(type: Type) {
15846            return type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value :
15847                type.flags & TypeFlags.NumberLiteral ? "" + (type as NumberLiteralType).value :
15848                type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((type as BigIntLiteralType).value) :
15849                type.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) ? (type as IntrinsicType).intrinsicName :
15850                undefined;
15851        }
15852
15853        function createTemplateLiteralType(texts: readonly string[], types: readonly Type[]) {
15854            const type = createType(TypeFlags.TemplateLiteral) as TemplateLiteralType;
15855            type.texts = texts;
15856            type.types = types;
15857            return type;
15858        }
15859
15860        function getStringMappingType(symbol: Symbol, type: Type): Type {
15861            return type.flags & (TypeFlags.Union | TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) :
15862                type.flags & TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) :
15863                type.flags & TypeFlags.TemplateLiteral ? getTemplateLiteralType(...applyTemplateStringMapping(symbol, (type as TemplateLiteralType).texts, (type as TemplateLiteralType).types)) :
15864                // Mapping<Mapping<T>> === Mapping<T>
15865                type.flags & TypeFlags.StringMapping && symbol === type.symbol ? type :
15866                type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.StringMapping) || isGenericIndexType(type) ? getStringMappingTypeForGenericType(symbol, type) :
15867                // This handles Mapping<`${number}`> and Mapping<`${bigint}`>
15868                isPatternLiteralPlaceholderType(type) ? getStringMappingTypeForGenericType(symbol, getTemplateLiteralType(["", ""], [type])) :
15869                type;
15870        }
15871
15872        function applyStringMapping(symbol: Symbol, str: string) {
15873            switch (intrinsicTypeKinds.get(symbol.escapedName as string)) {
15874                case IntrinsicTypeKind.Uppercase: return str.toUpperCase();
15875                case IntrinsicTypeKind.Lowercase: return str.toLowerCase();
15876                case IntrinsicTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1);
15877                case IntrinsicTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1);
15878            }
15879            return str;
15880        }
15881
15882        function applyTemplateStringMapping(symbol: Symbol, texts: readonly string[], types: readonly Type[]): [texts: readonly string[], types: readonly Type[]] {
15883            switch (intrinsicTypeKinds.get(symbol.escapedName as string)) {
15884                case IntrinsicTypeKind.Uppercase: return [texts.map(t => t.toUpperCase()), types.map(t => getStringMappingType(symbol, t))];
15885                case IntrinsicTypeKind.Lowercase: return [texts.map(t => t.toLowerCase()), types.map(t => getStringMappingType(symbol, t))];
15886                case IntrinsicTypeKind.Capitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toUpperCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types];
15887                case IntrinsicTypeKind.Uncapitalize: return [texts[0] === "" ? texts : [texts[0].charAt(0).toLowerCase() + texts[0].slice(1), ...texts.slice(1)], texts[0] === "" ? [getStringMappingType(symbol, types[0]), ...types.slice(1)] : types];
15888            }
15889            return [texts, types];
15890        }
15891
15892        function getStringMappingTypeForGenericType(symbol: Symbol, type: Type): Type {
15893            const id = `${getSymbolId(symbol)},${getTypeId(type)}`;
15894            let result = stringMappingTypes.get(id);
15895            if (!result) {
15896                stringMappingTypes.set(id, result = createStringMappingType(symbol, type));
15897            }
15898            return result;
15899        }
15900
15901        function createStringMappingType(symbol: Symbol, type: Type) {
15902            const result = createType(TypeFlags.StringMapping) as StringMappingType;
15903            result.symbol = symbol;
15904            result.type = type;
15905            return result;
15906        }
15907
15908        function createIndexedAccessType(objectType: Type, indexType: Type, accessFlags: AccessFlags, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) {
15909            const type = createType(TypeFlags.IndexedAccess) as IndexedAccessType;
15910            type.objectType = objectType;
15911            type.indexType = indexType;
15912            type.accessFlags = accessFlags;
15913            type.aliasSymbol = aliasSymbol;
15914            type.aliasTypeArguments = aliasTypeArguments;
15915            return type;
15916        }
15917
15918        /**
15919         * Returns if a type is or consists of a JSLiteral object type
15920         * In addition to objects which are directly literals,
15921         * * unions where every element is a jsliteral
15922         * * intersections where at least one element is a jsliteral
15923         * * and instantiable types constrained to a jsliteral
15924         * Should all count as literals and not print errors on access or assignment of possibly existing properties.
15925         * This mirrors the behavior of the index signature propagation, to which this behaves similarly (but doesn't affect assignability or inference).
15926         */
15927        function isJSLiteralType(type: Type): boolean {
15928            if (noImplicitAny) {
15929                return false; // Flag is meaningless under `noImplicitAny` mode
15930            }
15931            if (getObjectFlags(type) & ObjectFlags.JSLiteral) {
15932                return true;
15933            }
15934            if (type.flags & TypeFlags.Union) {
15935                return every((type as UnionType).types, isJSLiteralType);
15936            }
15937            if (type.flags & TypeFlags.Intersection) {
15938                return some((type as IntersectionType).types, isJSLiteralType);
15939            }
15940            if (type.flags & TypeFlags.Instantiable) {
15941                const constraint = getResolvedBaseConstraint(type);
15942                return constraint !== type && isJSLiteralType(constraint);
15943            }
15944            return false;
15945        }
15946
15947        function getPropertyNameFromIndex(indexType: Type, accessNode: StringLiteral | Identifier | PrivateIdentifier | ObjectBindingPattern | ArrayBindingPattern | ComputedPropertyName | NumericLiteral | IndexedAccessTypeNode | ElementAccessExpression | SyntheticExpression | undefined) {
15948            return isTypeUsableAsPropertyName(indexType) ?
15949                getPropertyNameFromType(indexType) :
15950                    accessNode && isPropertyName(accessNode) ?
15951                        // late bound names are handled in the first branch, so here we only need to handle normal names
15952                        getPropertyNameForPropertyNameNode(accessNode) :
15953                        undefined;
15954        }
15955
15956        function isUncalledFunctionReference(node: Node, symbol: Symbol) {
15957            if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
15958                const parent = findAncestor(node.parent, n => !isAccessExpression(n)) || node.parent;
15959                if (isCallLikeExpression(parent)) {
15960                    return isCallOrNewExpression(parent) && isIdentifier(node) && hasMatchingArgument(parent, node);
15961                }
15962                return every(symbol.declarations, d => !isFunctionLike(d) || !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated));
15963            }
15964            return true;
15965        }
15966
15967        function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, fullIndexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, accessFlags: AccessFlags) {
15968            const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
15969            const propName = accessNode && isPrivateIdentifier(accessNode) ? undefined : getPropertyNameFromIndex(indexType, accessNode);
15970
15971            if (propName !== undefined) {
15972                if (accessFlags & AccessFlags.Contextual) {
15973                    return getTypeOfPropertyOfContextualType(objectType, propName) || anyType;
15974                }
15975                const prop = getPropertyOfType(objectType, propName);
15976                if (prop) {
15977                    if (accessFlags & AccessFlags.ReportDeprecated && accessNode && prop.declarations && isDeprecatedSymbol(prop) && isUncalledFunctionReference(accessNode, prop)) {
15978                        const deprecatedNode = accessExpression?.argumentExpression ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode);
15979                        addDeprecatedSuggestion(deprecatedNode, prop.declarations, propName as string);
15980                    }
15981                    if (accessExpression) {
15982                        markPropertyAsReferenced(prop, accessExpression, isSelfTypeAccess(accessExpression.expression, objectType.symbol));
15983                        if (isAssignmentToReadonlyEntity(accessExpression, prop, getAssignmentTargetKind(accessExpression))) {
15984                            error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(prop));
15985                            return undefined;
15986                        }
15987                        if (accessFlags & AccessFlags.CacheSymbol) {
15988                            getNodeLinks(accessNode!).resolvedSymbol = prop;
15989                        }
15990                        if (isThisPropertyAccessInConstructor(accessExpression, prop)) {
15991                            return autoType;
15992                        }
15993                    }
15994                    const propType = getTypeOfSymbol(prop);
15995                    return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ?
15996                        getFlowTypeOfReference(accessExpression, propType) :
15997                        propType;
15998                }
15999                if (everyType(objectType, isTupleType) && isNumericLiteralName(propName)) {
16000                    const index = +propName;
16001                    if (accessNode && everyType(objectType, t => !(t as TupleTypeReference).target.hasRestElement) && !(accessFlags & AccessFlags.NoTupleBoundsCheck)) {
16002                        const indexNode = getIndexNodeForAccessExpression(accessNode);
16003                        if (isTupleType(objectType)) {
16004                            if (index < 0) {
16005                                error(indexNode, Diagnostics.A_tuple_type_cannot_be_indexed_with_a_negative_value);
16006                                return undefinedType;
16007                            }
16008                            error(indexNode, Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2,
16009                                typeToString(objectType), getTypeReferenceArity(objectType), unescapeLeadingUnderscores(propName));
16010                        }
16011                        else {
16012                            error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
16013                        }
16014                    }
16015                    if (index >= 0) {
16016                        errorIfWritingToReadonlyIndex(getIndexInfoOfType(objectType, numberType));
16017                        return mapType(objectType, t => {
16018                            const restType = getRestTypeOfTupleType(t as TupleTypeReference) || undefinedType;
16019                            return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([restType, undefinedType]) : restType;
16020                        });
16021                    }
16022                }
16023            }
16024            if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike)) {
16025                if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) {
16026                    return objectType;
16027                }
16028                // If no index signature is applicable, we default to the string index signature. In effect, this means the string
16029                // index signature applies even when accessing with a symbol-like type.
16030                const indexInfo = getApplicableIndexInfo(objectType, indexType) || getIndexInfoOfType(objectType, stringType);
16031                if (indexInfo) {
16032                    if (accessFlags & AccessFlags.NoIndexSignatures && indexInfo.keyType !== numberType) {
16033                        if (accessExpression) {
16034                            error(accessExpression, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType));
16035                        }
16036                        return undefined;
16037                    }
16038                    if (accessNode && indexInfo.keyType === stringType && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) {
16039                        const indexNode = getIndexNodeForAccessExpression(accessNode);
16040                        error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
16041                        return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
16042                    }
16043                    errorIfWritingToReadonlyIndex(indexInfo);
16044                    // When accessing an enum object with its own type,
16045                    // e.g. E[E.A] for enum E { A }, undefined shouldn't
16046                    // be included in the result type
16047                    if ((accessFlags & AccessFlags.IncludeUndefined) &&
16048                        !(objectType.symbol &&
16049                            objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum) &&
16050                            (indexType.symbol &&
16051                            indexType.flags & TypeFlags.EnumLiteral &&
16052                            getParentOfSymbol(indexType.symbol) === objectType.symbol))) {
16053                        return getUnionType([indexInfo.type, undefinedType]);
16054                    }
16055                    return indexInfo.type;
16056                }
16057                if (indexType.flags & TypeFlags.Never) {
16058                    return neverType;
16059                }
16060                if (isJSLiteralType(objectType)) {
16061                    return anyType;
16062                }
16063                if (accessExpression && !isConstEnumObjectType(objectType)) {
16064                    if (isObjectLiteralType(objectType)) {
16065                        if (noImplicitAny && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
16066                            diagnostics.add(createDiagnosticForNode(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType)));
16067                            return undefinedType;
16068                        }
16069                        else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) {
16070                            const types = map((objectType as ResolvedType).properties, property => {
16071                                return getTypeOfSymbol(property);
16072                            });
16073                            return getUnionType(append(types, undefinedType));
16074                        }
16075                    }
16076
16077                    if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped)) {
16078                        error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
16079                    }
16080                    else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & AccessFlags.SuppressNoImplicitAnyError)) {
16081                        if (propName !== undefined && typeHasStaticProperty(propName, objectType)) {
16082                            const typeName = typeToString(objectType);
16083                            error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName as string, typeName, typeName + "[" + getTextOfNode(accessExpression.argumentExpression) + "]");
16084                        }
16085                        else if (getIndexTypeOfType(objectType, numberType)) {
16086                            error(accessExpression.argumentExpression, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number);
16087                        }
16088                        else {
16089                            let suggestion: string | undefined;
16090                            if (propName !== undefined && (suggestion = getSuggestionForNonexistentProperty(propName as string, objectType))) {
16091                                if (suggestion !== undefined) {
16092                                    error(accessExpression.argumentExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName as string, typeToString(objectType), suggestion);
16093                                }
16094                            }
16095                            else {
16096                                const suggestion = getSuggestionForNonexistentIndexSignature(objectType, accessExpression, indexType);
16097                                if (suggestion !== undefined) {
16098                                    error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestion);
16099                                }
16100                                else {
16101                                    let errorInfo: DiagnosticMessageChain | undefined;
16102                                    if (indexType.flags & TypeFlags.EnumLiteral) {
16103                                        errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, "[" + typeToString(indexType) + "]", typeToString(objectType));
16104                                    }
16105                                    else if (indexType.flags & TypeFlags.UniqueESSymbol) {
16106                                        const symbolName = getFullyQualifiedName((indexType as UniqueESSymbolType).symbol, accessExpression);
16107                                        errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, "[" + symbolName + "]", typeToString(objectType));
16108                                    }
16109                                    else if (indexType.flags & TypeFlags.StringLiteral) {
16110                                        errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType));
16111                                    }
16112                                    else if (indexType.flags & TypeFlags.NumberLiteral) {
16113                                        errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as NumberLiteralType).value, typeToString(objectType));
16114                                    }
16115                                    else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) {
16116                                        errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.No_index_signature_with_a_parameter_of_type_0_was_found_on_type_1, typeToString(indexType), typeToString(objectType));
16117                                    }
16118
16119                                    errorInfo = chainDiagnosticMessages(
16120                                        errorInfo,
16121                                        Diagnostics.Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1, typeToString(fullIndexType), typeToString(objectType)
16122                                    );
16123                                    diagnostics.add(createDiagnosticForNodeFromMessageChain(accessExpression, errorInfo));
16124                                }
16125                            }
16126                        }
16127                    }
16128                    return undefined;
16129                }
16130            }
16131            if (isJSLiteralType(objectType)) {
16132                return anyType;
16133            }
16134            if (accessNode) {
16135                const indexNode = getIndexNodeForAccessExpression(accessNode);
16136                if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
16137                    error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (indexType as StringLiteralType | NumberLiteralType).value, typeToString(objectType));
16138                }
16139                else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) {
16140                    error(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType));
16141                }
16142                else {
16143                    error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
16144                }
16145            }
16146            if (isTypeAny(indexType)) {
16147                return indexType;
16148            }
16149            return undefined;
16150
16151            function errorIfWritingToReadonlyIndex(indexInfo: IndexInfo | undefined): void {
16152                if (indexInfo && indexInfo.isReadonly && accessExpression && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
16153                    error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
16154                }
16155            }
16156        }
16157
16158        function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression) {
16159            return accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression :
16160                accessNode.kind === SyntaxKind.IndexedAccessType ? accessNode.indexType :
16161                accessNode.kind === SyntaxKind.ComputedPropertyName ? accessNode.expression :
16162                accessNode;
16163        }
16164
16165        function isPatternLiteralPlaceholderType(type: Type): boolean {
16166            return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) || isPatternLiteralType(type);
16167        }
16168
16169        function isPatternLiteralType(type: Type) {
16170            return !!(type.flags & TypeFlags.TemplateLiteral) && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType) ||
16171                !!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type);
16172        }
16173
16174        function isGenericType(type: Type): boolean {
16175            return !!getGenericObjectFlags(type);
16176        }
16177
16178        function isGenericObjectType(type: Type): boolean {
16179            return !!(getGenericObjectFlags(type) & ObjectFlags.IsGenericObjectType);
16180        }
16181
16182        function isGenericIndexType(type: Type): boolean {
16183            return !!(getGenericObjectFlags(type) & ObjectFlags.IsGenericIndexType);
16184        }
16185
16186        function getGenericObjectFlags(type: Type): ObjectFlags {
16187            if (type.flags & TypeFlags.UnionOrIntersection) {
16188                if (!((type as UnionOrIntersectionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) {
16189                    (type as UnionOrIntersectionType).objectFlags |= ObjectFlags.IsGenericTypeComputed |
16190                        reduceLeft((type as UnionOrIntersectionType).types, (flags, t) => flags | getGenericObjectFlags(t), 0);
16191                }
16192                return (type as UnionOrIntersectionType).objectFlags & ObjectFlags.IsGenericType;
16193            }
16194            if (type.flags & TypeFlags.Substitution) {
16195                if (!((type as SubstitutionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) {
16196                    (type as SubstitutionType).objectFlags |= ObjectFlags.IsGenericTypeComputed |
16197                        getGenericObjectFlags((type as SubstitutionType).baseType) | getGenericObjectFlags((type as SubstitutionType).constraint);
16198                }
16199                return (type as SubstitutionType).objectFlags & ObjectFlags.IsGenericType;
16200            }
16201            return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ObjectFlags.IsGenericObjectType : 0) |
16202                (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0);
16203        }
16204
16205        function getSimplifiedType(type: Type, writing: boolean): Type {
16206            return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing) :
16207                type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(type as ConditionalType, writing) :
16208                type;
16209        }
16210
16211        function distributeIndexOverObjectType(objectType: Type, indexType: Type, writing: boolean) {
16212            // (T | U)[K] -> T[K] | U[K] (reading)
16213            // (T | U)[K] -> T[K] & U[K] (writing)
16214            // (T & U)[K] -> T[K] & U[K]
16215            if (objectType.flags & TypeFlags.Union || objectType.flags & TypeFlags.Intersection && !shouldDeferIndexType(objectType)) {
16216                const types = map((objectType as UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType), writing));
16217                return objectType.flags & TypeFlags.Intersection || writing ? getIntersectionType(types) : getUnionType(types);
16218            }
16219        }
16220
16221        function distributeObjectOverIndexType(objectType: Type, indexType: Type, writing: boolean) {
16222            // T[A | B] -> T[A] | T[B] (reading)
16223            // T[A | B] -> T[A] & T[B] (writing)
16224            if (indexType.flags & TypeFlags.Union) {
16225                const types = map((indexType as UnionType).types, t => getSimplifiedType(getIndexedAccessType(objectType, t), writing));
16226                return writing ? getIntersectionType(types) : getUnionType(types);
16227            }
16228        }
16229
16230        // Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
16231        // the type itself if no transformation is possible. The writing flag indicates that the type is
16232        // the target of an assignment.
16233        function getSimplifiedIndexedAccessType(type: IndexedAccessType, writing: boolean): Type {
16234            const cache = writing ? "simplifiedForWriting" : "simplifiedForReading";
16235            if (type[cache]) {
16236                return type[cache] === circularConstraintType ? type : type[cache]!;
16237            }
16238            type[cache] = circularConstraintType;
16239            // We recursively simplify the object type as it may in turn be an indexed access type. For example, with
16240            // '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type.
16241            const objectType = getSimplifiedType(type.objectType, writing);
16242            const indexType = getSimplifiedType(type.indexType, writing);
16243            // T[A | B] -> T[A] | T[B] (reading)
16244            // T[A | B] -> T[A] & T[B] (writing)
16245            const distributedOverIndex = distributeObjectOverIndexType(objectType, indexType, writing);
16246            if (distributedOverIndex) {
16247                return type[cache] = distributedOverIndex;
16248            }
16249            // Only do the inner distributions if the index can no longer be instantiated to cause index distribution again
16250            if (!(indexType.flags & TypeFlags.Instantiable)) {
16251                // (T | U)[K] -> T[K] | U[K] (reading)
16252                // (T | U)[K] -> T[K] & U[K] (writing)
16253                // (T & U)[K] -> T[K] & U[K]
16254                const distributedOverObject = distributeIndexOverObjectType(objectType, indexType, writing);
16255                if (distributedOverObject) {
16256                    return type[cache] = distributedOverObject;
16257                }
16258            }
16259            // So ultimately (reading):
16260            // ((A & B) | C)[K1 | K2] -> ((A & B) | C)[K1] | ((A & B) | C)[K2] -> (A & B)[K1] | C[K1] | (A & B)[K2] | C[K2] -> (A[K1] & B[K1]) | C[K1] | (A[K2] & B[K2]) | C[K2]
16261
16262            // A generic tuple type indexed by a number exists only when the index type doesn't select a
16263            // fixed element. We simplify to either the combined type of all elements (when the index type
16264            // the actual number type) or to the combined type of all non-fixed elements.
16265            if (isGenericTupleType(objectType) && indexType.flags & TypeFlags.NumberLike) {
16266                const elementType = getElementTypeOfSliceOfTupleType(objectType, indexType.flags & TypeFlags.Number ? 0 : objectType.target.fixedLength, /*endSkipCount*/ 0, writing);
16267                if (elementType) {
16268                    return type[cache] = elementType;
16269                }
16270            }
16271            // If the object type is a mapped type { [P in K]: E }, where K is generic, or { [P in K as N]: E }, where
16272            // K is generic and N is assignable to P, instantiate E using a mapper that substitutes the index type for P.
16273            // For example, for an index access { [P in K]: Box<T[P]> }[X], we construct the type Box<T[X]>.
16274            if (isGenericMappedType(objectType)) {
16275                const nameType = getNameTypeFromMappedType(objectType);
16276                if (!nameType || isTypeAssignableTo(nameType, getTypeParameterFromMappedType(objectType))) {
16277                    return type[cache] = mapType(substituteIndexedMappedType(objectType, type.indexType), t => getSimplifiedType(t, writing));
16278                }
16279            }
16280            return type[cache] = type;
16281        }
16282
16283        function getSimplifiedConditionalType(type: ConditionalType, writing: boolean) {
16284            const checkType = type.checkType;
16285            const extendsType = type.extendsType;
16286            const trueType = getTrueTypeFromConditionalType(type);
16287            const falseType = getFalseTypeFromConditionalType(type);
16288            // Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`.
16289            if (falseType.flags & TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) {
16290                if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
16291                    return getSimplifiedType(trueType, writing);
16292                }
16293                else if (isIntersectionEmpty(checkType, extendsType)) { // Always false
16294                    return neverType;
16295                }
16296            }
16297            else if (trueType.flags & TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType)) {
16298                if (!(checkType.flags & TypeFlags.Any) && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true
16299                    return neverType;
16300                }
16301                else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false
16302                    return getSimplifiedType(falseType, writing);
16303                }
16304            }
16305            return type;
16306        }
16307
16308        /**
16309         * Invokes union simplification logic to determine if an intersection is considered empty as a union constituent
16310         */
16311        function isIntersectionEmpty(type1: Type, type2: Type) {
16312            return !!(getUnionType([intersectTypes(type1, type2), neverType]).flags & TypeFlags.Never);
16313        }
16314
16315        function substituteIndexedMappedType(objectType: MappedType, index: Type) {
16316            const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [index]);
16317            const templateMapper = combineTypeMappers(objectType.mapper, mapper);
16318            return instantiateType(getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), templateMapper);
16319        }
16320
16321        function getIndexedAccessType(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
16322            return getIndexedAccessTypeOrUndefined(objectType, indexType, accessFlags, accessNode, aliasSymbol, aliasTypeArguments) || (accessNode ? errorType : unknownType);
16323        }
16324
16325        function indexTypeLessThan(indexType: Type, limit: number) {
16326            return everyType(indexType, t => {
16327                if (t.flags & TypeFlags.StringOrNumberLiteral) {
16328                    const propName = getPropertyNameFromType(t as StringLiteralType | NumberLiteralType);
16329                    if (isNumericLiteralName(propName)) {
16330                        const index = +propName;
16331                        return index >= 0 && index < limit;
16332                    }
16333                }
16334                return false;
16335            });
16336        }
16337
16338        function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type | undefined {
16339            if (objectType === wildcardType || indexType === wildcardType) {
16340                return wildcardType;
16341            }
16342            // If the object type has a string index signature and no other members we know that the result will
16343            // always be the type of that index signature and we can simplify accordingly.
16344            if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) {
16345                indexType = stringType;
16346            }
16347            // In noUncheckedIndexedAccess mode, indexed access operations that occur in an expression in a read position and resolve to
16348            // an index signature have 'undefined' included in their type.
16349            if (compilerOptions.noUncheckedIndexedAccess && accessFlags & AccessFlags.ExpressionPosition) accessFlags |= AccessFlags.IncludeUndefined;
16350            // If the index type is generic, or if the object type is generic and doesn't originate in an expression and
16351            // the operation isn't exclusively indexing the fixed (non-variadic) portion of a tuple type, we are performing
16352            // a higher-order index access where we cannot meaningfully access the properties of the object type. Note that
16353            // for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in an expression. This is to
16354            // preserve backwards compatibility. For example, an element access 'this["foo"]' has always been resolved
16355            // eagerly using the constraint type of 'this' at the given location.
16356            if (isGenericIndexType(indexType) || (accessNode && accessNode.kind !== SyntaxKind.IndexedAccessType ?
16357                isGenericTupleType(objectType) && !indexTypeLessThan(indexType, objectType.target.fixedLength) :
16358                isGenericObjectType(objectType) && !(isTupleType(objectType) && indexTypeLessThan(indexType, objectType.target.fixedLength)))) {
16359                if (objectType.flags & TypeFlags.AnyOrUnknown) {
16360                    return objectType;
16361                }
16362                // Defer the operation by creating an indexed access type.
16363                const persistentAccessFlags = accessFlags & AccessFlags.Persistent;
16364                const id = objectType.id + "," + indexType.id + "," + persistentAccessFlags + getAliasId(aliasSymbol, aliasTypeArguments);
16365                let type = indexedAccessTypes.get(id);
16366                if (!type) {
16367                    indexedAccessTypes.set(id, type = createIndexedAccessType(objectType, indexType, persistentAccessFlags, aliasSymbol, aliasTypeArguments));
16368                }
16369
16370                return type;
16371            }
16372            // In the following we resolve T[K] to the type of the property in T selected by K.
16373            // We treat boolean as different from other unions to improve errors;
16374            // skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'.
16375            const apparentObjectType = getReducedApparentType(objectType);
16376            if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) {
16377                const propTypes: Type[] = [];
16378                let wasMissingProp = false;
16379                for (const t of (indexType as UnionType).types) {
16380                    const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, indexType, accessNode, accessFlags | (wasMissingProp ? AccessFlags.SuppressNoImplicitAnyError : 0));
16381                    if (propType) {
16382                        propTypes.push(propType);
16383                    }
16384                    else if (!accessNode) {
16385                        // If there's no error node, we can immeditely stop, since error reporting is off
16386                        return undefined;
16387                    }
16388                    else {
16389                        // Otherwise we set a flag and return at the end of the loop so we still mark all errors
16390                        wasMissingProp = true;
16391                    }
16392                }
16393                if (wasMissingProp) {
16394                    return undefined;
16395                }
16396                return accessFlags & AccessFlags.Writing
16397                    ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments)
16398                    : getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
16399            }
16400            return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, accessNode, accessFlags | AccessFlags.CacheSymbol | AccessFlags.ReportDeprecated);
16401        }
16402
16403        function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
16404            const links = getNodeLinks(node);
16405            if (!links.resolvedType) {
16406                const objectType = getTypeFromTypeNode(node.objectType);
16407                const indexType = getTypeFromTypeNode(node.indexType);
16408                const potentialAlias = getAliasSymbolForTypeNode(node);
16409                links.resolvedType = getIndexedAccessType(objectType, indexType, AccessFlags.None, node, potentialAlias, getTypeArgumentsForAliasSymbol(potentialAlias));
16410            }
16411            return links.resolvedType;
16412        }
16413
16414        function getTypeFromMappedTypeNode(node: MappedTypeNode): Type {
16415            const links = getNodeLinks(node);
16416            if (!links.resolvedType) {
16417                const type = createObjectType(ObjectFlags.Mapped, node.symbol) as MappedType;
16418                type.declaration = node;
16419                type.aliasSymbol = getAliasSymbolForTypeNode(node);
16420                type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(type.aliasSymbol);
16421                links.resolvedType = type;
16422                // Eagerly resolve the constraint type which forces an error if the constraint type circularly
16423                // references itself through one or more type aliases.
16424                getConstraintTypeFromMappedType(type);
16425            }
16426            return links.resolvedType;
16427        }
16428
16429        function getActualTypeVariable(type: Type): Type {
16430            if (type.flags & TypeFlags.Substitution) {
16431                return (type as SubstitutionType).baseType;
16432            }
16433            if (type.flags & TypeFlags.IndexedAccess && (
16434                (type as IndexedAccessType).objectType.flags & TypeFlags.Substitution ||
16435                (type as IndexedAccessType).indexType.flags & TypeFlags.Substitution)) {
16436                return getIndexedAccessType(getActualTypeVariable((type as IndexedAccessType).objectType), getActualTypeVariable((type as IndexedAccessType).indexType));
16437            }
16438            return type;
16439        }
16440
16441        function maybeCloneTypeParameter(p: TypeParameter) {
16442            const constraint = getConstraintOfTypeParameter(p);
16443            return constraint && (isGenericObjectType(constraint) || isGenericIndexType(constraint)) ? cloneTypeParameter(p) : p;
16444        }
16445
16446        function isTypicalNondistributiveConditional(root: ConditionalRoot) {
16447            return !root.isDistributive && isSingletonTupleType(root.node.checkType) && isSingletonTupleType(root.node.extendsType);
16448        }
16449
16450        function isSingletonTupleType(node: TypeNode) {
16451            return isTupleTypeNode(node) &&
16452                length(node.elements) === 1 &&
16453                !isOptionalTypeNode(node.elements[0]) &&
16454                !isRestTypeNode(node.elements[0]) &&
16455                !(isNamedTupleMember(node.elements[0]) && (node.elements[0].questionToken || node.elements[0].dotDotDotToken));
16456        }
16457
16458        /**
16459         * We syntactually check for common nondistributive conditional shapes and unwrap them into
16460         * the intended comparison - we do this so we can check if the unwrapped types are generic or
16461         * not and appropriately defer condition calculation
16462         */
16463        function unwrapNondistributiveConditionalTuple(root: ConditionalRoot, type: Type) {
16464            return isTypicalNondistributiveConditional(root) && isTupleType(type) ? getTypeArguments(type)[0] : type;
16465        }
16466
16467        function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
16468            let result;
16469            let extraTypes: Type[] | undefined;
16470            let tailCount = 0;
16471            // We loop here for an immediately nested conditional type in the false position, effectively treating
16472            // types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for
16473            // purposes of resolution. We also loop here when resolution of a conditional type ends in resolution of
16474            // another (or, through recursion, possibly the same) conditional type. In the potentially tail-recursive
16475            // cases we increment the tail recursion counter and stop after 1000 iterations.
16476            while (true) {
16477                if (tailCount === 1000) {
16478                    error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
16479                    result = errorType;
16480                    break;
16481                }
16482                const isUnwrapped = isTypicalNondistributiveConditional(root);
16483                const checkType = instantiateType(unwrapNondistributiveConditionalTuple(root, getActualTypeVariable(root.checkType)), mapper);
16484                const checkTypeInstantiable = isGenericType(checkType);
16485                const extendsType = instantiateType(unwrapNondistributiveConditionalTuple(root, root.extendsType), mapper);
16486                if (checkType === wildcardType || extendsType === wildcardType) {
16487                    return wildcardType;
16488                }
16489                let combinedMapper: TypeMapper | undefined;
16490                if (root.inferTypeParameters) {
16491                    // When we're looking at making an inference for an infer type, when we get its constraint, it'll automagically be
16492                    // instantiated with the context, so it doesn't need the mapper for the inference contex - however the constraint
16493                    // may refer to another _root_, _uncloned_ `infer` type parameter [1], or to something mapped by `mapper` [2].
16494                    // [1] Eg, if we have `Foo<T, U extends T>` and `Foo<number, infer B>` - `B` is constrained to `T`, which, in turn, has been instantiated
16495                    // as `number`
16496                    // Conversely, if we have `Foo<infer A, infer B>`, `B` is still constrained to `T` and `T` is instantiated as `A`
16497                    // [2] Eg, if we have `Foo<T, U extends T>` and `Foo<Q, infer B>` where `Q` is mapped by `mapper` into `number` - `B` is constrained to `T`
16498                    // which is in turn instantiated as `Q`, which is in turn instantiated as `number`.
16499                    // So we need to:
16500                    //    * Clone the type parameters so their constraints can be instantiated in the context of `mapper` (otherwise theyd only get inference context information)
16501                    //    * Set the clones to both map the conditional's enclosing `mapper` and the original params
16502                    //    * instantiate the extends type with the clones
16503                    //    * incorporate all of the component mappers into the combined mapper for the true and false members
16504                    // This means we have three mappers that need applying:
16505                    //    * The original `mapper` used to create this conditional
16506                    //    * The mapper that maps the old root type parameter to the clone (`freshMapper`)
16507                    //    * The mapper that maps the clone to its inference result (`context.mapper`)
16508                    const freshParams = sameMap(root.inferTypeParameters, maybeCloneTypeParameter);
16509                    const freshMapper = freshParams !== root.inferTypeParameters ? createTypeMapper(root.inferTypeParameters, freshParams) : undefined;
16510                    const context = createInferenceContext(freshParams, /*signature*/ undefined, InferenceFlags.None);
16511                    if (freshMapper) {
16512                        const freshCombinedMapper = combineTypeMappers(mapper, freshMapper);
16513                        for (const p of freshParams) {
16514                            if (root.inferTypeParameters.indexOf(p) === -1) {
16515                                p.mapper = freshCombinedMapper;
16516                            }
16517                        }
16518                    }
16519                    if (!checkTypeInstantiable) {
16520                        // We don't want inferences from constraints as they may cause us to eagerly resolve the
16521                        // conditional type instead of deferring resolution. Also, we always want strict function
16522                        // types rules (i.e. proper contravariance) for inferences.
16523                        inferTypes(context.inferences, checkType, instantiateType(extendsType, freshMapper), InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
16524                    }
16525                    const innerMapper = combineTypeMappers(freshMapper, context.mapper);
16526                    // It's possible for 'infer T' type paramteters to be given uninstantiated constraints when the
16527                    // those type parameters are used in type references (see getInferredTypeParameterConstraint). For
16528                    // that reason we need context.mapper to be first in the combined mapper. See #42636 for examples.
16529                    combinedMapper = mapper ? combineTypeMappers(innerMapper, mapper) : innerMapper;
16530                }
16531                // Instantiate the extends type including inferences for 'infer T' type parameters
16532                const inferredExtendsType = combinedMapper ? instantiateType(unwrapNondistributiveConditionalTuple(root, root.extendsType), combinedMapper) : extendsType;
16533                // We attempt to resolve the conditional type only when the check and extends types are non-generic
16534                if (!checkTypeInstantiable && !isGenericType(inferredExtendsType)) {
16535                    // Return falseType for a definitely false extends check. We check an instantiations of the two
16536                    // types with type parameters mapped to the wildcard type, the most permissive instantiations
16537                    // possible (the wildcard type is assignable to and from all types). If those are not related,
16538                    // then no instantiations will be and we can just return the false branch type.
16539                    if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && ((checkType.flags & TypeFlags.Any && !isUnwrapped) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
16540                        // Return union of trueType and falseType for 'any' since it matches anything
16541                        if (checkType.flags & TypeFlags.Any && !isUnwrapped) {
16542                            (extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper));
16543                        }
16544                        // If falseType is an immediately nested conditional type that isn't distributive or has an
16545                        // identical checkType, switch to that type and loop.
16546                        const falseType = getTypeFromTypeNode(root.node.falseType);
16547                        if (falseType.flags & TypeFlags.Conditional) {
16548                            const newRoot = (falseType as ConditionalType).root;
16549                            if (newRoot.node.parent === root.node && (!newRoot.isDistributive || newRoot.checkType === root.checkType)) {
16550                                root = newRoot;
16551                                continue;
16552                            }
16553                            if (canTailRecurse(falseType, mapper)) {
16554                                continue;
16555                            }
16556                        }
16557                        result = instantiateType(falseType, mapper);
16558                        break;
16559                    }
16560                    // Return trueType for a definitely true extends check. We check instantiations of the two
16561                    // types with type parameters mapped to their restrictive form, i.e. a form of the type parameter
16562                    // that has no constraint. This ensures that, for example, the type
16563                    //   type Foo<T extends { x: any }> = T extends { x: string } ? string : number
16564                    // doesn't immediately resolve to 'string' instead of being deferred.
16565                    if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) {
16566                        const trueType = getTypeFromTypeNode(root.node.trueType);
16567                        const trueMapper = combinedMapper || mapper;
16568                        if (canTailRecurse(trueType, trueMapper)) {
16569                            continue;
16570                        }
16571                        result = instantiateType(trueType, trueMapper);
16572                        break;
16573                    }
16574                }
16575                // Return a deferred type for a check that is neither definitely true nor definitely false
16576                result = createType(TypeFlags.Conditional) as ConditionalType;
16577                result.root = root;
16578                result.checkType = instantiateType(root.checkType, mapper);
16579                result.extendsType = instantiateType(root.extendsType, mapper);
16580                result.mapper = mapper;
16581                result.combinedMapper = combinedMapper;
16582                result.aliasSymbol = aliasSymbol || root.aliasSymbol;
16583                result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217
16584                break;
16585            }
16586            return extraTypes ? getUnionType(append(extraTypes, result)) : result;
16587            // We tail-recurse for generic conditional types that (a) have not already been evaluated and cached, and
16588            // (b) are non distributive, have a check type that is unaffected by instantiation, or have a non-union check
16589            // type. Note that recursion is possible only through aliased conditional types, so we only increment the tail
16590            // recursion counter for those.
16591            function canTailRecurse(newType: Type, newMapper: TypeMapper | undefined) {
16592                if (newType.flags & TypeFlags.Conditional && newMapper) {
16593                    const newRoot = (newType as ConditionalType).root;
16594                    if (newRoot.outerTypeParameters) {
16595                        const typeParamMapper = combineTypeMappers((newType as ConditionalType).mapper, newMapper);
16596                        const typeArguments = map(newRoot.outerTypeParameters, t => getMappedType(t, typeParamMapper));
16597                        const newRootMapper = createTypeMapper(newRoot.outerTypeParameters, typeArguments);
16598                        const newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined;
16599                        if (!newCheckType || newCheckType === newRoot.checkType || !(newCheckType.flags & (TypeFlags.Union | TypeFlags.Never))) {
16600                            root = newRoot;
16601                            mapper = newRootMapper;
16602                            aliasSymbol = undefined;
16603                            aliasTypeArguments = undefined;
16604                            if (newRoot.aliasSymbol) {
16605                                tailCount++;
16606                            }
16607                            return true;
16608                        }
16609                    }
16610                }
16611                return false;
16612            }
16613        }
16614
16615        function getTrueTypeFromConditionalType(type: ConditionalType) {
16616            return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.mapper));
16617        }
16618
16619        function getFalseTypeFromConditionalType(type: ConditionalType) {
16620            return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(getTypeFromTypeNode(type.root.node.falseType), type.mapper));
16621        }
16622
16623        function getInferredTrueTypeFromConditionalType(type: ConditionalType) {
16624            return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = type.combinedMapper ? instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.combinedMapper) : getTrueTypeFromConditionalType(type));
16625        }
16626
16627        function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined {
16628            let result: TypeParameter[] | undefined;
16629            if (node.locals) {
16630                node.locals.forEach(symbol => {
16631                    if (symbol.flags & SymbolFlags.TypeParameter) {
16632                        result = append(result, getDeclaredTypeOfSymbol(symbol));
16633                    }
16634                });
16635            }
16636            return result;
16637        }
16638
16639        function isDistributionDependent(root: ConditionalRoot) {
16640            return root.isDistributive && (
16641                isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.trueType) ||
16642                isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.falseType));
16643        }
16644
16645        function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
16646            const links = getNodeLinks(node);
16647            if (!links.resolvedType) {
16648                const checkType = getTypeFromTypeNode(node.checkType);
16649                const aliasSymbol = getAliasSymbolForTypeNode(node);
16650                const aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
16651                const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
16652                const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node));
16653                const root: ConditionalRoot = {
16654                    node,
16655                    checkType,
16656                    extendsType: getTypeFromTypeNode(node.extendsType),
16657                    isDistributive: !!(checkType.flags & TypeFlags.TypeParameter),
16658                    inferTypeParameters: getInferTypeParameters(node),
16659                    outerTypeParameters,
16660                    instantiations: undefined,
16661                    aliasSymbol,
16662                    aliasTypeArguments
16663                };
16664                links.resolvedType = getConditionalType(root, /*mapper*/ undefined);
16665                if (outerTypeParameters) {
16666                    root.instantiations = new Map<string, Type>();
16667                    root.instantiations.set(getTypeListId(outerTypeParameters), links.resolvedType);
16668                }
16669            }
16670            return links.resolvedType;
16671        }
16672
16673        function getTypeFromInferTypeNode(node: InferTypeNode): Type {
16674            const links = getNodeLinks(node);
16675            if (!links.resolvedType) {
16676                links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter));
16677            }
16678            return links.resolvedType;
16679        }
16680
16681        function getIdentifierChain(node: EntityName): Identifier[] {
16682            if (isIdentifier(node)) {
16683                return [node];
16684            }
16685            else {
16686                return append(getIdentifierChain(node.left), node.right);
16687            }
16688        }
16689
16690        function getTypeFromImportTypeNode(node: ImportTypeNode): Type {
16691            const links = getNodeLinks(node);
16692            if (!links.resolvedType) {
16693                if (node.isTypeOf && node.typeArguments) { // Only the non-typeof form can make use of type arguments
16694                    error(node, Diagnostics.Type_arguments_cannot_be_used_here);
16695                    links.resolvedSymbol = unknownSymbol;
16696                    return links.resolvedType = errorType;
16697                }
16698                if (!isLiteralImportTypeNode(node)) {
16699                    error(node.argument, Diagnostics.String_literal_expected);
16700                    links.resolvedSymbol = unknownSymbol;
16701                    return links.resolvedType = errorType;
16702                }
16703                const targetMeaning = node.isTypeOf ? SymbolFlags.Value : node.flags & NodeFlags.JSDoc ? SymbolFlags.Value | SymbolFlags.Type : SymbolFlags.Type;
16704                // TODO: Future work: support unions/generics/whatever via a deferred import-type
16705                const innerModuleSymbol = resolveExternalModuleName(node, node.argument.literal);
16706                if (!innerModuleSymbol) {
16707                    links.resolvedSymbol = unknownSymbol;
16708                    return links.resolvedType = errorType;
16709                }
16710                const isExportEquals = !!innerModuleSymbol.exports?.get(InternalSymbolName.ExportEquals);
16711                const moduleSymbol = resolveExternalModuleSymbol(innerModuleSymbol, /*dontResolveAlias*/ false);
16712                if (!nodeIsMissing(node.qualifier)) {
16713                    const nameStack: Identifier[] = getIdentifierChain(node.qualifier!);
16714                    let currentNamespace = moduleSymbol;
16715                    let current: Identifier | undefined;
16716                    while (current = nameStack.shift()) {
16717                        const meaning = nameStack.length ? SymbolFlags.Namespace : targetMeaning;
16718                        // typeof a.b.c is normally resolved using `checkExpression` which in turn defers to `checkQualifiedName`
16719                        // That, in turn, ultimately uses `getPropertyOfType` on the type of the symbol, which differs slightly from
16720                        // the `exports` lookup process that only looks up namespace members which is used for most type references
16721                        const mergedResolvedSymbol = getMergedSymbol(resolveSymbol(currentNamespace));
16722                        const symbolFromVariable = node.isTypeOf || isInJSFile(node) && isExportEquals
16723                            ? getPropertyOfType(getTypeOfSymbol(mergedResolvedSymbol), current.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ true)
16724                            : undefined;
16725                        const symbolFromModule = node.isTypeOf ? undefined : getSymbol(getExportsOfSymbol(mergedResolvedSymbol), current.escapedText, meaning);
16726                        const next = symbolFromModule ?? symbolFromVariable;
16727                        if (!next) {
16728                            error(current, Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(currentNamespace), declarationNameToString(current));
16729                            return links.resolvedType = errorType;
16730                        }
16731                        getNodeLinks(current).resolvedSymbol = next;
16732                        getNodeLinks(current.parent).resolvedSymbol = next;
16733                        currentNamespace = next;
16734                    }
16735                    links.resolvedType = resolveImportSymbolType(node, links, currentNamespace, targetMeaning);
16736                }
16737                else {
16738                    if (moduleSymbol.flags & targetMeaning) {
16739                        links.resolvedType = resolveImportSymbolType(node, links, moduleSymbol, targetMeaning);
16740                    }
16741                    else {
16742                        const errorMessage = targetMeaning === SymbolFlags.Value
16743                            ? Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here
16744                            : Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0;
16745
16746                        error(node, errorMessage, node.argument.literal.text);
16747
16748                        links.resolvedSymbol = unknownSymbol;
16749                        links.resolvedType = errorType;
16750                    }
16751                }
16752            }
16753            return links.resolvedType;
16754        }
16755
16756        function resolveImportSymbolType(node: ImportTypeNode, links: NodeLinks, symbol: Symbol, meaning: SymbolFlags) {
16757            const resolvedSymbol = resolveSymbol(symbol);
16758            links.resolvedSymbol = resolvedSymbol;
16759            if (meaning === SymbolFlags.Value) {
16760                return getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias
16761            }
16762            else {
16763                return getTypeReferenceType(node, resolvedSymbol); // getTypeReferenceType doesn't handle aliases - it must get the resolved symbol
16764            }
16765        }
16766
16767        function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type {
16768            const links = getNodeLinks(node);
16769            if (!links.resolvedType) {
16770                // Deferred resolution of members is handled by resolveObjectTypeMembers
16771                const aliasSymbol = getAliasSymbolForTypeNode(node);
16772                if (getMembersOfSymbol(node.symbol).size === 0 && !aliasSymbol) {
16773                    links.resolvedType = emptyTypeLiteralType;
16774                }
16775                else {
16776                    let type = createObjectType(ObjectFlags.Anonymous, node.symbol);
16777                    type.aliasSymbol = aliasSymbol;
16778                    type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
16779                    if (isJSDocTypeLiteral(node) && node.isArrayType) {
16780                        type = createArrayType(type);
16781                    }
16782                    links.resolvedType = type;
16783                }
16784            }
16785            return links.resolvedType;
16786        }
16787
16788        function getAliasSymbolForTypeNode(node: Node) {
16789            let host = node.parent;
16790            while (isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) {
16791                host = host.parent;
16792            }
16793            return isTypeAlias(host) ? getSymbolOfNode(host) : undefined;
16794        }
16795
16796        function getTypeArgumentsForAliasSymbol(symbol: Symbol | undefined) {
16797            return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined;
16798        }
16799
16800        function isNonGenericObjectType(type: Type) {
16801            return !!(type.flags & TypeFlags.Object) && !isGenericMappedType(type);
16802        }
16803
16804        function isEmptyObjectTypeOrSpreadsIntoEmptyObject(type: Type) {
16805            return isEmptyObjectType(type) || !!(type.flags & (TypeFlags.Null | TypeFlags.Undefined | TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index));
16806        }
16807
16808        function tryMergeUnionOfObjectTypeAndEmptyObject(type: Type, readonly: boolean): Type {
16809            if (!(type.flags & TypeFlags.Union)) {
16810                return type;
16811            }
16812            if (every((type as UnionType).types, isEmptyObjectTypeOrSpreadsIntoEmptyObject)) {
16813                return find((type as UnionType).types, isEmptyObjectType) || emptyObjectType;
16814            }
16815            const firstType = find((type as UnionType).types, t => !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t));
16816            if (!firstType) {
16817                return type;
16818            }
16819            const secondType = find((type as UnionType).types, t => t !== firstType && !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t));
16820            if (secondType) {
16821                return type;
16822            }
16823            return getAnonymousPartialType(firstType);
16824
16825            function getAnonymousPartialType(type: Type) {
16826                // gets the type as if it had been spread, but where everything in the spread is made optional
16827                const members = createSymbolTable();
16828                for (const prop of getPropertiesOfType(type)) {
16829                    if (getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) {
16830                        // do nothing, skip privates
16831                    }
16832                    else if (isSpreadableProperty(prop)) {
16833                        const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
16834                        const flags = SymbolFlags.Property | SymbolFlags.Optional;
16835                        const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0));
16836                        result.type = isSetonlyAccessor ? undefinedType : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true);
16837                        result.declarations = prop.declarations;
16838                        result.nameType = getSymbolLinks(prop).nameType;
16839                        result.syntheticOrigin = prop;
16840                        members.set(prop.escapedName, result);
16841                    }
16842                }
16843                const spread = createAnonymousType(type.symbol, members, emptyArray, emptyArray, getIndexInfosOfType(type));
16844                spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral;
16845                return spread;
16846            }
16847        }
16848
16849        /**
16850         * Since the source of spread types are object literals, which are not binary,
16851         * this function should be called in a left folding style, with left = previous result of getSpreadType
16852         * and right = the new element to be spread.
16853         */
16854        function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean): Type {
16855            if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
16856                return anyType;
16857            }
16858            if (left.flags & TypeFlags.Unknown || right.flags & TypeFlags.Unknown) {
16859                return unknownType;
16860            }
16861            if (left.flags & TypeFlags.Never) {
16862                return right;
16863            }
16864            if (right.flags & TypeFlags.Never) {
16865                return left;
16866            }
16867            left = tryMergeUnionOfObjectTypeAndEmptyObject(left, readonly);
16868            if (left.flags & TypeFlags.Union) {
16869                return checkCrossProductUnion([left, right])
16870                    ? mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly))
16871                    : errorType;
16872            }
16873            right = tryMergeUnionOfObjectTypeAndEmptyObject(right, readonly);
16874            if (right.flags & TypeFlags.Union) {
16875                return checkCrossProductUnion([left, right])
16876                    ? mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly))
16877                    : errorType;
16878            }
16879            if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) {
16880                return left;
16881            }
16882
16883            if (isGenericObjectType(left) || isGenericObjectType(right)) {
16884                if (isEmptyObjectType(left)) {
16885                    return right;
16886                }
16887                // When the left type is an intersection, we may need to merge the last constituent of the
16888                // intersection with the right type. For example when the left type is 'T & { a: string }'
16889                // and the right type is '{ b: string }' we produce 'T & { a: string, b: string }'.
16890                if (left.flags & TypeFlags.Intersection) {
16891                    const types = (left as IntersectionType).types;
16892                    const lastLeft = types[types.length - 1];
16893                    if (isNonGenericObjectType(lastLeft) && isNonGenericObjectType(right)) {
16894                        return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, objectFlags, readonly)]));
16895                    }
16896                }
16897                return getIntersectionType([left, right]);
16898            }
16899
16900            const members = createSymbolTable();
16901            const skippedPrivateMembers = new Set<__String>();
16902            const indexInfos = left === emptyObjectType ? getIndexInfosOfType(right) : getUnionIndexInfos([left, right]);
16903
16904            for (const rightProp of getPropertiesOfType(right)) {
16905                if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) {
16906                    skippedPrivateMembers.add(rightProp.escapedName);
16907                }
16908                else if (isSpreadableProperty(rightProp)) {
16909                    members.set(rightProp.escapedName, getSpreadSymbol(rightProp, readonly));
16910                }
16911            }
16912
16913            for (const leftProp of getPropertiesOfType(left)) {
16914                if (skippedPrivateMembers.has(leftProp.escapedName) || !isSpreadableProperty(leftProp)) {
16915                    continue;
16916                }
16917                if (members.has(leftProp.escapedName)) {
16918                    const rightProp = members.get(leftProp.escapedName)!;
16919                    const rightType = getTypeOfSymbol(rightProp);
16920                    if (rightProp.flags & SymbolFlags.Optional) {
16921                        const declarations = concatenate(leftProp.declarations, rightProp.declarations);
16922                        const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional);
16923                        const result = createSymbol(flags, leftProp.escapedName);
16924                        result.type = getUnionType([getTypeOfSymbol(leftProp), removeMissingOrUndefinedType(rightType)], UnionReduction.Subtype);
16925                        result.leftSpread = leftProp;
16926                        result.rightSpread = rightProp;
16927                        result.declarations = declarations;
16928                        result.nameType = getSymbolLinks(leftProp).nameType;
16929                        members.set(leftProp.escapedName, result);
16930                    }
16931                }
16932                else {
16933                    members.set(leftProp.escapedName, getSpreadSymbol(leftProp, readonly));
16934                }
16935            }
16936
16937            const spread = createAnonymousType(symbol, members, emptyArray, emptyArray, sameMap(indexInfos, info => getIndexInfoWithReadonly(info, readonly)));
16938            spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral | ObjectFlags.ContainsSpread | objectFlags;
16939            return spread;
16940        }
16941
16942        /** We approximate own properties as non-methods plus methods that are inside the object literal */
16943        function isSpreadableProperty(prop: Symbol): boolean {
16944            return !some(prop.declarations, isPrivateIdentifierClassElementDeclaration) &&
16945                (!(prop.flags & (SymbolFlags.Method | SymbolFlags.GetAccessor | SymbolFlags.SetAccessor)) ||
16946                    !prop.declarations?.some(decl => isClassLike(decl.parent)));
16947        }
16948
16949        function getSpreadSymbol(prop: Symbol, readonly: boolean) {
16950            const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
16951            if (!isSetonlyAccessor && readonly === isReadonlySymbol(prop)) {
16952                return prop;
16953            }
16954            const flags = SymbolFlags.Property | (prop.flags & SymbolFlags.Optional);
16955            const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0));
16956            result.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop);
16957            result.declarations = prop.declarations;
16958            result.nameType = getSymbolLinks(prop).nameType;
16959            result.syntheticOrigin = prop;
16960            return result;
16961        }
16962
16963        function getIndexInfoWithReadonly(info: IndexInfo, readonly: boolean) {
16964            return info.isReadonly !== readonly ? createIndexInfo(info.keyType, info.type, readonly, info.declaration) : info;
16965        }
16966
16967        function createLiteralType(flags: TypeFlags, value: string | number | PseudoBigInt, symbol?: Symbol, regularType?: LiteralType) {
16968            const type = createType(flags) as LiteralType;
16969            type.symbol = symbol!;
16970            type.value = value;
16971            type.regularType = regularType || type;
16972            return type;
16973        }
16974
16975        function getFreshTypeOfLiteralType(type: Type): Type {
16976            if (type.flags & TypeFlags.Literal) {
16977                if (!(type as LiteralType).freshType) {
16978                    const freshType = createLiteralType(type.flags, (type as LiteralType).value, (type as LiteralType).symbol, type as LiteralType);
16979                    freshType.freshType = freshType;
16980                    (type as LiteralType).freshType = freshType;
16981                }
16982                return (type as LiteralType).freshType;
16983            }
16984            return type;
16985        }
16986
16987        function getRegularTypeOfLiteralType(type: Type): Type {
16988            return type.flags & TypeFlags.Literal ? (type as LiteralType).regularType :
16989                type.flags & TypeFlags.Union ? ((type as UnionType).regularType || ((type as UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as UnionType)) :
16990                type;
16991        }
16992
16993        function isFreshLiteralType(type: Type) {
16994            return !!(type.flags & TypeFlags.Literal) && (type as LiteralType).freshType === type;
16995        }
16996
16997        function getStringLiteralType(value: string): StringLiteralType {
16998            let type;
16999            return stringLiteralTypes.get(value) ||
17000                (stringLiteralTypes.set(value, type = createLiteralType(TypeFlags.StringLiteral, value) as StringLiteralType), type);
17001        }
17002
17003        function getNumberLiteralType(value: number): NumberLiteralType {
17004            let type;
17005            return numberLiteralTypes.get(value) ||
17006                (numberLiteralTypes.set(value, type = createLiteralType(TypeFlags.NumberLiteral, value) as NumberLiteralType), type);
17007        }
17008
17009        function getBigIntLiteralType(value: PseudoBigInt): BigIntLiteralType {
17010            let type;
17011            const key = pseudoBigIntToString(value);
17012            return bigIntLiteralTypes.get(key) ||
17013                (bigIntLiteralTypes.set(key, type = createLiteralType(TypeFlags.BigIntLiteral, value) as BigIntLiteralType), type);
17014        }
17015
17016        function getEnumLiteralType(value: string | number, enumId: number, symbol: Symbol): LiteralType {
17017            let type;
17018            const qualifier = typeof value === "string" ? "@" : "#";
17019            const key = enumId + qualifier + value;
17020            const flags = TypeFlags.EnumLiteral | (typeof value === "string" ? TypeFlags.StringLiteral : TypeFlags.NumberLiteral);
17021            return enumLiteralTypes.get(key) ||
17022                (enumLiteralTypes.set(key, type = createLiteralType(flags, value, symbol)), type);
17023        }
17024
17025        function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type {
17026            if (node.literal.kind === SyntaxKind.NullKeyword) {
17027                return nullType;
17028            }
17029            const links = getNodeLinks(node);
17030            if (!links.resolvedType) {
17031                links.resolvedType = getRegularTypeOfLiteralType(checkExpression(node.literal));
17032            }
17033            return links.resolvedType;
17034        }
17035
17036        function createUniqueESSymbolType(symbol: Symbol) {
17037            const type = createType(TypeFlags.UniqueESSymbol) as UniqueESSymbolType;
17038            type.symbol = symbol;
17039            type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
17040            return type;
17041        }
17042
17043        function getESSymbolLikeTypeForNode(node: Node) {
17044            if (isValidESSymbolDeclaration(node)) {
17045                const symbol = isCommonJsExportPropertyAssignment(node) ? getSymbolOfNode((node as BinaryExpression).left) : getSymbolOfNode(node);
17046                if (symbol) {
17047                    const links = getSymbolLinks(symbol);
17048                    return links.uniqueESSymbolType || (links.uniqueESSymbolType = createUniqueESSymbolType(symbol));
17049                }
17050            }
17051            return esSymbolType;
17052        }
17053
17054        function getThisType(node: Node): Type {
17055            const container = getThisContainer(node, /*includeArrowFunctions*/ false);
17056            const parent = container && container.parent;
17057            if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) {
17058                if (!isStatic(container) &&
17059                    (!isConstructorDeclaration(container) || isNodeDescendantOf(node, container.body))) {
17060                    return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!;
17061                }
17062            }
17063
17064            // inside x.prototype = { ... }
17065            if (parent && isObjectLiteralExpression(parent) && isBinaryExpression(parent.parent) && getAssignmentDeclarationKind(parent.parent) === AssignmentDeclarationKind.Prototype) {
17066                return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent.parent.left)!.parent!).thisType!;
17067            }
17068            // /** @return {this} */
17069            // x.prototype.m = function() { ... }
17070            const host = node.flags & NodeFlags.JSDoc ? getHostSignatureFromJSDoc(node) : undefined;
17071            if (host && isFunctionExpression(host) && isBinaryExpression(host.parent) && getAssignmentDeclarationKind(host.parent) === AssignmentDeclarationKind.PrototypeProperty) {
17072                return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(host.parent.left)!.parent!).thisType!;
17073            }
17074            // inside constructor function C() { ... }
17075            if (isJSConstructor(container) && isNodeDescendantOf(node, container.body)) {
17076                return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(container)).thisType!;
17077            }
17078            error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface);
17079            return errorType;
17080        }
17081
17082        function getTypeFromThisTypeNode(node: ThisExpression | ThisTypeNode): Type {
17083            const links = getNodeLinks(node);
17084            if (!links.resolvedType) {
17085                links.resolvedType = getThisType(node);
17086            }
17087            return links.resolvedType;
17088        }
17089
17090        function getTypeFromRestTypeNode(node: RestTypeNode | NamedTupleMember) {
17091            return getTypeFromTypeNode(getArrayElementTypeNode(node.type) || node.type);
17092        }
17093
17094        function getArrayElementTypeNode(node: TypeNode): TypeNode | undefined {
17095            switch (node.kind) {
17096                case SyntaxKind.ParenthesizedType:
17097                    return getArrayElementTypeNode((node as ParenthesizedTypeNode).type);
17098                case SyntaxKind.TupleType:
17099                    if ((node as TupleTypeNode).elements.length === 1) {
17100                        node = (node as TupleTypeNode).elements[0];
17101                        if (node.kind === SyntaxKind.RestType || node.kind === SyntaxKind.NamedTupleMember && (node as NamedTupleMember).dotDotDotToken) {
17102                            return getArrayElementTypeNode((node as RestTypeNode | NamedTupleMember).type);
17103                        }
17104                    }
17105                    break;
17106                case SyntaxKind.ArrayType:
17107                    return (node as ArrayTypeNode).elementType;
17108            }
17109            return undefined;
17110        }
17111
17112        function getTypeFromNamedTupleTypeNode(node: NamedTupleMember): Type {
17113            const links = getNodeLinks(node);
17114            return links.resolvedType || (links.resolvedType =
17115                    node.dotDotDotToken ? getTypeFromRestTypeNode(node) :
17116                    addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken));
17117        }
17118
17119        function getTypeFromTypeNode(node: TypeNode): Type {
17120            return getConditionalFlowTypeOfType(getTypeFromTypeNodeWorker(node), node);
17121        }
17122
17123        function getTypeFromTypeNodeWorker(node: TypeNode): Type {
17124            switch (node.kind) {
17125                case SyntaxKind.AnyKeyword:
17126                case SyntaxKind.JSDocAllType:
17127                case SyntaxKind.JSDocUnknownType:
17128                    return anyType;
17129                case SyntaxKind.UnknownKeyword:
17130                    return unknownType;
17131                case SyntaxKind.StringKeyword:
17132                    return stringType;
17133                case SyntaxKind.NumberKeyword:
17134                    return numberType;
17135                case SyntaxKind.BigIntKeyword:
17136                    return bigintType;
17137                case SyntaxKind.BooleanKeyword:
17138                    return booleanType;
17139                case SyntaxKind.SymbolKeyword:
17140                    return esSymbolType;
17141                case SyntaxKind.VoidKeyword:
17142                    return voidType;
17143                case SyntaxKind.UndefinedKeyword:
17144                    return undefinedType;
17145                case SyntaxKind.NullKeyword as TypeNodeSyntaxKind:
17146                    // TODO(rbuckton): `NullKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service.
17147                    return nullType;
17148                case SyntaxKind.NeverKeyword:
17149                    return neverType;
17150                case SyntaxKind.ObjectKeyword:
17151                    return node.flags & NodeFlags.JavaScriptFile && !noImplicitAny ? anyType : nonPrimitiveType;
17152                case SyntaxKind.IntrinsicKeyword:
17153                    return intrinsicMarkerType;
17154                case SyntaxKind.ThisType:
17155                case SyntaxKind.ThisKeyword as TypeNodeSyntaxKind:
17156                    // TODO(rbuckton): `ThisKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service and because of `isPartOfTypeNode`.
17157                    return getTypeFromThisTypeNode(node as ThisExpression | ThisTypeNode);
17158                case SyntaxKind.LiteralType:
17159                    return getTypeFromLiteralTypeNode(node as LiteralTypeNode);
17160                case SyntaxKind.TypeReference:
17161                    return getTypeFromTypeReference(node as TypeReferenceNode);
17162                case SyntaxKind.TypePredicate:
17163                    return (node as TypePredicateNode).assertsModifier ? voidType : booleanType;
17164                case SyntaxKind.ExpressionWithTypeArguments:
17165                    return getTypeFromTypeReference(node as ExpressionWithTypeArguments);
17166                case SyntaxKind.TypeQuery:
17167                    return getTypeFromTypeQueryNode(node as TypeQueryNode);
17168                case SyntaxKind.ArrayType:
17169                case SyntaxKind.TupleType:
17170                    return getTypeFromArrayOrTupleTypeNode(node as ArrayTypeNode | TupleTypeNode);
17171                case SyntaxKind.OptionalType:
17172                    return getTypeFromOptionalTypeNode(node as OptionalTypeNode);
17173                case SyntaxKind.UnionType:
17174                    return getTypeFromUnionTypeNode(node as UnionTypeNode);
17175                case SyntaxKind.IntersectionType:
17176                    return getTypeFromIntersectionTypeNode(node as IntersectionTypeNode);
17177                case SyntaxKind.JSDocNullableType:
17178                    return getTypeFromJSDocNullableTypeNode(node as JSDocNullableType);
17179                case SyntaxKind.JSDocOptionalType:
17180                    return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type));
17181                case SyntaxKind.NamedTupleMember:
17182                    return getTypeFromNamedTupleTypeNode(node as NamedTupleMember);
17183                case SyntaxKind.ParenthesizedType:
17184                case SyntaxKind.JSDocNonNullableType:
17185                case SyntaxKind.JSDocTypeExpression:
17186                    return getTypeFromTypeNode((node as ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember).type);
17187                case SyntaxKind.RestType:
17188                    return getTypeFromRestTypeNode(node as RestTypeNode);
17189                case SyntaxKind.JSDocVariadicType:
17190                    return getTypeFromJSDocVariadicType(node as JSDocVariadicType);
17191                case SyntaxKind.FunctionType:
17192                case SyntaxKind.ConstructorType:
17193                case SyntaxKind.TypeLiteral:
17194                case SyntaxKind.JSDocTypeLiteral:
17195                case SyntaxKind.JSDocFunctionType:
17196                case SyntaxKind.JSDocSignature:
17197                    return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
17198                case SyntaxKind.TypeOperator:
17199                    return getTypeFromTypeOperatorNode(node as TypeOperatorNode);
17200                case SyntaxKind.IndexedAccessType:
17201                    return getTypeFromIndexedAccessTypeNode(node as IndexedAccessTypeNode);
17202                case SyntaxKind.MappedType:
17203                    return getTypeFromMappedTypeNode(node as MappedTypeNode);
17204                case SyntaxKind.ConditionalType:
17205                    return getTypeFromConditionalTypeNode(node as ConditionalTypeNode);
17206                case SyntaxKind.InferType:
17207                    return getTypeFromInferTypeNode(node as InferTypeNode);
17208                case SyntaxKind.TemplateLiteralType:
17209                    return getTypeFromTemplateTypeNode(node as TemplateLiteralTypeNode);
17210                case SyntaxKind.ImportType:
17211                    return getTypeFromImportTypeNode(node as ImportTypeNode);
17212                // This function assumes that an identifier, qualified name, or property access expression is a type expression
17213                // Callers should first ensure this by calling `isPartOfTypeNode`
17214                // TODO(rbuckton): These aren't valid TypeNodes, but we treat them as such because of `isPartOfTypeNode`, which returns `true` for things that aren't `TypeNode`s.
17215                case SyntaxKind.Identifier as TypeNodeSyntaxKind:
17216                case SyntaxKind.QualifiedName as TypeNodeSyntaxKind:
17217                case SyntaxKind.PropertyAccessExpression as TypeNodeSyntaxKind:
17218                    const symbol = getSymbolAtLocation(node);
17219                    return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType;
17220                default:
17221                    return errorType;
17222            }
17223        }
17224
17225        function instantiateList<T>(items: readonly T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[];
17226        function instantiateList<T>(items: readonly T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[] | undefined;
17227        function instantiateList<T>(items: readonly T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[] | undefined {
17228            if (items && items.length) {
17229                for (let i = 0; i < items.length; i++) {
17230                    const item = items[i];
17231                    const mapped = instantiator(item, mapper);
17232                    if (item !== mapped) {
17233                        const result = i === 0 ? [] : items.slice(0, i);
17234                        result.push(mapped);
17235                        for (i++; i < items.length; i++) {
17236                            result.push(instantiator(items[i], mapper));
17237                        }
17238                        return result;
17239                    }
17240                }
17241            }
17242            return items;
17243        }
17244
17245        function instantiateTypes(types: readonly Type[], mapper: TypeMapper): readonly Type[];
17246        function instantiateTypes(types: readonly Type[] | undefined, mapper: TypeMapper): readonly Type[] | undefined;
17247        function instantiateTypes(types: readonly Type[] | undefined, mapper: TypeMapper): readonly Type[] | undefined {
17248            return instantiateList<Type>(types, mapper, instantiateType);
17249        }
17250
17251        function instantiateSignatures(signatures: readonly Signature[], mapper: TypeMapper): readonly Signature[] {
17252            return instantiateList<Signature>(signatures, mapper, instantiateSignature);
17253        }
17254
17255        function instantiateIndexInfos(indexInfos: readonly IndexInfo[], mapper: TypeMapper): readonly IndexInfo[] {
17256            return instantiateList<IndexInfo>(indexInfos, mapper, instantiateIndexInfo);
17257        }
17258
17259        function createTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
17260            return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : makeArrayTypeMapper(sources, targets);
17261        }
17262
17263        function getMappedType(type: Type, mapper: TypeMapper): Type {
17264            switch (mapper.kind) {
17265                case TypeMapKind.Simple:
17266                    return type === mapper.source ? mapper.target : type;
17267                case TypeMapKind.Array: {
17268                    const sources = mapper.sources;
17269                    const targets = mapper.targets;
17270                    for (let i = 0; i < sources.length; i++) {
17271                        if (type === sources[i]) {
17272                            return targets ? targets[i] : anyType;
17273                        }
17274                    }
17275                    return type;
17276                }
17277                case TypeMapKind.Deferred: {
17278                    const sources = mapper.sources;
17279                    const targets = mapper.targets;
17280                    for (let i = 0; i < sources.length; i++) {
17281                        if (type === sources[i]) {
17282                            return targets[i]();
17283                        }
17284                    }
17285                    return type;
17286                }
17287                case TypeMapKind.Function:
17288                    return mapper.func(type);
17289                case TypeMapKind.Composite:
17290                case TypeMapKind.Merged:
17291                    const t1 = getMappedType(type, mapper.mapper1);
17292                    return t1 !== type && mapper.kind === TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) : getMappedType(t1, mapper.mapper2);
17293            }
17294        }
17295
17296        function makeUnaryTypeMapper(source: Type, target: Type): TypeMapper {
17297            return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Simple, source, target });
17298        }
17299
17300        function makeArrayTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper {
17301            return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Array, sources, targets });
17302        }
17303
17304        function makeFunctionTypeMapper(func: (t: Type) => Type, debugInfo: () => string): TypeMapper {
17305            return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Function, func, debugInfo: Debug.isDebugging ? debugInfo : undefined });
17306        }
17307
17308        function makeDeferredTypeMapper(sources: readonly TypeParameter[], targets: (() => Type)[]) {
17309            return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Deferred, sources, targets });
17310        }
17311
17312        function makeCompositeTypeMapper(kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
17313            return Debug.attachDebugPrototypeIfDebug({ kind, mapper1, mapper2 });
17314        }
17315
17316        function createTypeEraser(sources: readonly TypeParameter[]): TypeMapper {
17317            return createTypeMapper(sources, /*targets*/ undefined);
17318        }
17319
17320        /**
17321         * Maps forward-references to later types parameters to the empty object type.
17322         * This is used during inference when instantiating type parameter defaults.
17323         */
17324        function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper {
17325            const forwardInferences = context.inferences.slice(index);
17326            return createTypeMapper(map(forwardInferences, i => i.typeParameter), map(forwardInferences, () => unknownType));
17327        }
17328
17329        function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
17330            return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Composite, mapper1, mapper2) : mapper2;
17331        }
17332
17333        function mergeTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper {
17334            return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Merged, mapper1, mapper2) : mapper2;
17335        }
17336
17337        function prependTypeMapping(source: Type, target: Type, mapper: TypeMapper | undefined) {
17338            return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper);
17339        }
17340
17341        function appendTypeMapping(mapper: TypeMapper | undefined, source: Type, target: Type) {
17342            return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target));
17343        }
17344
17345        function getRestrictiveTypeParameter(tp: TypeParameter) {
17346            return !tp.constraint && !getConstraintDeclaration(tp) || tp.constraint === noConstraintType ? tp : tp.restrictiveInstantiation || (
17347                tp.restrictiveInstantiation = createTypeParameter(tp.symbol),
17348                (tp.restrictiveInstantiation as TypeParameter).constraint = noConstraintType,
17349                tp.restrictiveInstantiation
17350            );
17351        }
17352
17353        function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter {
17354            const result = createTypeParameter(typeParameter.symbol);
17355            result.target = typeParameter;
17356            return result;
17357        }
17358
17359        function instantiateTypePredicate(predicate: TypePredicate, mapper: TypeMapper): TypePredicate {
17360            return createTypePredicate(predicate.kind, predicate.parameterName, predicate.parameterIndex, instantiateType(predicate.type, mapper));
17361        }
17362
17363        function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature {
17364            let freshTypeParameters: TypeParameter[] | undefined;
17365            if (signature.typeParameters && !eraseTypeParameters) {
17366                // First create a fresh set of type parameters, then include a mapping from the old to the
17367                // new type parameters in the mapper function. Finally store this mapper in the new type
17368                // parameters such that we can use it when instantiating constraints.
17369                freshTypeParameters = map(signature.typeParameters, cloneTypeParameter);
17370                mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
17371                for (const tp of freshTypeParameters) {
17372                    tp.mapper = mapper;
17373                }
17374            }
17375            // Don't compute resolvedReturnType and resolvedTypePredicate now,
17376            // because using `mapper` now could trigger inferences to become fixed. (See `createInferenceContext`.)
17377            // See GH#17600.
17378            const result = createSignature(signature.declaration, freshTypeParameters,
17379                signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper),
17380                instantiateList(signature.parameters, mapper, instantiateSymbol),
17381                /*resolvedReturnType*/ undefined,
17382                /*resolvedTypePredicate*/ undefined,
17383                signature.minArgumentCount,
17384                signature.flags & SignatureFlags.PropagatingFlags);
17385            result.target = signature;
17386            result.mapper = mapper;
17387            return result;
17388        }
17389
17390        function instantiateSymbol(symbol: Symbol, mapper: TypeMapper): Symbol {
17391            const links = getSymbolLinks(symbol);
17392            if (links.type && !couldContainTypeVariables(links.type)) {
17393                // If the type of the symbol is already resolved, and if that type could not possibly
17394                // be affected by instantiation, simply return the symbol itself.
17395                return symbol;
17396            }
17397            if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
17398                // If symbol being instantiated is itself a instantiation, fetch the original target and combine the
17399                // type mappers. This ensures that original type identities are properly preserved and that aliases
17400                // always reference a non-aliases.
17401                symbol = links.target!;
17402                mapper = combineTypeMappers(links.mapper, mapper);
17403            }
17404            // Keep the flags from the symbol we're instantiating.  Mark that is instantiated, and
17405            // also transient so that we can just store data on it directly.
17406            const result = createSymbol(symbol.flags, symbol.escapedName, CheckFlags.Instantiated | getCheckFlags(symbol) & (CheckFlags.Readonly | CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter));
17407            result.declarations = symbol.declarations;
17408            result.parent = symbol.parent;
17409            result.target = symbol;
17410            result.mapper = mapper;
17411            if (symbol.valueDeclaration) {
17412                result.valueDeclaration = symbol.valueDeclaration;
17413            }
17414            if (links.nameType) {
17415                result.nameType = links.nameType;
17416            }
17417            return result;
17418        }
17419
17420        function getObjectTypeInstantiation(type: AnonymousType | DeferredTypeReference, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) {
17421            const declaration = type.objectFlags & ObjectFlags.Reference ? (type as TypeReference).node! :
17422                type.objectFlags & ObjectFlags.InstantiationExpressionType ? (type as InstantiationExpressionType).node :
17423                type.symbol.declarations![0];
17424            const links = getNodeLinks(declaration);
17425            const target = type.objectFlags & ObjectFlags.Reference ? links.resolvedType! as DeferredTypeReference :
17426                type.objectFlags & ObjectFlags.Instantiated ? type.target! : type;
17427            let typeParameters = links.outerTypeParameters;
17428            if (!typeParameters) {
17429                // The first time an anonymous type is instantiated we compute and store a list of the type
17430                // parameters that are in scope (and therefore potentially referenced). For type literals that
17431                // aren't the right hand side of a generic type alias declaration we optimize by reducing the
17432                // set of type parameters to those that are possibly referenced in the literal.
17433                let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true);
17434                if (isJSConstructor(declaration)) {
17435                    const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters);
17436                    outerTypeParameters = addRange(outerTypeParameters, templateTagParameters);
17437                }
17438                typeParameters = outerTypeParameters || emptyArray;
17439                const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!;
17440                typeParameters = (target.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) || target.symbol.flags & SymbolFlags.Method || target.symbol.flags & SymbolFlags.TypeLiteral) && !target.aliasTypeArguments ?
17441                    filter(typeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) :
17442                    typeParameters;
17443                links.outerTypeParameters = typeParameters;
17444            }
17445            if (typeParameters.length) {
17446                // We are instantiating an anonymous type that has one or more type parameters in scope. Apply the
17447                // mapper to the type parameters to produce the effective list of type arguments, and compute the
17448                // instantiation cache key from the type IDs of the type arguments.
17449                const combinedMapper = combineTypeMappers(type.mapper, mapper);
17450                const typeArguments = map(typeParameters, t => getMappedType(t, combinedMapper));
17451                const newAliasSymbol = aliasSymbol || type.aliasSymbol;
17452                const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper);
17453                const id = getTypeListId(typeArguments) + getAliasId(newAliasSymbol, newAliasTypeArguments);
17454                if (!target.instantiations) {
17455                    target.instantiations = new Map<string, Type>();
17456                    target.instantiations.set(getTypeListId(typeParameters) + getAliasId(target.aliasSymbol, target.aliasTypeArguments), target);
17457                }
17458                let result = target.instantiations.get(id);
17459                if (!result) {
17460                    const newMapper = createTypeMapper(typeParameters, typeArguments);
17461                    result = target.objectFlags & ObjectFlags.Reference ? createDeferredTypeReference((type as DeferredTypeReference).target, (type as DeferredTypeReference).node, newMapper, newAliasSymbol, newAliasTypeArguments) :
17462                        target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(target as MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) :
17463                        instantiateAnonymousType(target, newMapper, newAliasSymbol, newAliasTypeArguments);
17464                    target.instantiations.set(id, result);
17465                }
17466                return result;
17467            }
17468            return type;
17469        }
17470
17471        function maybeTypeParameterReference(node: Node) {
17472            return !(node.parent.kind === SyntaxKind.TypeReference && (node.parent as TypeReferenceNode).typeArguments && node === (node.parent as TypeReferenceNode).typeName ||
17473                node.parent.kind === SyntaxKind.ImportType && (node.parent as ImportTypeNode).typeArguments && node === (node.parent as ImportTypeNode).qualifier);
17474        }
17475
17476        function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node) {
17477            // If the type parameter doesn't have exactly one declaration, if there are intervening statement blocks
17478            // between the node and the type parameter declaration, if the node contains actual references to the
17479            // type parameter, or if the node contains type queries that we can't prove couldn't contain references to the type parameter,
17480            // we consider the type parameter possibly referenced.
17481            if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) {
17482                const container = tp.symbol.declarations[0].parent;
17483                for (let n = node; n !== container; n = n.parent) {
17484                    if (!n || n.kind === SyntaxKind.Block || n.kind === SyntaxKind.ConditionalType && forEachChild((n as ConditionalTypeNode).extendsType, containsReference)) {
17485                        return true;
17486                    }
17487                }
17488                return containsReference(node);
17489            }
17490            return true;
17491            function containsReference(node: Node): boolean {
17492                switch (node.kind) {
17493                    case SyntaxKind.ThisType:
17494                        return !!tp.isThisType;
17495                    case SyntaxKind.Identifier:
17496                        return !tp.isThisType && isPartOfTypeNode(node) && maybeTypeParameterReference(node) &&
17497                            getTypeFromTypeNodeWorker(node as TypeNode) === tp; // use worker because we're looking for === equality
17498                    case SyntaxKind.TypeQuery:
17499                        const entityName = (node as TypeQueryNode).exprName;
17500                        const firstIdentifier = getFirstIdentifier(entityName);
17501                        const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier);
17502                        const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called
17503                        let tpScope: Node;
17504                        if (tpDeclaration.kind === SyntaxKind.TypeParameter) { // Type parameter is a regular type parameter, e.g. foo<T>
17505                            tpScope = tpDeclaration.parent;
17506                        }
17507                        else if (tp.isThisType) {
17508                             // Type parameter is the this type, and its declaration is the class declaration.
17509                            tpScope = tpDeclaration;
17510                        }
17511                        else {
17512                            // Type parameter's declaration was unrecognized.
17513                            // This could happen if the type parameter comes from e.g. a JSDoc annotation, so we default to returning true.
17514                            return true;
17515                        }
17516
17517                        if (firstIdentifierSymbol.declarations) {
17518                            return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) ||
17519                                some((node as TypeQueryNode).typeArguments, containsReference);
17520                        }
17521                        return true;
17522                    case SyntaxKind.MethodDeclaration:
17523                    case SyntaxKind.MethodSignature:
17524                        return !(node as FunctionLikeDeclaration).type && !!(node as FunctionLikeDeclaration).body ||
17525                            some((node as FunctionLikeDeclaration).typeParameters, containsReference) ||
17526                            some((node as FunctionLikeDeclaration).parameters, containsReference) ||
17527                            !!(node as FunctionLikeDeclaration).type && containsReference((node as FunctionLikeDeclaration).type!);
17528                }
17529                return !!forEachChild(node, containsReference);
17530            }
17531        }
17532
17533        function getHomomorphicTypeVariable(type: MappedType) {
17534            const constraintType = getConstraintTypeFromMappedType(type);
17535            if (constraintType.flags & TypeFlags.Index) {
17536                const typeVariable = getActualTypeVariable((constraintType as IndexType).type);
17537                if (typeVariable.flags & TypeFlags.TypeParameter) {
17538                    return typeVariable as TypeParameter;
17539                }
17540            }
17541            return undefined;
17542        }
17543
17544        function instantiateMappedType(type: MappedType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
17545            // For a homomorphic mapped type { [P in keyof T]: X }, where T is some type variable, the mapping
17546            // operation depends on T as follows:
17547            // * If T is a primitive type no mapping is performed and the result is simply T.
17548            // * If T is a union type we distribute the mapped type over the union.
17549            // * If T is an array we map to an array where the element type has been transformed.
17550            // * If T is a tuple we map to a tuple where the element types have been transformed.
17551            // * Otherwise we map to an object type where the type of each property has been transformed.
17552            // For example, when T is instantiated to a union type A | B, we produce { [P in keyof A]: X } |
17553            // { [P in keyof B]: X }, and when when T is instantiated to a union type A | undefined, we produce
17554            // { [P in keyof A]: X } | undefined.
17555            const typeVariable = getHomomorphicTypeVariable(type);
17556            if (typeVariable) {
17557                const mappedTypeVariable = instantiateType(typeVariable, mapper);
17558                if (typeVariable !== mappedTypeVariable) {
17559                    return mapTypeWithAlias(getReducedType(mappedTypeVariable), t => {
17560                        if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) {
17561                            if (!type.declaration.nameType) {
17562                                let constraint;
17563                                if (isArrayType(t) || t.flags & TypeFlags.Any && findResolutionCycleStartIndex(typeVariable, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 &&
17564                                    (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) {
17565                                    return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper));
17566                                }
17567                                if (isGenericTupleType(t)) {
17568                                    return instantiateMappedGenericTupleType(t, type, typeVariable, mapper);
17569                                }
17570                                if (isTupleType(t)) {
17571                                    return instantiateMappedTupleType(t, type, prependTypeMapping(typeVariable, t, mapper));
17572                                }
17573                            }
17574                            return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper));
17575                        }
17576                        return t;
17577                    }, aliasSymbol, aliasTypeArguments);
17578                }
17579            }
17580            // If the constraint type of the instantiation is the wildcard type, return the wildcard type.
17581            return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments);
17582        }
17583
17584        function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) {
17585            return modifiers & MappedTypeModifiers.IncludeReadonly ? true : modifiers & MappedTypeModifiers.ExcludeReadonly ? false : state;
17586        }
17587
17588        function instantiateMappedGenericTupleType(tupleType: TupleTypeReference, mappedType: MappedType, typeVariable: TypeVariable, mapper: TypeMapper) {
17589            // When a tuple type is generic (i.e. when it contains variadic elements), we want to eagerly map the
17590            // non-generic elements and defer mapping the generic elements. In order to facilitate this, we transform
17591            // M<[A, B?, ...T, ...C[]] into [...M<[A]>, ...M<[B?]>, ...M<T>, ...M<C[]>] and then rely on tuple type
17592            // normalization to resolve the non-generic parts of the resulting tuple.
17593            const elementFlags = tupleType.target.elementFlags;
17594            const elementTypes = map(getTypeArguments(tupleType), (t, i) => {
17595                const singleton = elementFlags[i] & ElementFlags.Variadic ? t :
17596                    elementFlags[i] & ElementFlags.Rest ? createArrayType(t) :
17597                    createTupleType([t], [elementFlags[i]]);
17598                // The singleton is never a generic tuple type, so it is safe to recurse here.
17599                return instantiateMappedType(mappedType, prependTypeMapping(typeVariable, singleton, mapper));
17600            });
17601            const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, getMappedTypeModifiers(mappedType));
17602            return createTupleType(elementTypes, map(elementTypes, _ => ElementFlags.Variadic), newReadonly);
17603        }
17604
17605        function instantiateMappedArrayType(arrayType: Type, mappedType: MappedType, mapper: TypeMapper) {
17606            const elementType = instantiateMappedTypeTemplate(mappedType, numberType, /*isOptional*/ true, mapper);
17607            return isErrorType(elementType) ? errorType :
17608                createArrayType(elementType, getModifiedReadonlyState(isReadonlyArrayType(arrayType), getMappedTypeModifiers(mappedType)));
17609        }
17610
17611        function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) {
17612            const elementFlags = tupleType.target.elementFlags;
17613            const elementTypes = map(getTypeArguments(tupleType), (_, i) =>
17614                instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(elementFlags[i] & ElementFlags.Optional), mapper));
17615            const modifiers = getMappedTypeModifiers(mappedType);
17616            const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) :
17617                modifiers & MappedTypeModifiers.ExcludeOptional ? map(elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) :
17618                elementFlags;
17619            const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
17620            return contains(elementTypes, errorType) ? errorType :
17621                createTupleType(elementTypes, newTupleModifiers, newReadonly, tupleType.target.labeledElementDeclarations);
17622        }
17623
17624        function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
17625            const templateMapper = appendTypeMapping(mapper, getTypeParameterFromMappedType(type), key);
17626            const propType = instantiateType(getTemplateTypeFromMappedType(type.target as MappedType || type), templateMapper);
17627            const modifiers = getMappedTypeModifiers(type);
17628            return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) :
17629                strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
17630                propType;
17631        }
17632
17633        function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): AnonymousType {
17634            const result = createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol) as AnonymousType;
17635            if (type.objectFlags & ObjectFlags.Mapped) {
17636                (result as MappedType).declaration = (type as MappedType).declaration;
17637                // C.f. instantiateSignature
17638                const origTypeParameter = getTypeParameterFromMappedType(type as MappedType);
17639                const freshTypeParameter = cloneTypeParameter(origTypeParameter);
17640                (result as MappedType).typeParameter = freshTypeParameter;
17641                mapper = combineTypeMappers(makeUnaryTypeMapper(origTypeParameter, freshTypeParameter), mapper);
17642                freshTypeParameter.mapper = mapper;
17643            }
17644            if (type.objectFlags & ObjectFlags.InstantiationExpressionType) {
17645                (result as InstantiationExpressionType).node = (type as InstantiationExpressionType).node;
17646            }
17647            result.target = type;
17648            result.mapper = mapper;
17649            result.aliasSymbol = aliasSymbol || type.aliasSymbol;
17650            result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper);
17651            result.objectFlags |= result.aliasTypeArguments ? getPropagatingFlagsOfTypes(result.aliasTypeArguments) : 0;
17652            return result;
17653        }
17654
17655        function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
17656            const root = type.root;
17657            if (root.outerTypeParameters) {
17658                // We are instantiating a conditional type that has one or more type parameters in scope. Apply the
17659                // mapper to the type parameters to produce the effective list of type arguments, and compute the
17660                // instantiation cache key from the type IDs of the type arguments.
17661                const typeArguments = map(root.outerTypeParameters, t => getMappedType(t, mapper));
17662                const id = getTypeListId(typeArguments) + getAliasId(aliasSymbol, aliasTypeArguments);
17663                let result = root.instantiations!.get(id);
17664                if (!result) {
17665                    const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
17666                    const checkType = root.checkType;
17667                    const distributionType = root.isDistributive ? getMappedType(checkType, newMapper) : undefined;
17668                    // Distributive conditional types are distributed over union types. For example, when the
17669                    // distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
17670                    // result is (A extends U ? X : Y) | (B extends U ? X : Y).
17671                    result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
17672                        mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
17673                        getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
17674                    root.instantiations!.set(id, result);
17675                }
17676                return result;
17677            }
17678            return type;
17679        }
17680
17681        function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
17682        function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
17683        function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
17684            return type && mapper ? instantiateTypeWithAlias(type, mapper, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined) : type;
17685        }
17686
17687        function instantiateTypeWithAlias(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type {
17688            if (!couldContainTypeVariables(type)) {
17689                return type;
17690            }
17691            if (instantiationDepth === 100 || instantiationCount >= 5000000) {
17692                // We have reached 100 recursive type instantiations, or 5M type instantiations caused by the same statement
17693                // or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types
17694                // that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
17695                tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount });
17696                error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
17697                return errorType;
17698            }
17699            totalInstantiationCount++;
17700            instantiationCount++;
17701            instantiationDepth++;
17702            const result = instantiateTypeWorker(type, mapper, aliasSymbol, aliasTypeArguments);
17703            instantiationDepth--;
17704            return result;
17705        }
17706
17707        function instantiateTypeWorker(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type {
17708            const flags = type.flags;
17709            if (flags & TypeFlags.TypeParameter) {
17710                return getMappedType(type, mapper);
17711            }
17712            if (flags & TypeFlags.Object) {
17713                const objectFlags = (type as ObjectType).objectFlags;
17714                if (objectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous | ObjectFlags.Mapped)) {
17715                    if (objectFlags & ObjectFlags.Reference && !(type as TypeReference).node) {
17716                        const resolvedTypeArguments = (type as TypeReference).resolvedTypeArguments;
17717                        const newTypeArguments = instantiateTypes(resolvedTypeArguments, mapper);
17718                        return newTypeArguments !== resolvedTypeArguments ? createNormalizedTypeReference((type as TypeReference).target, newTypeArguments) : type;
17719                    }
17720                    if (objectFlags & ObjectFlags.ReverseMapped) {
17721                        return instantiateReverseMappedType(type as ReverseMappedType, mapper);
17722                    }
17723                    return getObjectTypeInstantiation(type as TypeReference | AnonymousType | MappedType, mapper, aliasSymbol, aliasTypeArguments);
17724                }
17725                return type;
17726            }
17727            if (flags & TypeFlags.UnionOrIntersection) {
17728                const origin = type.flags & TypeFlags.Union ? (type as UnionType).origin : undefined;
17729                const types = origin && origin.flags & TypeFlags.UnionOrIntersection ? (origin as UnionOrIntersectionType).types : (type as UnionOrIntersectionType).types;
17730                const newTypes = instantiateTypes(types, mapper);
17731                if (newTypes === types && aliasSymbol === type.aliasSymbol) {
17732                    return type;
17733                }
17734                const newAliasSymbol = aliasSymbol || type.aliasSymbol;
17735                const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper);
17736                return flags & TypeFlags.Intersection || origin && origin.flags & TypeFlags.Intersection ?
17737                    getIntersectionType(newTypes, newAliasSymbol, newAliasTypeArguments) :
17738                    getUnionType(newTypes, UnionReduction.Literal, newAliasSymbol, newAliasTypeArguments);
17739            }
17740            if (flags & TypeFlags.Index) {
17741                return getIndexType(instantiateType((type as IndexType).type, mapper));
17742            }
17743            if (flags & TypeFlags.TemplateLiteral) {
17744                return getTemplateLiteralType((type as TemplateLiteralType).texts, instantiateTypes((type as TemplateLiteralType).types, mapper));
17745            }
17746            if (flags & TypeFlags.StringMapping) {
17747                return getStringMappingType((type as StringMappingType).symbol, instantiateType((type as StringMappingType).type, mapper));
17748            }
17749            if (flags & TypeFlags.IndexedAccess) {
17750                const newAliasSymbol = aliasSymbol || type.aliasSymbol;
17751                const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper);
17752                return getIndexedAccessType(instantiateType((type as IndexedAccessType).objectType, mapper), instantiateType((type as IndexedAccessType).indexType, mapper), (type as IndexedAccessType).accessFlags, /*accessNode*/ undefined, newAliasSymbol, newAliasTypeArguments);
17753            }
17754            if (flags & TypeFlags.Conditional) {
17755                return getConditionalTypeInstantiation(type as ConditionalType, combineTypeMappers((type as ConditionalType).mapper, mapper), aliasSymbol, aliasTypeArguments);
17756            }
17757            if (flags & TypeFlags.Substitution) {
17758                const newBaseType = instantiateType((type as SubstitutionType).baseType, mapper);
17759                const newConstraint = instantiateType((type as SubstitutionType).constraint, mapper);
17760                // A substitution type originates in the true branch of a conditional type and can be resolved
17761                // to just the base type in the same cases as the conditional type resolves to its true branch
17762                // (because the base type is then known to satisfy the constraint).
17763                if (newBaseType.flags & TypeFlags.TypeVariable && isGenericType(newConstraint)) {
17764                    return getSubstitutionType(newBaseType, newConstraint);
17765                }
17766                if (newConstraint.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(newBaseType), getRestrictiveInstantiation(newConstraint))) {
17767                    return newBaseType;
17768                }
17769                return newBaseType.flags & TypeFlags.TypeVariable ? getSubstitutionType(newBaseType, newConstraint) : getIntersectionType([newConstraint, newBaseType]);
17770            }
17771            return type;
17772        }
17773
17774        function instantiateReverseMappedType(type: ReverseMappedType, mapper: TypeMapper) {
17775            const innerMappedType = instantiateType(type.mappedType, mapper);
17776            if (!(getObjectFlags(innerMappedType) & ObjectFlags.Mapped)) {
17777                return type;
17778            }
17779            const innerIndexType = instantiateType(type.constraintType, mapper);
17780            if (!(innerIndexType.flags & TypeFlags.Index)) {
17781                return type;
17782            }
17783            const instantiated = inferTypeForHomomorphicMappedType(
17784                instantiateType(type.source, mapper),
17785                innerMappedType as MappedType,
17786                innerIndexType as IndexType
17787            );
17788            if (instantiated) {
17789                return instantiated;
17790            }
17791            return type; // Nested invocation of `inferTypeForHomomorphicMappedType` or the `source` instantiated into something unmappable
17792        }
17793
17794        function getUniqueLiteralFilledInstantiation(type: Type) {
17795            return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type :
17796                type.uniqueLiteralFilledInstantiation || (type.uniqueLiteralFilledInstantiation = instantiateType(type, uniqueLiteralMapper));
17797        }
17798
17799        function getPermissiveInstantiation(type: Type) {
17800            return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type :
17801                type.permissiveInstantiation || (type.permissiveInstantiation = instantiateType(type, permissiveMapper));
17802        }
17803
17804        function getRestrictiveInstantiation(type: Type) {
17805            if (type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never)) {
17806                return type;
17807            }
17808            if (type.restrictiveInstantiation) {
17809                return type.restrictiveInstantiation;
17810            }
17811            type.restrictiveInstantiation = instantiateType(type, restrictiveMapper);
17812            // We set the following so we don't attempt to set the restrictive instance of a restrictive instance
17813            // which is redundant - we'll produce new type identities, but all type params have already been mapped.
17814            // This also gives us a way to detect restrictive instances upon comparisons and _disable_ the "distributeive constraint"
17815            // assignability check for them, which is distinctly unsafe, as once you have a restrctive instance, all the type parameters
17816            // are constrained to `unknown` and produce tons of false positives/negatives!
17817            type.restrictiveInstantiation.restrictiveInstantiation = type.restrictiveInstantiation;
17818            return type.restrictiveInstantiation;
17819        }
17820
17821        function instantiateIndexInfo(info: IndexInfo, mapper: TypeMapper) {
17822            return createIndexInfo(info.keyType, instantiateType(info.type, mapper), info.isReadonly, info.declaration);
17823        }
17824
17825        // Returns true if the given expression contains (at any level of nesting) a function or arrow expression
17826        // that is subject to contextual typing.
17827        function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean {
17828            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
17829            switch (node.kind) {
17830                case SyntaxKind.FunctionExpression:
17831                case SyntaxKind.ArrowFunction:
17832                case SyntaxKind.MethodDeclaration:
17833                case SyntaxKind.FunctionDeclaration: // Function declarations can have context when annotated with a jsdoc @type
17834                    return isContextSensitiveFunctionLikeDeclaration(node as FunctionExpression | ArrowFunction | MethodDeclaration);
17835                case SyntaxKind.ObjectLiteralExpression:
17836                    return some((node as ObjectLiteralExpression).properties, isContextSensitive);
17837                case SyntaxKind.ArrayLiteralExpression:
17838                    return some((node as ArrayLiteralExpression).elements, isContextSensitive);
17839                case SyntaxKind.ConditionalExpression:
17840                    return isContextSensitive((node as ConditionalExpression).whenTrue) ||
17841                        isContextSensitive((node as ConditionalExpression).whenFalse);
17842                case SyntaxKind.BinaryExpression:
17843                    return ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken || (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken) &&
17844                        (isContextSensitive((node as BinaryExpression).left) || isContextSensitive((node as BinaryExpression).right));
17845                case SyntaxKind.PropertyAssignment:
17846                    return isContextSensitive((node as PropertyAssignment).initializer);
17847                case SyntaxKind.ParenthesizedExpression:
17848                    return isContextSensitive((node as ParenthesizedExpression).expression);
17849                case SyntaxKind.JsxAttributes:
17850                    return some((node as JsxAttributes).properties, isContextSensitive) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, isContextSensitive);
17851                case SyntaxKind.JsxAttribute: {
17852                    // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive.
17853                    const { initializer } = node as JsxAttribute;
17854                    return !!initializer && isContextSensitive(initializer);
17855                }
17856                case SyntaxKind.JsxExpression: {
17857                    // It is possible to that node.expression is undefined (e.g <div x={} />)
17858                    const { expression } = node as JsxExpression;
17859                    return !!expression && isContextSensitive(expression);
17860                }
17861            }
17862
17863            return false;
17864        }
17865
17866        function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
17867            return hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node);
17868        }
17869
17870        function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) {
17871            // TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value.
17872            return !node.typeParameters && !getEffectiveReturnTypeNode(node) && !!node.body && node.body.kind !== SyntaxKind.Block && isContextSensitive(node.body);
17873        }
17874
17875        function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
17876            return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) &&
17877                isContextSensitiveFunctionLikeDeclaration(func);
17878        }
17879
17880        function getTypeWithoutSignatures(type: Type): Type {
17881            if (type.flags & TypeFlags.Object) {
17882                const resolved = resolveStructuredTypeMembers(type as ObjectType);
17883                if (resolved.constructSignatures.length || resolved.callSignatures.length) {
17884                    const result = createObjectType(ObjectFlags.Anonymous, type.symbol);
17885                    result.members = resolved.members;
17886                    result.properties = resolved.properties;
17887                    result.callSignatures = emptyArray;
17888                    result.constructSignatures = emptyArray;
17889                    result.indexInfos = emptyArray;
17890                    return result;
17891                }
17892            }
17893            else if (type.flags & TypeFlags.Intersection) {
17894                return getIntersectionType(map((type as IntersectionType).types, getTypeWithoutSignatures));
17895            }
17896            return type;
17897        }
17898
17899        // TYPE CHECKING
17900
17901        function isTypeIdenticalTo(source: Type, target: Type): boolean {
17902            return isTypeRelatedTo(source, target, identityRelation);
17903        }
17904
17905        function compareTypesIdentical(source: Type, target: Type): Ternary {
17906            return isTypeRelatedTo(source, target, identityRelation) ? Ternary.True : Ternary.False;
17907        }
17908
17909        function compareTypesAssignable(source: Type, target: Type): Ternary {
17910            return isTypeRelatedTo(source, target, assignableRelation) ? Ternary.True : Ternary.False;
17911        }
17912
17913        function compareTypesSubtypeOf(source: Type, target: Type): Ternary {
17914            return isTypeRelatedTo(source, target, subtypeRelation) ? Ternary.True : Ternary.False;
17915        }
17916
17917        function isTypeSubtypeOf(source: Type, target: Type): boolean {
17918            return isTypeRelatedTo(source, target, subtypeRelation);
17919        }
17920
17921        function isTypeAssignableTo(source: Type, target: Type): boolean {
17922            return isTypeRelatedTo(source, target, assignableRelation);
17923        }
17924
17925        // An object type S is considered to be derived from an object type T if
17926        // S is a union type and every constituent of S is derived from T,
17927        // T is a union type and S is derived from at least one constituent of T, or
17928        // S is a type variable with a base constraint that is derived from T,
17929        // T is one of the global types Object and Function and S is a subtype of T, or
17930        // T occurs directly or indirectly in an 'extends' clause of S.
17931        // Note that this check ignores type parameters and only considers the
17932        // inheritance hierarchy.
17933        function isTypeDerivedFrom(source: Type, target: Type): boolean {
17934            return source.flags & TypeFlags.Union ? every((source as UnionType).types, t => isTypeDerivedFrom(t, target)) :
17935                target.flags & TypeFlags.Union ? some((target as UnionType).types, t => isTypeDerivedFrom(source, t)) :
17936                source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) :
17937                target === globalObjectType ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) :
17938                target === globalFunctionType ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) :
17939                hasBaseType(source, getTargetType(target)) || (isArrayType(target) && !isReadonlyArrayType(target) && isTypeDerivedFrom(source, globalReadonlyArrayType));
17940        }
17941
17942        /**
17943         * This is *not* a bi-directional relationship.
17944         * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
17945         *
17946         * A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T.
17947         * It is used to check following cases:
17948         *   - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`).
17949         *   - the types of `case` clause expressions and their respective `switch` expressions.
17950         *   - the type of an expression in a type assertion with the type being asserted.
17951         */
17952        function isTypeComparableTo(source: Type, target: Type): boolean {
17953            return isTypeRelatedTo(source, target, comparableRelation);
17954        }
17955
17956        function areTypesComparable(type1: Type, type2: Type): boolean {
17957            return isTypeComparableTo(type1, type2) || isTypeComparableTo(type2, type1);
17958        }
17959
17960        function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined, errorOutputObject?: { errors?: Diagnostic[] }): boolean {
17961            return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain, errorOutputObject);
17962        }
17963
17964        /**
17965         * Like `checkTypeAssignableTo`, but if it would issue an error, instead performs structural comparisons of the types using the given expression node to
17966         * attempt to issue more specific errors on, for example, specific object literal properties or tuple members.
17967         */
17968        function checkTypeAssignableToAndOptionallyElaborate(source: Type, target: Type, errorNode: Node | undefined, expr: Expression | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean {
17969            return checkTypeRelatedToAndOptionallyElaborate(source, target, assignableRelation, errorNode, expr, headMessage, containingMessageChain, /*errorOutputContainer*/ undefined);
17970        }
17971
17972        function checkTypeRelatedToAndOptionallyElaborate(
17973            source: Type,
17974            target: Type,
17975            relation: ESMap<string, RelationComparisonResult>,
17976            errorNode: Node | undefined,
17977            expr: Expression | undefined,
17978            headMessage: DiagnosticMessage | undefined,
17979            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
17980            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
17981        ): boolean {
17982            if (isTypeRelatedTo(source, target, relation)) return true;
17983            if (!errorNode || !elaborateError(expr, source, target, relation, headMessage, containingMessageChain, errorOutputContainer)) {
17984                return checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer);
17985            }
17986            return false;
17987        }
17988
17989        function isOrHasGenericConditional(type: Type): boolean {
17990            return !!(type.flags & TypeFlags.Conditional || (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isOrHasGenericConditional)));
17991        }
17992
17993        function elaborateError(
17994            node: Expression | undefined,
17995            source: Type,
17996            target: Type,
17997            relation: ESMap<string, RelationComparisonResult>,
17998            headMessage: DiagnosticMessage | undefined,
17999            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18000            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18001        ): boolean {
18002            if (!node || isOrHasGenericConditional(target)) return false;
18003            if (!checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined)
18004                && elaborateDidYouMeanToCallOrConstruct(node, source, target, relation, headMessage, containingMessageChain, errorOutputContainer)) {
18005                return true;
18006            }
18007            switch (node.kind) {
18008                case SyntaxKind.JsxExpression:
18009                case SyntaxKind.ParenthesizedExpression:
18010                    return elaborateError((node as ParenthesizedExpression | JsxExpression).expression, source, target, relation, headMessage, containingMessageChain, errorOutputContainer);
18011                case SyntaxKind.BinaryExpression:
18012                    switch ((node as BinaryExpression).operatorToken.kind) {
18013                        case SyntaxKind.EqualsToken:
18014                        case SyntaxKind.CommaToken:
18015                            return elaborateError((node as BinaryExpression).right, source, target, relation, headMessage, containingMessageChain, errorOutputContainer);
18016                    }
18017                    break;
18018                case SyntaxKind.ObjectLiteralExpression:
18019                    return elaborateObjectLiteral(node as ObjectLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer);
18020                case SyntaxKind.ArrayLiteralExpression:
18021                    return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer);
18022                case SyntaxKind.JsxAttributes:
18023                    return elaborateJsxComponents(node as JsxAttributes, source, target, relation, containingMessageChain, errorOutputContainer);
18024                case SyntaxKind.ArrowFunction:
18025                    return elaborateArrowFunction(node as ArrowFunction, source, target, relation, containingMessageChain, errorOutputContainer);
18026            }
18027            return false;
18028        }
18029
18030        function elaborateDidYouMeanToCallOrConstruct(
18031            node: Expression,
18032            source: Type,
18033            target: Type,
18034            relation: ESMap<string, RelationComparisonResult>,
18035            headMessage: DiagnosticMessage | undefined,
18036            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18037            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18038        ): boolean {
18039            const callSignatures = getSignaturesOfType(source, SignatureKind.Call);
18040            const constructSignatures = getSignaturesOfType(source, SignatureKind.Construct);
18041            for (const signatures of [constructSignatures, callSignatures]) {
18042                if (some(signatures, s => {
18043                    const returnType = getReturnTypeOfSignature(s);
18044                    return !(returnType.flags & (TypeFlags.Any | TypeFlags.Never)) && checkTypeRelatedTo(returnType, target, relation, /*errorNode*/ undefined);
18045                })) {
18046                    const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {};
18047                    checkTypeAssignableTo(source, target, node, headMessage, containingMessageChain, resultObj);
18048                    const diagnostic = resultObj.errors![resultObj.errors!.length - 1];
18049                    addRelatedInfo(diagnostic, createDiagnosticForNode(
18050                        node,
18051                        signatures === constructSignatures ? Diagnostics.Did_you_mean_to_use_new_with_this_expression : Diagnostics.Did_you_mean_to_call_this_expression
18052                    ));
18053                    return true;
18054                }
18055            }
18056            return false;
18057        }
18058
18059        function elaborateArrowFunction(
18060            node: ArrowFunction,
18061            source: Type,
18062            target: Type,
18063            relation: ESMap<string, RelationComparisonResult>,
18064            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18065            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18066        ): boolean {
18067            // Don't elaborate blocks
18068            if (isBlock(node.body)) {
18069                return false;
18070            }
18071            // Or functions with annotated parameter types
18072            if (some(node.parameters, ts.hasType)) {
18073                return false;
18074            }
18075            const sourceSig = getSingleCallSignature(source);
18076            if (!sourceSig) {
18077                return false;
18078            }
18079            const targetSignatures = getSignaturesOfType(target, SignatureKind.Call);
18080            if (!length(targetSignatures)) {
18081                return false;
18082            }
18083            const returnExpression = node.body;
18084            const sourceReturn = getReturnTypeOfSignature(sourceSig);
18085            const targetReturn = getUnionType(map(targetSignatures, getReturnTypeOfSignature));
18086            if (!checkTypeRelatedTo(sourceReturn, targetReturn, relation, /*errorNode*/ undefined)) {
18087                const elaborated = returnExpression && elaborateError(returnExpression, sourceReturn, targetReturn, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer);
18088                if (elaborated) {
18089                    return elaborated;
18090                }
18091                const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {};
18092                checkTypeRelatedTo(sourceReturn, targetReturn, relation, returnExpression, /*message*/ undefined, containingMessageChain, resultObj);
18093                if (resultObj.errors) {
18094                    if (target.symbol && length(target.symbol.declarations)) {
18095                        addRelatedInfo(resultObj.errors[resultObj.errors.length - 1], createDiagnosticForNode(
18096                            target.symbol.declarations![0],
18097                            Diagnostics.The_expected_type_comes_from_the_return_type_of_this_signature,
18098                        ));
18099                    }
18100                    if ((getFunctionFlags(node) & FunctionFlags.Async) === 0
18101                        // exclude cases where source itself is promisy - this way we don't make a suggestion when relating
18102                        // an IPromise and a Promise that are slightly different
18103                        && !getTypeOfPropertyOfType(sourceReturn, "then" as __String)
18104                        && checkTypeRelatedTo(createPromiseType(sourceReturn), targetReturn, relation, /*errorNode*/ undefined)
18105                    ) {
18106                        addRelatedInfo(resultObj.errors[resultObj.errors.length - 1], createDiagnosticForNode(
18107                            node,
18108                            Diagnostics.Did_you_mean_to_mark_this_function_as_async
18109                        ));
18110                    }
18111                    return true;
18112                }
18113            }
18114            return false;
18115        }
18116
18117        function getBestMatchIndexedAccessTypeOrUndefined(source: Type, target: Type, nameType: Type) {
18118            const idx = getIndexedAccessTypeOrUndefined(target, nameType);
18119            if (idx) {
18120                return idx;
18121            }
18122            if (target.flags & TypeFlags.Union) {
18123                const best = getBestMatchingType(source, target as UnionType);
18124                if (best) {
18125                    return getIndexedAccessTypeOrUndefined(best, nameType);
18126                }
18127            }
18128        }
18129
18130        function checkExpressionForMutableLocationWithContextualType(next: Expression, sourcePropType: Type) {
18131            next.contextualType = sourcePropType;
18132            try {
18133                return checkExpressionForMutableLocation(next, CheckMode.Contextual, sourcePropType);
18134            }
18135            finally {
18136                next.contextualType = undefined;
18137            }
18138        }
18139
18140        type ElaborationIterator = IterableIterator<{ errorNode: Node, innerExpression: Expression | undefined, nameType: Type, errorMessage?: DiagnosticMessage | undefined }>;
18141        /**
18142         * For every element returned from the iterator, checks that element to issue an error on a property of that element's type
18143         * If that element would issue an error, we first attempt to dive into that element's inner expression and issue a more specific error by recuring into `elaborateError`
18144         * Otherwise, we issue an error on _every_ element which fail the assignability check
18145         */
18146        function elaborateElementwise(
18147            iterator: ElaborationIterator,
18148            source: Type,
18149            target: Type,
18150            relation: ESMap<string, RelationComparisonResult>,
18151            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18152            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18153        ) {
18154            // Assignability failure - check each prop individually, and if that fails, fall back on the bad error span
18155            let reportedError = false;
18156            for (let status = iterator.next(); !status.done; status = iterator.next()) {
18157                const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value;
18158                let targetPropType = getBestMatchIndexedAccessTypeOrUndefined(source, target, nameType);
18159                if (!targetPropType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables
18160                let sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType);
18161                if (!sourcePropType) continue;
18162                const propName = getPropertyNameFromIndex(nameType, /*accessNode*/ undefined);
18163                if (!checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
18164                    const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer);
18165                    reportedError = true;
18166                    if (!elaborated) {
18167                        // Issue error on the prop itself, since the prop couldn't elaborate the error
18168                        const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {};
18169                        // Use the expression type, if available
18170                        const specificSource = next ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType;
18171                        if (exactOptionalPropertyTypes && isExactOptionalPropertyMismatch(specificSource, targetPropType)) {
18172                            const diag = createDiagnosticForNode(prop, Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, typeToString(specificSource), typeToString(targetPropType));
18173                            diagnostics.add(diag);
18174                            resultObj.errors = [diag];
18175                        }
18176                        else {
18177                            const targetIsOptional = !!(propName && (getPropertyOfType(target, propName) || unknownSymbol).flags & SymbolFlags.Optional);
18178                            const sourceIsOptional = !!(propName && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional);
18179                            targetPropType = removeMissingType(targetPropType, targetIsOptional);
18180                            sourcePropType = removeMissingType(sourcePropType, targetIsOptional && sourceIsOptional);
18181                            const result = checkTypeRelatedTo(specificSource, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj);
18182                            if (result && specificSource !== sourcePropType) {
18183                                // If for whatever reason the expression type doesn't yield an error, make sure we still issue an error on the sourcePropType
18184                                checkTypeRelatedTo(sourcePropType, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj);
18185                            }
18186                        }
18187                        if (resultObj.errors) {
18188                            const reportedDiag = resultObj.errors[resultObj.errors.length - 1];
18189                            const propertyName = isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
18190                            const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) : undefined;
18191
18192                            let issuedElaboration = false;
18193                            if (!targetProp) {
18194                                const indexInfo = getApplicableIndexInfo(target, nameType);
18195                                if (indexInfo && indexInfo.declaration && !getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib) {
18196                                    issuedElaboration = true;
18197                                    addRelatedInfo(reportedDiag, createDiagnosticForNode(indexInfo.declaration, Diagnostics.The_expected_type_comes_from_this_index_signature));
18198                                }
18199                            }
18200
18201                            if (!issuedElaboration && (targetProp && length(targetProp.declarations) || target.symbol && length(target.symbol.declarations))) {
18202                                const targetNode = targetProp && length(targetProp.declarations) ? targetProp.declarations![0] : target.symbol.declarations![0];
18203                                if (!getSourceFileOfNode(targetNode).hasNoDefaultLib) {
18204                                    addRelatedInfo(reportedDiag, createDiagnosticForNode(
18205                                        targetNode,
18206                                        Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1,
18207                                        propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType),
18208                                        typeToString(target)
18209                                    ));
18210                                }
18211                            }
18212                        }
18213                    }
18214                }
18215            }
18216            return reportedError;
18217        }
18218
18219        function *generateJsxAttributes(node: JsxAttributes): ElaborationIterator {
18220            if (!length(node.properties)) return;
18221            for (const prop of node.properties) {
18222                if (isJsxSpreadAttribute(prop) || isHyphenatedJsxName(idText(prop.name))) continue;
18223                yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: getStringLiteralType(idText(prop.name)) };
18224            }
18225        }
18226
18227        function *generateJsxChildren(node: JsxElement, getInvalidTextDiagnostic: () => DiagnosticMessage): ElaborationIterator {
18228            if (!length(node.children)) return;
18229            let memberOffset = 0;
18230            for (let i = 0; i < node.children.length; i++) {
18231                const child = node.children[i];
18232                const nameType = getNumberLiteralType(i - memberOffset);
18233                const elem = getElaborationElementForJsxChild(child, nameType, getInvalidTextDiagnostic);
18234                if (elem) {
18235                    yield elem;
18236                }
18237                else {
18238                    memberOffset++;
18239                }
18240            }
18241        }
18242
18243        function getElaborationElementForJsxChild(child: JsxChild, nameType: LiteralType, getInvalidTextDiagnostic: () => DiagnosticMessage) {
18244            switch (child.kind) {
18245                case SyntaxKind.JsxExpression:
18246                    // child is of the type of the expression
18247                    return { errorNode: child, innerExpression: child.expression, nameType };
18248                case SyntaxKind.JsxText:
18249                    if (child.containsOnlyTriviaWhiteSpaces) {
18250                        break; // Whitespace only jsx text isn't real jsx text
18251                    }
18252                    // child is a string
18253                    return { errorNode: child, innerExpression: undefined, nameType, errorMessage: getInvalidTextDiagnostic() };
18254                case SyntaxKind.JsxElement:
18255                case SyntaxKind.JsxSelfClosingElement:
18256                case SyntaxKind.JsxFragment:
18257                    // child is of type JSX.Element
18258                    return { errorNode: child, innerExpression: child, nameType };
18259                default:
18260                    return Debug.assertNever(child, "Found invalid jsx child");
18261            }
18262        }
18263
18264        function elaborateJsxComponents(
18265            node: JsxAttributes,
18266            source: Type,
18267            target: Type,
18268            relation: ESMap<string, RelationComparisonResult>,
18269            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18270            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18271        ) {
18272            let result = elaborateElementwise(generateJsxAttributes(node), source, target, relation, containingMessageChain, errorOutputContainer);
18273            let invalidTextDiagnostic: DiagnosticMessage | undefined;
18274            if (isJsxOpeningElement(node.parent) && isJsxElement(node.parent.parent)) {
18275                const containingElement = node.parent.parent;
18276                const childPropName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node));
18277                const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName);
18278                const childrenNameType = getStringLiteralType(childrenPropName);
18279                const childrenTargetType = getIndexedAccessType(target, childrenNameType);
18280                const validChildren = getSemanticJsxChildren(containingElement.children);
18281                if (!length(validChildren)) {
18282                    return result;
18283                }
18284                const moreThanOneRealChildren = length(validChildren) > 1;
18285                const arrayLikeTargetParts = filterType(childrenTargetType, isArrayOrTupleLikeType);
18286                const nonArrayLikeTargetParts = filterType(childrenTargetType, t => !isArrayOrTupleLikeType(t));
18287                if (moreThanOneRealChildren) {
18288                    if (arrayLikeTargetParts !== neverType) {
18289                        const realSource = createTupleType(checkJsxChildren(containingElement, CheckMode.Normal));
18290                        const children = generateJsxChildren(containingElement, getInvalidTextualChildDiagnostic);
18291                        result = elaborateElementwise(children, realSource, arrayLikeTargetParts, relation, containingMessageChain, errorOutputContainer) || result;
18292                    }
18293                    else if (!isTypeRelatedTo(getIndexedAccessType(source, childrenNameType), childrenTargetType, relation)) {
18294                        // arity mismatch
18295                        result = true;
18296                        const diag = error(
18297                            containingElement.openingElement.tagName,
18298                            Diagnostics.This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided,
18299                            childrenPropName,
18300                            typeToString(childrenTargetType)
18301                        );
18302                        if (errorOutputContainer && errorOutputContainer.skipLogging) {
18303                            (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
18304                        }
18305                    }
18306                }
18307                else {
18308                    if (nonArrayLikeTargetParts !== neverType) {
18309                        const child = validChildren[0];
18310                        const elem = getElaborationElementForJsxChild(child, childrenNameType, getInvalidTextualChildDiagnostic);
18311                        if (elem) {
18312                            result = elaborateElementwise(
18313                                (function*() { yield elem; })(),
18314                                source,
18315                                target,
18316                                relation,
18317                                containingMessageChain,
18318                                errorOutputContainer
18319                            ) || result;
18320                        }
18321                    }
18322                    else if (!isTypeRelatedTo(getIndexedAccessType(source, childrenNameType), childrenTargetType, relation)) {
18323                        // arity mismatch
18324                        result = true;
18325                        const diag = error(
18326                            containingElement.openingElement.tagName,
18327                            Diagnostics.This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided,
18328                            childrenPropName,
18329                            typeToString(childrenTargetType)
18330                        );
18331                        if (errorOutputContainer && errorOutputContainer.skipLogging) {
18332                            (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
18333                        }
18334                    }
18335                }
18336            }
18337            return result;
18338
18339            function getInvalidTextualChildDiagnostic() {
18340                if (!invalidTextDiagnostic) {
18341                    const tagNameText = getTextOfNode(node.parent.tagName);
18342                    const childPropName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node));
18343                    const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName);
18344                    const childrenTargetType = getIndexedAccessType(target, getStringLiteralType(childrenPropName));
18345                    const diagnostic = Diagnostics._0_components_don_t_accept_text_as_child_elements_Text_in_JSX_has_the_type_string_but_the_expected_type_of_1_is_2;
18346                    invalidTextDiagnostic = { ...diagnostic, key: "!!ALREADY FORMATTED!!", message: formatMessage(/*_dummy*/ undefined, diagnostic, tagNameText, childrenPropName, typeToString(childrenTargetType)) };
18347                }
18348                return invalidTextDiagnostic;
18349            }
18350        }
18351
18352        function *generateLimitedTupleElements(node: ArrayLiteralExpression, target: Type): ElaborationIterator {
18353            const len = length(node.elements);
18354            if (!len) return;
18355            for (let i = 0; i < len; i++) {
18356                // Skip elements which do not exist in the target - a length error on the tuple overall is likely better than an error on a mismatched index signature
18357                if (isTupleLikeType(target) && !getPropertyOfType(target, ("" + i) as __String)) continue;
18358                const elem = node.elements[i];
18359                if (isOmittedExpression(elem)) continue;
18360                const nameType = getNumberLiteralType(i);
18361                yield { errorNode: elem, innerExpression: elem, nameType };
18362            }
18363        }
18364
18365        function elaborateArrayLiteral(
18366            node: ArrayLiteralExpression,
18367            source: Type,
18368            target: Type,
18369            relation: ESMap<string, RelationComparisonResult>,
18370            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18371            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18372        ) {
18373            if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false;
18374            if (isTupleLikeType(source)) {
18375                return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation, containingMessageChain, errorOutputContainer);
18376            }
18377            // recreate a tuple from the elements, if possible
18378            // Since we're re-doing the expression type, we need to reapply the contextual type
18379            const oldContext = node.contextualType;
18380            node.contextualType = target;
18381            try {
18382                const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true);
18383                node.contextualType = oldContext;
18384                if (isTupleLikeType(tupleizedType)) {
18385                    return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation, containingMessageChain, errorOutputContainer);
18386                }
18387                return false;
18388            }
18389            finally {
18390                node.contextualType = oldContext;
18391            }
18392        }
18393
18394        function *generateObjectLiteralElements(node: ObjectLiteralExpression): ElaborationIterator {
18395            if (!length(node.properties)) return;
18396            for (const prop of node.properties) {
18397                if (isSpreadAssignment(prop)) continue;
18398                const type = getLiteralTypeFromProperty(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique);
18399                if (!type || (type.flags & TypeFlags.Never)) {
18400                    continue;
18401                }
18402                switch (prop.kind) {
18403                    case SyntaxKind.SetAccessor:
18404                    case SyntaxKind.GetAccessor:
18405                    case SyntaxKind.MethodDeclaration:
18406                    case SyntaxKind.ShorthandPropertyAssignment:
18407                        yield { errorNode: prop.name, innerExpression: undefined, nameType: type };
18408                        break;
18409                    case SyntaxKind.PropertyAssignment:
18410                        yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: type, errorMessage: isComputedNonLiteralName(prop.name) ? Diagnostics.Type_of_computed_property_s_value_is_0_which_is_not_assignable_to_type_1 : undefined };
18411                        break;
18412                    default:
18413                        Debug.assertNever(prop);
18414                }
18415            }
18416        }
18417
18418        function elaborateObjectLiteral(
18419            node: ObjectLiteralExpression,
18420            source: Type,
18421            target: Type,
18422            relation: ESMap<string, RelationComparisonResult>,
18423            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
18424            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined
18425        ) {
18426            if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false;
18427            return elaborateElementwise(generateObjectLiteralElements(node), source, target, relation, containingMessageChain, errorOutputContainer);
18428        }
18429
18430        /**
18431         * This is *not* a bi-directional relationship.
18432         * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'.
18433         */
18434        function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean {
18435            return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain);
18436        }
18437
18438        function isSignatureAssignableTo(source: Signature,
18439            target: Signature,
18440            ignoreReturnTypes: boolean): boolean {
18441            return compareSignaturesRelated(source, target, ignoreReturnTypes ? SignatureCheckMode.IgnoreReturnTypes : 0, /*reportErrors*/ false,
18442                /*errorReporter*/ undefined, /*errorReporter*/ undefined, compareTypesAssignable, /*reportUnreliableMarkers*/ undefined) !== Ternary.False;
18443        }
18444
18445        type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void;
18446
18447        /**
18448         * Returns true if `s` is `(...args: any[]) => any` or `(this: any, ...args: any[]) => any`
18449         */
18450        function isAnySignature(s: Signature) {
18451            return !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 &&
18452                signatureHasRestParameter(s) && (getTypeOfParameter(s.parameters[0]) === anyArrayType || isTypeAny(getTypeOfParameter(s.parameters[0]))) &&
18453                isTypeAny(getReturnTypeOfSignature(s));
18454        }
18455
18456        /**
18457         * See signatureRelatedTo, compareSignaturesIdentical
18458         */
18459        function compareSignaturesRelated(source: Signature,
18460            target: Signature,
18461            checkMode: SignatureCheckMode,
18462            reportErrors: boolean,
18463            errorReporter: ErrorReporter | undefined,
18464            incompatibleErrorReporter: ((source: Type, target: Type) => void) | undefined,
18465            compareTypes: TypeComparer,
18466            reportUnreliableMarkers: TypeMapper | undefined): Ternary {
18467            // TODO (drosen): De-duplicate code between related functions.
18468            if (source === target) {
18469                return Ternary.True;
18470            }
18471
18472            if (isAnySignature(target)) {
18473                return Ternary.True;
18474            }
18475
18476            const targetCount = getParameterCount(target);
18477            const sourceHasMoreParameters = !hasEffectiveRestParameter(target) &&
18478                (checkMode & SignatureCheckMode.StrictArity ? hasEffectiveRestParameter(source) || getParameterCount(source) > targetCount : getMinArgumentCount(source) > targetCount);
18479            if (sourceHasMoreParameters) {
18480                return Ternary.False;
18481            }
18482
18483            if (source.typeParameters && source.typeParameters !== target.typeParameters) {
18484                target = getCanonicalSignature(target);
18485                source = instantiateSignatureInContextOf(source, target, /*inferenceContext*/ undefined, compareTypes);
18486            }
18487
18488            const sourceCount = getParameterCount(source);
18489            const sourceRestType = getNonArrayRestType(source);
18490            const targetRestType = getNonArrayRestType(target);
18491            if (sourceRestType || targetRestType) {
18492                void instantiateType(sourceRestType || targetRestType, reportUnreliableMarkers);
18493            }
18494
18495            const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
18496            const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration &&
18497                kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor;
18498            let result = Ternary.True;
18499
18500            const sourceThisType = getThisTypeOfSignature(source);
18501            if (sourceThisType && sourceThisType !== voidType) {
18502                const targetThisType = getThisTypeOfSignature(target);
18503                if (targetThisType) {
18504                    // void sources are assignable to anything.
18505                    const related = !strictVariance && compareTypes(sourceThisType, targetThisType, /*reportErrors*/ false)
18506                        || compareTypes(targetThisType, sourceThisType, reportErrors);
18507                    if (!related) {
18508                        if (reportErrors) {
18509                            errorReporter!(Diagnostics.The_this_types_of_each_signature_are_incompatible);
18510                        }
18511                        return Ternary.False;
18512                    }
18513                    result &= related;
18514                }
18515            }
18516
18517            const paramCount = sourceRestType || targetRestType ? Math.min(sourceCount, targetCount) : Math.max(sourceCount, targetCount);
18518            const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
18519
18520            for (let i = 0; i < paramCount; i++) {
18521                const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
18522                const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
18523                if (sourceType && targetType) {
18524                    // In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
18525                    // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
18526                    // they naturally relate only contra-variantly). However, if the source and target parameters both have
18527                    // function types with a single call signature, we know we are relating two callback parameters. In
18528                    // that case it is sufficient to only relate the parameters of the signatures co-variantly because,
18529                    // similar to return values, callback parameters are output positions. This means that a Promise<T>,
18530                    // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant)
18531                    // with respect to T.
18532                    const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
18533                    const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType));
18534                    const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) &&
18535                        (getTypeFacts(sourceType) & TypeFacts.IsUndefinedOrNull) === (getTypeFacts(targetType) & TypeFacts.IsUndefinedOrNull);
18536                    let related = callbacks ?
18537                        compareSignaturesRelated(targetSig, sourceSig, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) :
18538                        !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors);
18539                    // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void
18540                    if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) {
18541                        related = Ternary.False;
18542                    }
18543                    if (!related) {
18544                        if (reportErrors) {
18545                            errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
18546                                unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)),
18547                                unescapeLeadingUnderscores(getParameterNameAtPosition(target, i)));
18548                        }
18549                        return Ternary.False;
18550                    }
18551                    result &= related;
18552                }
18553            }
18554
18555            if (!(checkMode & SignatureCheckMode.IgnoreReturnTypes)) {
18556                // If a signature resolution is already in-flight, skip issuing a circularity error
18557                // here and just use the `any` type directly
18558                const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType
18559                    : target.declaration && isJSConstructor(target.declaration) ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(target.declaration.symbol))
18560                    : getReturnTypeOfSignature(target);
18561                if (targetReturnType === voidType || targetReturnType === anyType) {
18562                    return result;
18563                }
18564                const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType
18565                    : source.declaration && isJSConstructor(source.declaration) ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(source.declaration.symbol))
18566                    : getReturnTypeOfSignature(source);
18567
18568                // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
18569                const targetTypePredicate = getTypePredicateOfSignature(target);
18570                if (targetTypePredicate) {
18571                    const sourceTypePredicate = getTypePredicateOfSignature(source);
18572                    if (sourceTypePredicate) {
18573                        result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, reportErrors, errorReporter, compareTypes);
18574                    }
18575                    else if (isIdentifierTypePredicate(targetTypePredicate)) {
18576                        if (reportErrors) {
18577                            errorReporter!(Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source));
18578                        }
18579                        return Ternary.False;
18580                    }
18581                }
18582                else {
18583                    // When relating callback signatures, we still need to relate return types bi-variantly as otherwise
18584                    // the containing type wouldn't be co-variant. For example, interface Foo<T> { add(cb: () => T): void }
18585                    // wouldn't be co-variant for T without this rule.
18586                    result &= checkMode & SignatureCheckMode.BivariantCallback && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) ||
18587                        compareTypes(sourceReturnType, targetReturnType, reportErrors);
18588                    if (!result && reportErrors && incompatibleErrorReporter) {
18589                        incompatibleErrorReporter(sourceReturnType, targetReturnType);
18590                    }
18591                }
18592
18593            }
18594
18595            return result;
18596        }
18597
18598        function compareTypePredicateRelatedTo(
18599            source: TypePredicate,
18600            target: TypePredicate,
18601            reportErrors: boolean,
18602            errorReporter: ErrorReporter | undefined,
18603            compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
18604            if (source.kind !== target.kind) {
18605                if (reportErrors) {
18606                    errorReporter!(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard);
18607                    errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
18608                }
18609                return Ternary.False;
18610            }
18611
18612            if (source.kind === TypePredicateKind.Identifier || source.kind === TypePredicateKind.AssertsIdentifier) {
18613                if (source.parameterIndex !== (target as IdentifierTypePredicate).parameterIndex) {
18614                    if (reportErrors) {
18615                        errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, (target as IdentifierTypePredicate).parameterName);
18616                        errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
18617                    }
18618                    return Ternary.False;
18619                }
18620            }
18621
18622            const related = source.type === target.type ? Ternary.True :
18623                source.type && target.type ? compareTypes(source.type, target.type, reportErrors) :
18624                Ternary.False;
18625            if (related === Ternary.False && reportErrors) {
18626                errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
18627            }
18628            return related;
18629        }
18630
18631        function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean {
18632            const erasedSource = getErasedSignature(implementation);
18633            const erasedTarget = getErasedSignature(overload);
18634
18635            // First see if the return types are compatible in either direction.
18636            const sourceReturnType = getReturnTypeOfSignature(erasedSource);
18637            const targetReturnType = getReturnTypeOfSignature(erasedTarget);
18638            if (targetReturnType === voidType
18639                || isTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation)
18640                || isTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation)) {
18641
18642                return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true);
18643            }
18644
18645            return false;
18646        }
18647
18648        function isEmptyResolvedType(t: ResolvedType) {
18649            return t !== anyFunctionType &&
18650                t.properties.length === 0 &&
18651                t.callSignatures.length === 0 &&
18652                t.constructSignatures.length === 0 &&
18653                t.indexInfos.length === 0;
18654        }
18655
18656        function isEmptyObjectType(type: Type): boolean {
18657            return type.flags & TypeFlags.Object ? !isGenericMappedType(type) && isEmptyResolvedType(resolveStructuredTypeMembers(type as ObjectType)) :
18658                type.flags & TypeFlags.NonPrimitive ? true :
18659                type.flags & TypeFlags.Union ? some((type as UnionType).types, isEmptyObjectType) :
18660                type.flags & TypeFlags.Intersection ? every((type as UnionType).types, isEmptyObjectType) :
18661                false;
18662        }
18663
18664        function isEmptyAnonymousObjectType(type: Type) {
18665            return !!(getObjectFlags(type) & ObjectFlags.Anonymous && (
18666                (type as ResolvedType).members && isEmptyResolvedType(type as ResolvedType) ||
18667                type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && getMembersOfSymbol(type.symbol).size === 0));
18668        }
18669
18670        function isUnknownLikeUnionType(type: Type) {
18671            if (strictNullChecks && type.flags & TypeFlags.Union) {
18672                if (!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnionComputed)) {
18673                    const types = (type as UnionType).types;
18674                    (type as UnionType).objectFlags |= ObjectFlags.IsUnknownLikeUnionComputed | (types.length >= 3 && types[0].flags & TypeFlags.Undefined &&
18675                        types[1].flags & TypeFlags.Null && some(types, isEmptyAnonymousObjectType) ? ObjectFlags.IsUnknownLikeUnion : 0);
18676                }
18677                return !!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnion);
18678            }
18679            return false;
18680        }
18681
18682        function containsUndefinedType(type: Type) {
18683            return !!((type.flags & TypeFlags.Union ? (type as UnionType).types[0] : type).flags & TypeFlags.Undefined);
18684        }
18685
18686        function isStringIndexSignatureOnlyType(type: Type): boolean {
18687            return type.flags & TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) ||
18688                type.flags & TypeFlags.UnionOrIntersection && every((type as UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) ||
18689                false;
18690        }
18691
18692        function isEnumTypeRelatedTo(sourceSymbol: Symbol, targetSymbol: Symbol, errorReporter?: ErrorReporter) {
18693            if (sourceSymbol === targetSymbol) {
18694                return true;
18695            }
18696            const id = getSymbolId(sourceSymbol) + "," + getSymbolId(targetSymbol);
18697            const entry = enumRelation.get(id);
18698            if (entry !== undefined && !(!(entry & RelationComparisonResult.Reported) && entry & RelationComparisonResult.Failed && errorReporter)) {
18699                return !!(entry & RelationComparisonResult.Succeeded);
18700            }
18701            if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & SymbolFlags.RegularEnum) || !(targetSymbol.flags & SymbolFlags.RegularEnum)) {
18702                enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported);
18703                return false;
18704            }
18705            const targetEnumType = getTypeOfSymbol(targetSymbol);
18706            for (const property of getPropertiesOfType(getTypeOfSymbol(sourceSymbol))) {
18707                if (property.flags & SymbolFlags.EnumMember) {
18708                    const targetProperty = getPropertyOfType(targetEnumType, property.escapedName);
18709                    if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) {
18710                        if (errorReporter) {
18711                            errorReporter(Diagnostics.Property_0_is_missing_in_type_1, symbolName(property),
18712                                typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
18713                            enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported);
18714                        }
18715                        else {
18716                            enumRelation.set(id, RelationComparisonResult.Failed);
18717                        }
18718                        return false;
18719                    }
18720                }
18721            }
18722            enumRelation.set(id, RelationComparisonResult.Succeeded);
18723            return true;
18724        }
18725
18726        function isSimpleTypeRelatedTo(source: Type, target: Type, relation: ESMap<string, RelationComparisonResult>, errorReporter?: ErrorReporter) {
18727            const s = source.flags;
18728            const t = target.flags;
18729            if (t & TypeFlags.AnyOrUnknown || s & TypeFlags.Never || source === wildcardType) return true;
18730            if (t & TypeFlags.Never) return false;
18731            if (s & TypeFlags.StringLike && t & TypeFlags.String) return true;
18732            if (s & TypeFlags.StringLiteral && s & TypeFlags.EnumLiteral &&
18733                t & TypeFlags.StringLiteral && !(t & TypeFlags.EnumLiteral) &&
18734                (source as StringLiteralType).value === (target as StringLiteralType).value) return true;
18735            if (s & TypeFlags.NumberLike && t & TypeFlags.Number) return true;
18736            if (s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral &&
18737                t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) &&
18738                (source as NumberLiteralType).value === (target as NumberLiteralType).value) return true;
18739            if (s & TypeFlags.BigIntLike && t & TypeFlags.BigInt) return true;
18740            if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true;
18741            if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true;
18742            if (s & TypeFlags.Enum && t & TypeFlags.Enum && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true;
18743            if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) {
18744                if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true;
18745                if (s & TypeFlags.Literal && t & TypeFlags.Literal &&
18746                    (source as LiteralType).value === (target as LiteralType).value &&
18747                    isEnumTypeRelatedTo(getParentOfSymbol(source.symbol)!, getParentOfSymbol(target.symbol)!, errorReporter)) return true;
18748            }
18749            // In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`.
18750            // Since unions and intersections may reduce to `never`, we exclude them here.
18751            if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true;
18752            if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true;
18753            if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) && !(getObjectFlags(source) & ObjectFlags.FreshLiteral))) return true;
18754            if (relation === assignableRelation || relation === comparableRelation) {
18755                if (s & TypeFlags.Any) return true;
18756                // Type number or any numeric literal type is assignable to any numeric enum type or any
18757                // numeric enum literal type. This rule exists for backwards compatibility reasons because
18758                // bit-flag enum types sometimes look like literal enum types with numeric literal values.
18759                if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && (
18760                    t & TypeFlags.Enum || relation === assignableRelation && t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true;
18761                // Anything is assignable to a union containing undefined, null, and {}
18762                if (isUnknownLikeUnionType(target)) return true;
18763            }
18764            return false;
18765        }
18766
18767        function isTypeRelatedTo(source: Type, target: Type, relation: ESMap<string, RelationComparisonResult>) {
18768            if (isFreshLiteralType(source)) {
18769                source = (source as FreshableType).regularType;
18770            }
18771            if (isFreshLiteralType(target)) {
18772                target = (target as FreshableType).regularType;
18773            }
18774            if (source === target) {
18775                return true;
18776            }
18777            if (relation !== identityRelation) {
18778                if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) {
18779                    return true;
18780                }
18781            }
18782            else if (!((source.flags | target.flags) & (TypeFlags.UnionOrIntersection | TypeFlags.IndexedAccess | TypeFlags.Conditional | TypeFlags.Substitution))) {
18783                // We have excluded types that may simplify to other forms, so types must have identical flags
18784                if (source.flags !== target.flags) return false;
18785                if (source.flags & TypeFlags.Singleton) return true;
18786            }
18787            if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
18788                const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation, /*ignoreConstraints*/ false));
18789                if (related !== undefined) {
18790                    return !!(related & RelationComparisonResult.Succeeded);
18791                }
18792            }
18793            if (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable) {
18794                return checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined);
18795            }
18796            return false;
18797        }
18798
18799        function isIgnoredJsxProperty(source: Type, sourceProp: Symbol) {
18800            return getObjectFlags(source) & ObjectFlags.JsxAttributes && isHyphenatedJsxName(sourceProp.escapedName);
18801        }
18802
18803        function getNormalizedType(type: Type, writing: boolean): Type {
18804            while (true) {
18805                const t = isFreshLiteralType(type) ? (type as FreshableType).regularType :
18806                    getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type :
18807                    type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) :
18808                    type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) :
18809                    type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) :
18810                    type;
18811                if (t === type) return t;
18812                type = t;
18813            }
18814        }
18815
18816        function getNormalizedUnionOrIntersectionType(type: UnionOrIntersectionType, writing: boolean) {
18817            const reduced = getReducedType(type);
18818            if (reduced !== type) {
18819                return reduced;
18820            }
18821            if (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isEmptyAnonymousObjectType)) {
18822                const normalizedTypes = sameMap(type.types, t => getNormalizedType(t, writing));
18823                if (normalizedTypes !== type.types) {
18824                    return getIntersectionType(normalizedTypes);
18825                }
18826            }
18827            return type;
18828        }
18829
18830        /**
18831         * Checks if 'source' is related to 'target' (e.g.: is a assignable to).
18832         * @param source The left-hand-side of the relation.
18833         * @param target The right-hand-side of the relation.
18834         * @param relation The relation considered. One of 'identityRelation', 'subtypeRelation', 'assignableRelation', or 'comparableRelation'.
18835         * Used as both to determine which checks are performed and as a cache of previously computed results.
18836         * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used.
18837         * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used.
18838         * @param containingMessageChain A chain of errors to prepend any new errors found.
18839         * @param errorOutputContainer Return the diagnostic. Do not log if 'skipLogging' is truthy.
18840         */
18841        function checkTypeRelatedTo(
18842            source: Type,
18843            target: Type,
18844            relation: ESMap<string, RelationComparisonResult>,
18845            errorNode: Node | undefined,
18846            headMessage?: DiagnosticMessage,
18847            containingMessageChain?: () => DiagnosticMessageChain | undefined,
18848            errorOutputContainer?: { errors?: Diagnostic[], skipLogging?: boolean },
18849        ): boolean {
18850
18851            let errorInfo: DiagnosticMessageChain | undefined;
18852            let relatedInfo: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined;
18853            let maybeKeys: string[];
18854            let sourceStack: Type[];
18855            let targetStack: Type[];
18856            let maybeCount = 0;
18857            let sourceDepth = 0;
18858            let targetDepth = 0;
18859            let expandingFlags = ExpandingFlags.None;
18860            let overflow = false;
18861            let overrideNextErrorInfo = 0; // How many `reportRelationError` calls should be skipped in the elaboration pyramid
18862            let lastSkippedInfo: [Type, Type] | undefined;
18863            let incompatibleStack: [DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] | undefined;
18864            let inPropertyCheck = false;
18865
18866            Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
18867
18868            const result = isRelatedTo(source, target, RecursionFlags.Both, /*reportErrors*/ !!errorNode, headMessage);
18869            if (incompatibleStack) {
18870                reportIncompatibleStack();
18871            }
18872            if (overflow) {
18873                tracing?.instant(tracing.Phase.CheckTypes, "checkTypeRelatedTo_DepthLimit", { sourceId: source.id, targetId: target.id, depth: sourceDepth, targetDepth });
18874                const diag = error(errorNode || currentNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
18875                if (errorOutputContainer) {
18876                    (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
18877                }
18878            }
18879            else if (errorInfo) {
18880                if (containingMessageChain) {
18881                    const chain = containingMessageChain();
18882                    if (chain) {
18883                        concatenateDiagnosticMessageChains(chain, errorInfo);
18884                        errorInfo = chain;
18885                    }
18886                }
18887
18888                let relatedInformation: DiagnosticRelatedInformation[] | undefined;
18889                // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement
18890                if (headMessage && errorNode && !result && source.symbol) {
18891                    const links = getSymbolLinks(source.symbol);
18892                    if (links.originatingImport && !isImportCall(links.originatingImport)) {
18893                        const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target!), target, relation, /*errorNode*/ undefined);
18894                        if (helpfulRetry) {
18895                            // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import
18896                            const diag = createDiagnosticForNode(links.originatingImport, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead);
18897                            relatedInformation = append(relatedInformation, diag); // Cause the error to appear with the error that triggered it
18898                        }
18899                    }
18900                }
18901                const diag = createDiagnosticForNodeFromMessageChain(errorNode!, errorInfo, relatedInformation);
18902                if (relatedInfo) {
18903                    addRelatedInfo(diag, ...relatedInfo);
18904                }
18905                if (errorOutputContainer) {
18906                    (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
18907                }
18908                if (!errorOutputContainer || !errorOutputContainer.skipLogging) {
18909                    diagnostics.add(diag);
18910                }
18911            }
18912            if (errorNode && errorOutputContainer && errorOutputContainer.skipLogging && result === Ternary.False) {
18913                Debug.assert(!!errorOutputContainer.errors, "missed opportunity to interact with error.");
18914            }
18915
18916
18917            return result !== Ternary.False;
18918
18919            function resetErrorInfo(saved: ReturnType<typeof captureErrorCalculationState>) {
18920                errorInfo = saved.errorInfo;
18921                lastSkippedInfo = saved.lastSkippedInfo;
18922                incompatibleStack = saved.incompatibleStack;
18923                overrideNextErrorInfo = saved.overrideNextErrorInfo;
18924                relatedInfo = saved.relatedInfo;
18925            }
18926
18927            function captureErrorCalculationState() {
18928                return {
18929                    errorInfo,
18930                    lastSkippedInfo,
18931                    incompatibleStack: incompatibleStack?.slice(),
18932                    overrideNextErrorInfo,
18933                    relatedInfo: relatedInfo?.slice() as [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined,
18934                };
18935            }
18936
18937            function reportIncompatibleError(message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number) {
18938                overrideNextErrorInfo++; // Suppress the next relation error
18939                lastSkippedInfo = undefined; // Reset skipped info cache
18940                (incompatibleStack ||= []).push([message, arg0, arg1, arg2, arg3]);
18941            }
18942
18943            function reportIncompatibleStack() {
18944                const stack = incompatibleStack || [];
18945                incompatibleStack = undefined;
18946                const info = lastSkippedInfo;
18947                lastSkippedInfo = undefined;
18948                if (stack.length === 1) {
18949                    reportError(...stack[0]);
18950                    if (info) {
18951                        // Actually do the last relation error
18952                        reportRelationError(/*headMessage*/ undefined, ...info);
18953                    }
18954                    return;
18955                }
18956                // The first error will be the innermost, while the last will be the outermost - so by popping off the end,
18957                // we can build from left to right
18958                let path = "";
18959                const secondaryRootErrors: [DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] = [];
18960                while (stack.length) {
18961                    const [msg, ...args] = stack.pop()!;
18962                    switch (msg.code) {
18963                        case Diagnostics.Types_of_property_0_are_incompatible.code: {
18964                            // Parenthesize a `new` if there is one
18965                            if (path.indexOf("new ") === 0) {
18966                                path = `(${path})`;
18967                            }
18968                            const str = "" + args[0];
18969                            // If leading, just print back the arg (irrespective of if it's a valid identifier)
18970                            if (path.length === 0) {
18971                                path = `${str}`;
18972                            }
18973                            // Otherwise write a dotted name if possible
18974                            else if (isIdentifierText(str, getEmitScriptTarget(compilerOptions))) {
18975                                path = `${path}.${str}`;
18976                            }
18977                            // Failing that, check if the name is already a computed name
18978                            else if (str[0] === "[" && str[str.length - 1] === "]") {
18979                                path = `${path}${str}`;
18980                            }
18981                            // And finally write out a computed name as a last resort
18982                            else {
18983                                path = `${path}[${str}]`;
18984                            }
18985                            break;
18986                        }
18987                        case Diagnostics.Call_signature_return_types_0_and_1_are_incompatible.code:
18988                        case Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code:
18989                        case Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code:
18990                        case Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: {
18991                            if (path.length === 0) {
18992                                // Don't flatten signature compatability errors at the start of a chain - instead prefer
18993                                // to unify (the with no arguments bit is excessive for printback) and print them back
18994                                let mappedMsg = msg;
18995                                if (msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) {
18996                                    mappedMsg = Diagnostics.Call_signature_return_types_0_and_1_are_incompatible;
18997                                }
18998                                else if (msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) {
18999                                    mappedMsg = Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible;
19000                                }
19001                                secondaryRootErrors.unshift([mappedMsg, args[0], args[1]]);
19002                            }
19003                            else {
19004                                const prefix = (msg.code === Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code ||
19005                                    msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code)
19006                                        ? "new "
19007                                        : "";
19008                                const params = (msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code ||
19009                                    msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code)
19010                                        ? ""
19011                                        : "...";
19012                                path = `${prefix}${path}(${params})`;
19013                            }
19014                            break;
19015                        }
19016                        case Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target.code: {
19017                            secondaryRootErrors.unshift([Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, args[0], args[1]]);
19018                            break;
19019                        }
19020                        case Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target.code: {
19021                            secondaryRootErrors.unshift([Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, args[0], args[1], args[2]]);
19022                            break;
19023                        }
19024                        default:
19025                            return Debug.fail(`Unhandled Diagnostic: ${msg.code}`);
19026                    }
19027                }
19028                if (path) {
19029                    reportError(path[path.length - 1] === ")"
19030                        ? Diagnostics.The_types_returned_by_0_are_incompatible_between_these_types
19031                        : Diagnostics.The_types_of_0_are_incompatible_between_these_types,
19032                        path
19033                    );
19034                }
19035                else {
19036                    // Remove the innermost secondary error as it will duplicate the error already reported by `reportRelationError` on entry
19037                    secondaryRootErrors.shift();
19038                }
19039                for (const [msg, ...args] of secondaryRootErrors) {
19040                    const originalValue = msg.elidedInCompatabilityPyramid;
19041                    msg.elidedInCompatabilityPyramid = false; // Temporarily override elision to ensure error is reported
19042                    reportError(msg, ...args);
19043                    msg.elidedInCompatabilityPyramid = originalValue;
19044                }
19045                if (info) {
19046                    // Actually do the last relation error
19047                    reportRelationError(/*headMessage*/ undefined, ...info);
19048                }
19049            }
19050
19051            function reportError(message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void {
19052                Debug.assert(!!errorNode);
19053                if (incompatibleStack) reportIncompatibleStack();
19054                if (message.elidedInCompatabilityPyramid) return;
19055                errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2, arg3);
19056            }
19057
19058            function associateRelatedInfo(info: DiagnosticRelatedInformation) {
19059                Debug.assert(!!errorInfo);
19060                if (!relatedInfo) {
19061                    relatedInfo = [info];
19062                }
19063                else {
19064                    relatedInfo.push(info);
19065                }
19066            }
19067
19068            function reportRelationError(message: DiagnosticMessage | undefined, source: Type, target: Type) {
19069                if (incompatibleStack) reportIncompatibleStack();
19070                const [sourceType, targetType] = getTypeNamesForErrorDisplay(source, target);
19071                let generalizedSource = source;
19072                let generalizedSourceType = sourceType;
19073
19074                if (isLiteralType(source) && !typeCouldHaveTopLevelSingletonTypes(target)) {
19075                    generalizedSource = getBaseTypeOfLiteralType(source);
19076                    Debug.assert(!isTypeAssignableTo(generalizedSource, target), "generalized source shouldn't be assignable");
19077                    generalizedSourceType = getTypeNameForErrorDisplay(generalizedSource);
19078                }
19079
19080                if (target.flags & TypeFlags.TypeParameter && target !== markerSuperTypeForCheck && target !== markerSubTypeForCheck) {
19081                    const constraint = getBaseConstraintOfType(target);
19082                    let needsOriginalSource;
19083                    if (constraint && (isTypeAssignableTo(generalizedSource, constraint) || (needsOriginalSource = isTypeAssignableTo(source, constraint)))) {
19084                        reportError(
19085                            Diagnostics._0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2,
19086                            needsOriginalSource ? sourceType : generalizedSourceType,
19087                            targetType,
19088                            typeToString(constraint),
19089                        );
19090                    }
19091                    else {
19092                        errorInfo = undefined;
19093                        reportError(
19094                            Diagnostics._0_could_be_instantiated_with_an_arbitrary_type_which_could_be_unrelated_to_1,
19095                            targetType,
19096                            generalizedSourceType
19097                        );
19098                    }
19099                }
19100
19101                if (!message) {
19102                    if (relation === comparableRelation) {
19103                        message = Diagnostics.Type_0_is_not_comparable_to_type_1;
19104                    }
19105                    else if (sourceType === targetType) {
19106                        message = Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated;
19107                    }
19108                    else if (exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length) {
19109                        message = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties;
19110                    }
19111                    else {
19112                        if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.Union) {
19113                            const suggestedType = getSuggestedTypeForNonexistentStringLiteralType(source as StringLiteralType, target as UnionType);
19114                            if (suggestedType) {
19115                                reportError(Diagnostics.Type_0_is_not_assignable_to_type_1_Did_you_mean_2, generalizedSourceType, targetType, typeToString(suggestedType));
19116                                return;
19117                            }
19118                        }
19119                        message = Diagnostics.Type_0_is_not_assignable_to_type_1;
19120                    }
19121                }
19122                else if (message === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1
19123                    && exactOptionalPropertyTypes
19124                    && getExactOptionalUnassignableProperties(source, target).length) {
19125                    message = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties;
19126                }
19127
19128                reportError(message, generalizedSourceType, targetType);
19129            }
19130
19131            function tryElaborateErrorsForPrimitivesAndObjects(source: Type, target: Type) {
19132                const sourceType = symbolValueDeclarationIsContextSensitive(source.symbol) ? typeToString(source, source.symbol.valueDeclaration) : typeToString(source);
19133                const targetType = symbolValueDeclarationIsContextSensitive(target.symbol) ? typeToString(target, target.symbol.valueDeclaration) : typeToString(target);
19134
19135                if ((globalStringType === source && stringType === target) ||
19136                    (globalNumberType === source && numberType === target) ||
19137                    (globalBooleanType === source && booleanType === target) ||
19138                    (getGlobalESSymbolType() === source && esSymbolType === target)) {
19139                    reportError(Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType);
19140                }
19141            }
19142
19143            /**
19144             * Try and elaborate array and tuple errors. Returns false
19145             * if we have found an elaboration, or we should ignore
19146             * any other elaborations when relating the `source` and
19147             * `target` types.
19148             */
19149            function tryElaborateArrayLikeErrors(source: Type, target: Type, reportErrors: boolean): boolean {
19150                /**
19151                 * The spec for elaboration is:
19152                 * - If the source is a readonly tuple and the target is a mutable array or tuple, elaborate on mutability and skip property elaborations.
19153                 * - If the source is a tuple then skip property elaborations if the target is an array or tuple.
19154                 * - If the source is a readonly array and the target is a mutable array or tuple, elaborate on mutability and skip property elaborations.
19155                 * - If the source an array then skip property elaborations if the target is a tuple.
19156                 */
19157                if (isTupleType(source)) {
19158                    if (source.target.readonly && isMutableArrayOrTuple(target)) {
19159                        if (reportErrors) {
19160                            reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target));
19161                        }
19162                        return false;
19163                    }
19164                    return isArrayOrTupleType(target);
19165                }
19166                if (isReadonlyArrayType(source) && isMutableArrayOrTuple(target)) {
19167                    if (reportErrors) {
19168                        reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target));
19169                    }
19170                    return false;
19171                }
19172                if (isTupleType(target)) {
19173                    return isArrayType(source);
19174                }
19175                return true;
19176            }
19177
19178            function isRelatedToWorker(source: Type, target: Type, reportErrors: boolean) {
19179                return isRelatedTo(source, target, RecursionFlags.Both, reportErrors);
19180            }
19181
19182            /**
19183             * Compare two types and return
19184             * * Ternary.True if they are related with no assumptions,
19185             * * Ternary.Maybe if they are related with assumptions of other relationships, or
19186             * * Ternary.False if they are not related.
19187             */
19188            function isRelatedTo(originalSource: Type, originalTarget: Type, recursionFlags: RecursionFlags = RecursionFlags.Both, reportErrors = false, headMessage?: DiagnosticMessage, intersectionState = IntersectionState.None): Ternary {
19189                // Before normalization: if `source` is type an object type, and `target` is primitive,
19190                // skip all the checks we don't need and just return `isSimpleTypeRelatedTo` result
19191                if (originalSource.flags & TypeFlags.Object && originalTarget.flags & TypeFlags.Primitive) {
19192                    if (isSimpleTypeRelatedTo(originalSource, originalTarget, relation, reportErrors ? reportError : undefined)) {
19193                        return Ternary.True;
19194                    }
19195                    if (reportErrors) {
19196                        reportErrorResults(originalSource, originalTarget, originalSource, originalTarget, headMessage);
19197                    }
19198                    return Ternary.False;
19199                }
19200
19201                // Normalize the source and target types: Turn fresh literal types into regular literal types,
19202                // turn deferred type references into regular type references, simplify indexed access and
19203                // conditional types, and resolve substitution types to either the substitution (on the source
19204                // side) or the type variable (on the target side).
19205                const source = getNormalizedType(originalSource, /*writing*/ false);
19206                let target = getNormalizedType(originalTarget, /*writing*/ true);
19207
19208                if (source === target) return Ternary.True;
19209
19210                if (relation === identityRelation) {
19211                    if (source.flags !== target.flags) return Ternary.False;
19212                    if (source.flags & TypeFlags.Singleton) return Ternary.True;
19213                    traceUnionsOrIntersectionsTooLarge(source, target);
19214                    return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None, recursionFlags);
19215                }
19216
19217                // We fastpath comparing a type parameter to exactly its constraint, as this is _super_ common,
19218                // and otherwise, for type parameters in large unions, causes us to need to compare the union to itself,
19219                // as we break down the _target_ union first, _then_ get the source constraint - so for every
19220                // member of the target, we attempt to find a match in the source. This avoids that in cases where
19221                // the target is exactly the constraint.
19222                if (source.flags & TypeFlags.TypeParameter && getConstraintOfType(source) === target) {
19223                    return Ternary.True;
19224                }
19225
19226                // See if we're relating a definitely non-nullable type to a union that includes null and/or undefined
19227                // plus a single non-nullable type. If so, remove null and/or undefined from the target type.
19228                if (source.flags & TypeFlags.DefinitelyNonNullable && target.flags & TypeFlags.Union) {
19229                    const types = (target as UnionType).types;
19230                    const candidate = types.length === 2 && types[0].flags & TypeFlags.Nullable ? types[1] :
19231                        types.length === 3 && types[0].flags & TypeFlags.Nullable && types[1].flags & TypeFlags.Nullable ? types[2] :
19232                        undefined;
19233                    if (candidate && !(candidate.flags & TypeFlags.Nullable)) {
19234                        target = getNormalizedType(candidate, /*writing*/ true);
19235                        if (source === target) return Ternary.True;
19236                    }
19237                }
19238
19239                if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
19240                    isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
19241
19242                if (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable) {
19243                    const isPerformingExcessPropertyChecks = !(intersectionState & IntersectionState.Target) && (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral);
19244                    if (isPerformingExcessPropertyChecks) {
19245                        if (hasExcessProperties(source as FreshObjectLiteralType, target, reportErrors)) {
19246                            if (reportErrors) {
19247                                reportRelationError(headMessage, source, originalTarget.aliasSymbol ? originalTarget : target);
19248                            }
19249                            return Ternary.False;
19250                        }
19251                    }
19252
19253                    const isPerformingCommonPropertyChecks = (relation !== comparableRelation || isUnitType(source)) &&
19254                        !(intersectionState & IntersectionState.Target) &&
19255                        source.flags & (TypeFlags.Primitive | TypeFlags.Object | TypeFlags.Intersection) && source !== globalObjectType &&
19256                        target.flags & (TypeFlags.Object | TypeFlags.Intersection) && isWeakType(target) &&
19257                        (getPropertiesOfType(source).length > 0 || typeHasCallOrConstructSignatures(source));
19258                    const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes);
19259                    if (isPerformingCommonPropertyChecks && !hasCommonProperties(source, target, isComparingJsxAttributes)) {
19260                        if (reportErrors) {
19261                            const sourceString = typeToString(originalSource.aliasSymbol ? originalSource : source);
19262                            const targetString = typeToString(originalTarget.aliasSymbol ? originalTarget : target);
19263                            const calls = getSignaturesOfType(source, SignatureKind.Call);
19264                            const constructs = getSignaturesOfType(source, SignatureKind.Construct);
19265                            if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, RecursionFlags.Source, /*reportErrors*/ false) ||
19266                                constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, RecursionFlags.Source, /*reportErrors*/ false)) {
19267                                reportError(Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, sourceString, targetString);
19268                            }
19269                            else {
19270                                reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, sourceString, targetString);
19271                            }
19272                        }
19273                        return Ternary.False;
19274                    }
19275
19276                    traceUnionsOrIntersectionsTooLarge(source, target);
19277
19278                    const skipCaching = source.flags & TypeFlags.Union && (source as UnionType).types.length < 4 && !(target.flags & TypeFlags.Union) ||
19279                        target.flags & TypeFlags.Union && (target as UnionType).types.length < 4 && !(source.flags & TypeFlags.StructuredOrInstantiable);
19280                    const result = skipCaching ?
19281                        unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState) :
19282                        recursiveTypeRelatedTo(source, target, reportErrors, intersectionState, recursionFlags);
19283                    if (result) {
19284                        return result;
19285                    }
19286                }
19287
19288                if (reportErrors) {
19289                    reportErrorResults(originalSource, originalTarget, source, target, headMessage);
19290                }
19291                return Ternary.False;
19292            }
19293
19294            function reportErrorResults(originalSource: Type, originalTarget: Type, source: Type, target: Type, headMessage: DiagnosticMessage | undefined) {
19295                const sourceHasBase = !!getSingleBaseForNonAugmentingSubtype(originalSource);
19296                const targetHasBase = !!getSingleBaseForNonAugmentingSubtype(originalTarget);
19297                source = (originalSource.aliasSymbol || sourceHasBase) ? originalSource : source;
19298                target = (originalTarget.aliasSymbol || targetHasBase) ? originalTarget : target;
19299                let maybeSuppress = overrideNextErrorInfo > 0;
19300                if (maybeSuppress) {
19301                    overrideNextErrorInfo--;
19302                }
19303                if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
19304                    const currentError = errorInfo;
19305                    tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ true);
19306                    if (errorInfo !== currentError) {
19307                        maybeSuppress = !!errorInfo;
19308                    }
19309                }
19310                if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) {
19311                    tryElaborateErrorsForPrimitivesAndObjects(source, target);
19312                }
19313                else if (source.symbol && source.flags & TypeFlags.Object && globalObjectType === source) {
19314                    reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead);
19315                }
19316                else if (getObjectFlags(source) & ObjectFlags.JsxAttributes && target.flags & TypeFlags.Intersection) {
19317                    const targetTypes = (target as IntersectionType).types;
19318                    const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, errorNode);
19319                    const intrinsicClassAttributes = getJsxType(JsxNames.IntrinsicClassAttributes, errorNode);
19320                    if (!isErrorType(intrinsicAttributes) && !isErrorType(intrinsicClassAttributes) &&
19321                        (contains(targetTypes, intrinsicAttributes) || contains(targetTypes, intrinsicClassAttributes))) {
19322                        // do not report top error
19323                        return;
19324                    }
19325                }
19326                else {
19327                    errorInfo = elaborateNeverIntersection(errorInfo, originalTarget);
19328                }
19329                if (!headMessage && maybeSuppress) {
19330                    lastSkippedInfo = [source, target];
19331                    // Used by, eg, missing property checking to replace the top-level message with a more informative one
19332                    return;
19333                }
19334                reportRelationError(headMessage, source, target);
19335                if (source.flags & TypeFlags.TypeParameter && source.symbol?.declarations?.[0] && !getConstraintOfType(source as TypeVariable)) {
19336                    const syntheticParam = cloneTypeParameter(source as TypeParameter);
19337                    syntheticParam.constraint = instantiateType(target, makeUnaryTypeMapper(source, syntheticParam));
19338                    if (hasNonCircularBaseConstraint(syntheticParam)) {
19339                        const targetConstraintString = typeToString(target, source.symbol.declarations[0]);
19340                        associateRelatedInfo(createDiagnosticForNode(source.symbol.declarations[0], Diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString));
19341                    }
19342                }
19343            }
19344
19345            function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void {
19346                if (!tracing) {
19347                    return;
19348                }
19349
19350                if ((source.flags & TypeFlags.UnionOrIntersection) && (target.flags & TypeFlags.UnionOrIntersection)) {
19351                    const sourceUnionOrIntersection = source as UnionOrIntersectionType;
19352                    const targetUnionOrIntersection = target as UnionOrIntersectionType;
19353
19354                    if (sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags & ObjectFlags.PrimitiveUnion) {
19355                        // There's a fast path for comparing primitive unions
19356                        return;
19357                    }
19358
19359                    const sourceSize = sourceUnionOrIntersection.types.length;
19360                    const targetSize = targetUnionOrIntersection.types.length;
19361                    if (sourceSize * targetSize > 1E6) {
19362                        tracing.instant(tracing.Phase.CheckTypes, "traceUnionsOrIntersectionsTooLarge_DepthLimit", {
19363                            sourceId: source.id,
19364                            sourceSize,
19365                            targetId: target.id,
19366                            targetSize,
19367                            pos: errorNode?.pos,
19368                            end: errorNode?.end
19369                        });
19370                    }
19371                }
19372            }
19373
19374            function getTypeOfPropertyInTypes(types: Type[], name: __String) {
19375                const appendPropType = (propTypes: Type[] | undefined, type: Type) => {
19376                    type = getApparentType(type);
19377                    const prop = type.flags & TypeFlags.UnionOrIntersection ? getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name) : getPropertyOfObjectType(type, name);
19378                    const propType = prop && getTypeOfSymbol(prop) || getApplicableIndexInfoForName(type, name)?.type || undefinedType;
19379                    return append(propTypes, propType);
19380                };
19381                return getUnionType(reduceLeft(types, appendPropType, /*initial*/ undefined) || emptyArray);
19382            }
19383
19384            function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
19385                if (!isExcessPropertyCheckTarget(target) || !noImplicitAny && getObjectFlags(target) & ObjectFlags.JSLiteral) {
19386                    return false; // Disable excess property checks on JS literals to simulate having an implicit "index signature" - but only outside of noImplicitAny
19387                }
19388                const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes);
19389                if ((relation === assignableRelation || relation === comparableRelation) &&
19390                    (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) {
19391                    return false;
19392                }
19393                let reducedTarget = target;
19394                let checkTypes: Type[] | undefined;
19395                if (target.flags & TypeFlags.Union) {
19396                    reducedTarget = findMatchingDiscriminantType(source, target as UnionType, isRelatedTo) || filterPrimitivesIfContainsNonPrimitive(target as UnionType);
19397                    checkTypes = reducedTarget.flags & TypeFlags.Union ? (reducedTarget as UnionType).types : [reducedTarget];
19398                }
19399                for (const prop of getPropertiesOfType(source)) {
19400                    if (shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop)) {
19401                        if (!isKnownProperty(reducedTarget, prop.escapedName, isComparingJsxAttributes)) {
19402                            if (reportErrors) {
19403                                // Report error in terms of object types in the target as those are the only ones
19404                                // we check in isKnownProperty.
19405                                const errorTarget = filterType(reducedTarget, isExcessPropertyCheckTarget);
19406                                // We know *exactly* where things went wrong when comparing the types.
19407                                // Use this property as the error node as this will be more helpful in
19408                                // reasoning about what went wrong.
19409                                if (!errorNode) return Debug.fail();
19410                                if (isJsxAttributes(errorNode) || isJsxOpeningLikeElement(errorNode) || isJsxOpeningLikeElement(errorNode.parent)) {
19411                                    // JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal.
19412                                    // However, using an object-literal error message will be very confusing to the users so we give different a message.
19413                                    if (prop.valueDeclaration && isJsxAttribute(prop.valueDeclaration) && getSourceFileOfNode(errorNode) === getSourceFileOfNode(prop.valueDeclaration.name)) {
19414                                        // Note that extraneous children (as in `<NoChild>extra</NoChild>`) don't pass this check,
19415                                        // since `children` is a SyntaxKind.PropertySignature instead of a SyntaxKind.JsxAttribute.
19416                                        errorNode = prop.valueDeclaration.name;
19417                                    }
19418                                    const propName = symbolToString(prop);
19419                                    const suggestionSymbol = getSuggestedSymbolForNonexistentJSXAttribute(propName, errorTarget);
19420                                    const suggestion = suggestionSymbol ? symbolToString(suggestionSymbol) : undefined;
19421                                    if (suggestion) {
19422                                        reportError(Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName, typeToString(errorTarget), suggestion);
19423                                    }
19424                                    else {
19425                                        reportError(Diagnostics.Property_0_does_not_exist_on_type_1, propName, typeToString(errorTarget));
19426                                    }
19427                                }
19428                                else {
19429                                    // use the property's value declaration if the property is assigned inside the literal itself
19430                                    const objectLiteralDeclaration = source.symbol?.declarations && firstOrUndefined(source.symbol.declarations);
19431                                    let suggestion: string | undefined;
19432                                    if (prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration) && getSourceFileOfNode(objectLiteralDeclaration) === getSourceFileOfNode(errorNode)) {
19433                                        const propDeclaration = prop.valueDeclaration as ObjectLiteralElementLike;
19434                                        Debug.assertNode(propDeclaration, isObjectLiteralElementLike);
19435
19436                                        errorNode = propDeclaration;
19437
19438                                        const name = propDeclaration.name!;
19439                                        if (isIdentifier(name)) {
19440                                            suggestion = getSuggestionForNonexistentProperty(name, errorTarget);
19441                                        }
19442                                    }
19443                                    if (suggestion !== undefined) {
19444                                        reportError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2,
19445                                            symbolToString(prop), typeToString(errorTarget), suggestion);
19446                                    }
19447                                    else {
19448                                        reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
19449                                            symbolToString(prop), typeToString(errorTarget));
19450                                    }
19451                                }
19452                            }
19453                            return true;
19454                        }
19455                        if (checkTypes && !isRelatedTo(getTypeOfSymbol(prop), getTypeOfPropertyInTypes(checkTypes, prop.escapedName), RecursionFlags.Both, reportErrors)) {
19456                            if (reportErrors) {
19457                                reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(prop));
19458                            }
19459                            return true;
19460                        }
19461                    }
19462                }
19463                return false;
19464            }
19465
19466            function shouldCheckAsExcessProperty(prop: Symbol, container: Symbol) {
19467                return prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration;
19468            }
19469
19470            function unionOrIntersectionRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
19471                // Note that these checks are specifically ordered to produce correct results. In particular,
19472                // we need to deconstruct unions before intersections (because unions are always at the top),
19473                // and we need to handle "each" relations before "some" relations for the same kind of type.
19474                if (source.flags & TypeFlags.Union) {
19475                    return relation === comparableRelation ?
19476                        someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState) :
19477                        eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState);
19478                }
19479                if (target.flags & TypeFlags.Union) {
19480                    return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
19481                }
19482                if (target.flags & TypeFlags.Intersection) {
19483                    return typeRelatedToEachType(source, target as IntersectionType, reportErrors, IntersectionState.Target);
19484                }
19485                // Source is an intersection. For the comparable relation, if the target is a primitive type we hoist the
19486                // constraints of all non-primitive types in the source into a new intersection. We do this because the
19487                // intersection may further constrain the constraints of the non-primitive types. For example, given a type
19488                // parameter 'T extends 1 | 2', the intersection 'T & 1' should be reduced to '1' such that it doesn't
19489                // appear to be comparable to '2'.
19490                if (relation === comparableRelation && target.flags & TypeFlags.Primitive) {
19491                    const constraints = sameMap((source as IntersectionType).types, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(t) || unknownType : t);
19492                    if (constraints !== (source as IntersectionType).types) {
19493                        source = getIntersectionType(constraints);
19494                        if (source.flags & TypeFlags.Never) {
19495                            return Ternary.False;
19496                        }
19497                        if (!(source.flags & TypeFlags.Intersection)) {
19498                            return isRelatedTo(source, target, RecursionFlags.Source, /*reportErrors*/ false) ||
19499                                isRelatedTo(target, source, RecursionFlags.Source, /*reportErrors*/ false);
19500                        }
19501                    }
19502                }
19503                // Check to see if any constituents of the intersection are immediately related to the target.
19504                // Don't report errors though. Elaborating on whether a source constituent is related to the target is
19505                // not actually useful and leads to some confusing error messages. Instead, we rely on the caller
19506                // checking whether the full intersection viewed as an object is related to the target.
19507                return someTypeRelatedToType(source as IntersectionType, target, /*reportErrors*/ false, IntersectionState.Source);
19508            }
19509
19510            function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
19511                let result = Ternary.True;
19512                const sourceTypes = source.types;
19513                for (const sourceType of sourceTypes) {
19514                    const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false);
19515                    if (!related) {
19516                        return Ternary.False;
19517                    }
19518                    result &= related;
19519                }
19520                return result;
19521            }
19522
19523            function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
19524                const targetTypes = target.types;
19525                if (target.flags & TypeFlags.Union) {
19526                    if (containsType(targetTypes, source)) {
19527                        return Ternary.True;
19528                    }
19529                    const match = getMatchingUnionConstituentForType(target as UnionType, source);
19530                    if (match) {
19531                        const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false);
19532                        if (related) {
19533                            return related;
19534                        }
19535                    }
19536                }
19537                for (const type of targetTypes) {
19538                    const related = isRelatedTo(source, type, RecursionFlags.Target, /*reportErrors*/ false);
19539                    if (related) {
19540                        return related;
19541                    }
19542                }
19543                if (reportErrors) {
19544                    // Elaborate only if we can find a best matching type in the target union
19545                    const bestMatchingType = getBestMatchingType(source, target, isRelatedTo);
19546                    if (bestMatchingType) {
19547                        isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true);
19548                    }
19549                }
19550                return Ternary.False;
19551            }
19552
19553            function typeRelatedToEachType(source: Type, target: IntersectionType, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
19554                let result = Ternary.True;
19555                const targetTypes = target.types;
19556                for (const targetType of targetTypes) {
19557                    const related = isRelatedTo(source, targetType, RecursionFlags.Target, reportErrors, /*headMessage*/ undefined, intersectionState);
19558                    if (!related) {
19559                        return Ternary.False;
19560                    }
19561                    result &= related;
19562                }
19563                return result;
19564            }
19565
19566            function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
19567                const sourceTypes = source.types;
19568                if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
19569                    return Ternary.True;
19570                }
19571                const len = sourceTypes.length;
19572                for (let i = 0; i < len; i++) {
19573                    const related = isRelatedTo(sourceTypes[i], target, RecursionFlags.Source, reportErrors && i === len - 1, /*headMessage*/ undefined, intersectionState);
19574                    if (related) {
19575                        return related;
19576                    }
19577                }
19578                return Ternary.False;
19579            }
19580
19581            function getUndefinedStrippedTargetIfNeeded(source: Type, target: Type) {
19582                // As a builtin type, `undefined` is a very low type ID - making it almsot always first, making this a very fast check to see
19583                // if we need to strip `undefined` from the target
19584                if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union &&
19585                    !((source as UnionType).types[0].flags & TypeFlags.Undefined) && (target as UnionType).types[0].flags & TypeFlags.Undefined) {
19586                    return extractTypesOfKind(target, ~TypeFlags.Undefined);
19587                }
19588                return target;
19589            }
19590
19591            function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
19592                let result = Ternary.True;
19593                const sourceTypes = source.types;
19594                // We strip `undefined` from the target if the `source` trivially doesn't contain it for our correspondence-checking fastpath
19595                // since `undefined` is frequently added by optionality and would otherwise spoil a potentially useful correspondence
19596                const undefinedStrippedTarget = getUndefinedStrippedTargetIfNeeded(source, target as UnionType);
19597                for (let i = 0; i < sourceTypes.length; i++) {
19598                    const sourceType = sourceTypes[i];
19599                    if (undefinedStrippedTarget.flags & TypeFlags.Union && sourceTypes.length >= (undefinedStrippedTarget as UnionType).types.length && sourceTypes.length % (undefinedStrippedTarget as UnionType).types.length === 0) {
19600                        // many unions are mappings of one another; in such cases, simply comparing members at the same index can shortcut the comparison
19601                        // such unions will have identical lengths, and their corresponding elements will match up. Another common scenario is where a large
19602                        // union has a union of objects intersected with it. In such cases, if the input was, eg `("a" | "b" | "c") & (string | boolean | {} | {whatever})`,
19603                        // the result will have the structure `"a" | "b" | "c" | "a" & {} | "b" & {} | "c" & {} | "a" & {whatever} | "b" & {whatever} | "c" & {whatever}`
19604                        // - the resulting union has a length which is a multiple of the original union, and the elements correspond modulo the length of the original union
19605                        const related = isRelatedTo(sourceType, (undefinedStrippedTarget as UnionType).types[i % (undefinedStrippedTarget as UnionType).types.length], RecursionFlags.Both, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
19606                        if (related) {
19607                            result &= related;
19608                            continue;
19609                        }
19610                    }
19611                    const related = isRelatedTo(sourceType, target, RecursionFlags.Source, reportErrors, /*headMessage*/ undefined, intersectionState);
19612                    if (!related) {
19613                        return Ternary.False;
19614                    }
19615                    result &= related;
19616                }
19617                return result;
19618            }
19619
19620            function typeArgumentsRelatedTo(sources: readonly Type[] = emptyArray, targets: readonly Type[] = emptyArray, variances: readonly VarianceFlags[] = emptyArray, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
19621                if (sources.length !== targets.length && relation === identityRelation) {
19622                    return Ternary.False;
19623                }
19624                const length = sources.length <= targets.length ? sources.length : targets.length;
19625                let result = Ternary.True;
19626                for (let i = 0; i < length; i++) {
19627                    // When variance information isn't available we default to covariance. This happens
19628                    // in the process of computing variance information for recursive types and when
19629                    // comparing 'this' type arguments.
19630                    const varianceFlags = i < variances.length ? variances[i] : VarianceFlags.Covariant;
19631                    const variance = varianceFlags & VarianceFlags.VarianceMask;
19632                    // We ignore arguments for independent type parameters (because they're never witnessed).
19633                    if (variance !== VarianceFlags.Independent) {
19634                        const s = sources[i];
19635                        const t = targets[i];
19636                        let related = Ternary.True;
19637                        if (varianceFlags & VarianceFlags.Unmeasurable) {
19638                            // Even an `Unmeasurable` variance works out without a structural check if the source and target are _identical_.
19639                            // We can't simply assume invariance, because `Unmeasurable` marks nonlinear relations, for example, a relation tained by
19640                            // the `-?` modifier in a mapped type (where, no matter how the inputs are related, the outputs still might not be)
19641                            related = relation === identityRelation ? isRelatedTo(s, t, RecursionFlags.Both, /*reportErrors*/ false) : compareTypesIdentical(s, t);
19642                        }
19643                        else if (variance === VarianceFlags.Covariant) {
19644                            related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
19645                        }
19646                        else if (variance === VarianceFlags.Contravariant) {
19647                            related = isRelatedTo(t, s, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
19648                        }
19649                        else if (variance === VarianceFlags.Bivariant) {
19650                            // In the bivariant case we first compare contravariantly without reporting
19651                            // errors. Then, if that doesn't succeed, we compare covariantly with error
19652                            // reporting. Thus, error elaboration will be based on the the covariant check,
19653                            // which is generally easier to reason about.
19654                            related = isRelatedTo(t, s, RecursionFlags.Both, /*reportErrors*/ false);
19655                            if (!related) {
19656                                related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
19657                            }
19658                        }
19659                        else {
19660                            // In the invariant case we first compare covariantly, and only when that
19661                            // succeeds do we proceed to compare contravariantly. Thus, error elaboration
19662                            // will typically be based on the covariant check.
19663                            related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
19664                            if (related) {
19665                                related &= isRelatedTo(t, s, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
19666                            }
19667                        }
19668                        if (!related) {
19669                            return Ternary.False;
19670                        }
19671                        result &= related;
19672                    }
19673                }
19674                return result;
19675            }
19676
19677            // Determine if possibly recursive types are related. First, check if the result is already available in the global cache.
19678            // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
19679            // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
19680            // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
19681            // and issue an error. Otherwise, actually compare the structure of the two types.
19682            function recursiveTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, recursionFlags: RecursionFlags): Ternary {
19683                if (overflow) {
19684                    return Ternary.False;
19685                }
19686                const id = getRelationKey(source, target, intersectionState, relation, /*ingnoreConstraints*/ false);
19687                const entry = relation.get(id);
19688                if (entry !== undefined) {
19689                    if (reportErrors && entry & RelationComparisonResult.Failed && !(entry & RelationComparisonResult.Reported)) {
19690                        // We are elaborating errors and the cached result is an unreported failure. The result will be reported
19691                        // as a failure, and should be updated as a reported failure by the bottom of this function.
19692                    }
19693                    else {
19694                        if (outofbandVarianceMarkerHandler) {
19695                            // We're in the middle of variance checking - integrate any unmeasurable/unreliable flags from this cached component
19696                            const saved = entry & RelationComparisonResult.ReportsMask;
19697                            if (saved & RelationComparisonResult.ReportsUnmeasurable) {
19698                                instantiateType(source, reportUnmeasurableMapper);
19699                            }
19700                            if (saved & RelationComparisonResult.ReportsUnreliable) {
19701                                instantiateType(source, reportUnreliableMapper);
19702                            }
19703                        }
19704                        return entry & RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False;
19705                    }
19706                }
19707                if (!maybeKeys) {
19708                    maybeKeys = [];
19709                    sourceStack = [];
19710                    targetStack = [];
19711                }
19712                else {
19713                    // A key that starts with "*" is an indication that we have type references that reference constrained
19714                    // type parameters. For such keys we also check against the key we would have gotten if all type parameters
19715                    // were unconstrained.
19716                    const broadestEquivalentId = id.startsWith("*") ? getRelationKey(source, target, intersectionState, relation, /*ignoreConstraints*/ true) : undefined;
19717                    for (let i = 0; i < maybeCount; i++) {
19718                        // If source and target are already being compared, consider them related with assumptions
19719                        if (id === maybeKeys[i] || broadestEquivalentId && broadestEquivalentId === maybeKeys[i]) {
19720                            return Ternary.Maybe;
19721                        }
19722                    }
19723                    if (sourceDepth === 100 || targetDepth === 100) {
19724                        overflow = true;
19725                        return Ternary.False;
19726                    }
19727                }
19728                const maybeStart = maybeCount;
19729                maybeKeys[maybeCount] = id;
19730                maybeCount++;
19731                const saveExpandingFlags = expandingFlags;
19732                if (recursionFlags & RecursionFlags.Source) {
19733                    sourceStack[sourceDepth] = source;
19734                    sourceDepth++;
19735                    if (!(expandingFlags & ExpandingFlags.Source) && isDeeplyNestedType(source, sourceStack, sourceDepth)) expandingFlags |= ExpandingFlags.Source;
19736                }
19737                if (recursionFlags & RecursionFlags.Target) {
19738                    targetStack[targetDepth] = target;
19739                    targetDepth++;
19740                    if (!(expandingFlags & ExpandingFlags.Target) && isDeeplyNestedType(target, targetStack, targetDepth)) expandingFlags |= ExpandingFlags.Target;
19741                }
19742                let originalHandler: typeof outofbandVarianceMarkerHandler;
19743                let propagatingVarianceFlags: RelationComparisonResult = 0;
19744                if (outofbandVarianceMarkerHandler) {
19745                    originalHandler = outofbandVarianceMarkerHandler;
19746                    outofbandVarianceMarkerHandler = onlyUnreliable => {
19747                        propagatingVarianceFlags |= onlyUnreliable ? RelationComparisonResult.ReportsUnreliable : RelationComparisonResult.ReportsUnmeasurable;
19748                        return originalHandler!(onlyUnreliable);
19749                    };
19750                }
19751
19752                let result: Ternary;
19753                if (expandingFlags === ExpandingFlags.Both) {
19754                    tracing?.instant(tracing.Phase.CheckTypes, "recursiveTypeRelatedTo_DepthLimit", {
19755                        sourceId: source.id,
19756                        sourceIdStack: sourceStack.map(t => t.id),
19757                        targetId: target.id,
19758                        targetIdStack: targetStack.map(t => t.id),
19759                        depth: sourceDepth,
19760                        targetDepth
19761                    });
19762                    result = Ternary.Maybe;
19763                }
19764                else {
19765                    tracing?.push(tracing.Phase.CheckTypes, "structuredTypeRelatedTo", { sourceId: source.id, targetId: target.id });
19766                    result = structuredTypeRelatedTo(source, target, reportErrors, intersectionState);
19767                    tracing?.pop();
19768                }
19769
19770                if (outofbandVarianceMarkerHandler) {
19771                    outofbandVarianceMarkerHandler = originalHandler;
19772                }
19773                if (recursionFlags & RecursionFlags.Source) {
19774                    sourceDepth--;
19775                }
19776                if (recursionFlags & RecursionFlags.Target) {
19777                    targetDepth--;
19778                }
19779                expandingFlags = saveExpandingFlags;
19780                if (result) {
19781                    if (result === Ternary.True || (sourceDepth === 0 && targetDepth === 0)) {
19782                        if (result === Ternary.True || result === Ternary.Maybe) {
19783                            // If result is definitely true, record all maybe keys as having succeeded. Also, record Ternary.Maybe
19784                            // results as having succeeded once we reach depth 0, but never record Ternary.Unknown results.
19785                            for (let i = maybeStart; i < maybeCount; i++) {
19786                                relation.set(maybeKeys[i], RelationComparisonResult.Succeeded | propagatingVarianceFlags);
19787                            }
19788                        }
19789                        maybeCount = maybeStart;
19790                    }
19791                }
19792                else {
19793                    // A false result goes straight into global cache (when something is false under
19794                    // assumptions it will also be false without assumptions)
19795                    relation.set(id, (reportErrors ? RelationComparisonResult.Reported : 0) | RelationComparisonResult.Failed | propagatingVarianceFlags);
19796                    maybeCount = maybeStart;
19797                }
19798                return result;
19799            }
19800
19801            function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
19802                const saveErrorInfo = captureErrorCalculationState();
19803                let result = structuredTypeRelatedToWorker(source, target, reportErrors, intersectionState, saveErrorInfo);
19804                if (relation !== identityRelation) {
19805                    // The combined constraint of an intersection type is the intersection of the constraints of
19806                    // the constituents. When an intersection type contains instantiable types with union type
19807                    // constraints, there are situations where we need to examine the combined constraint. One is
19808                    // when the target is a union type. Another is when the intersection contains types belonging
19809                    // to one of the disjoint domains. For example, given type variables T and U, each with the
19810                    // constraint 'string | number', the combined constraint of 'T & U' is 'string | number' and
19811                    // we need to check this constraint against a union on the target side. Also, given a type
19812                    // variable V constrained to 'string | number', 'V & number' has a combined constraint of
19813                    // 'string & number | number & number' which reduces to just 'number'.
19814                    // This also handles type parameters, as a type parameter with a union constraint compared against a union
19815                    // needs to have its constraint hoisted into an intersection with said type parameter, this way
19816                    // the type param can be compared with itself in the target (with the influence of its constraint to match other parts)
19817                    // For example, if `T extends 1 | 2` and `U extends 2 | 3` and we compare `T & U` to `T & U & (1 | 2 | 3)`
19818                    if (!result && (source.flags & TypeFlags.Intersection || source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.Union)) {
19819                        const constraint = getEffectiveConstraintOfIntersection(source.flags & TypeFlags.Intersection ? (source as IntersectionType).types: [source], !!(target.flags & TypeFlags.Union));
19820                        if (constraint && everyType(constraint, c => c !== source)) { // Skip comparison if expansion contains the source itself
19821                            // TODO: Stack errors so we get a pyramid for the "normal" comparison above, _and_ a second for this
19822                            result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
19823                        }
19824                    }
19825                    // For certain combinations involving intersections and optional, excess, or mismatched properties we need
19826                    // an extra property check where the intersection is viewed as a single object. The following are motivating
19827                    // examples that all should be errors, but aren't without this extra property check:
19828                    //
19829                    //   let obj: { a: { x: string } } & { c: number } = { a: { x: 'hello', y: 2 }, c: 5 };  // Nested excess property
19830                    //
19831                    //   declare let wrong: { a: { y: string } };
19832                    //   let weak: { a?: { x?: number } } & { c?: string } = wrong;  // Nested weak object type
19833                    //
19834                    //   function foo<T extends object>(x: { a?: string }, y: T & { a: boolean }) {
19835                    //     x = y;  // Mismatched property in source intersection
19836                    //   }
19837                    //
19838                    // We suppress recursive intersection property checks because they can generate lots of work when relating
19839                    // recursive intersections that are structurally similar but not exactly identical. See #37854.
19840                    if (result && !inPropertyCheck && (
19841                        target.flags & TypeFlags.Intersection && !isGenericObjectType(target) && source.flags & (TypeFlags.Object | TypeFlags.Intersection) ||
19842                        isNonGenericObjectType(target) && !isArrayOrTupleType(target) && source.flags & TypeFlags.Intersection && getApparentType(source).flags & TypeFlags.StructuredType && !some((source as IntersectionType).types, t => !!(getObjectFlags(t) & ObjectFlags.NonInferrableType)))) {
19843                        inPropertyCheck = true;
19844                        result &= propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.None);
19845                        inPropertyCheck = false;
19846                    }
19847                }
19848                if (result) {
19849                    resetErrorInfo(saveErrorInfo);
19850                }
19851                return result;
19852            }
19853
19854            function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType<typeof captureErrorCalculationState>): Ternary {
19855                let result: Ternary;
19856                let originalErrorInfo: DiagnosticMessageChain | undefined;
19857                let varianceCheckFailed = false;
19858                let sourceFlags = source.flags;
19859                const targetFlags = target.flags;
19860                if (relation === identityRelation) {
19861                    // We've already checked that source.flags and target.flags are identical
19862                    if (sourceFlags & TypeFlags.UnionOrIntersection) {
19863                        let result = eachTypeRelatedToSomeType(source as UnionOrIntersectionType, target as UnionOrIntersectionType);
19864                        if (result) {
19865                            result &= eachTypeRelatedToSomeType(target as UnionOrIntersectionType, source as UnionOrIntersectionType);
19866                        }
19867                        return result;
19868                    }
19869                    if (sourceFlags & TypeFlags.Index) {
19870                        return isRelatedTo((source as IndexType).type, (target as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false);
19871                    }
19872                    if (sourceFlags & TypeFlags.IndexedAccess) {
19873                        if (result = isRelatedTo((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType, RecursionFlags.Both, /*reportErrors*/ false)) {
19874                            if (result &= isRelatedTo((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType, RecursionFlags.Both, /*reportErrors*/ false)) {
19875                                return result;
19876                            }
19877                        }
19878                    }
19879                    if (sourceFlags & TypeFlags.Conditional) {
19880                        if ((source as ConditionalType).root.isDistributive === (target as ConditionalType).root.isDistributive) {
19881                            if (result = isRelatedTo((source as ConditionalType).checkType, (target as ConditionalType).checkType, RecursionFlags.Both, /*reportErrors*/ false)) {
19882                                if (result &= isRelatedTo((source as ConditionalType).extendsType, (target as ConditionalType).extendsType, RecursionFlags.Both, /*reportErrors*/ false)) {
19883                                    if (result &= isRelatedTo(getTrueTypeFromConditionalType(source as ConditionalType), getTrueTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) {
19884                                        if (result &= isRelatedTo(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) {
19885                                            return result;
19886                                        }
19887                                    }
19888                                }
19889                            }
19890                        }
19891                    }
19892                    if (sourceFlags & TypeFlags.Substitution) {
19893                        if (result = isRelatedTo((source as SubstitutionType).baseType, (target as SubstitutionType).baseType, RecursionFlags.Both, /*reportErrors*/ false)) {
19894                            if (result &= isRelatedTo((source as SubstitutionType).constraint, (target as SubstitutionType).constraint, RecursionFlags.Both, /*reportErrors*/ false)) {
19895                                return result;
19896                            }
19897                        }
19898                    }
19899                    if (!(sourceFlags & TypeFlags.Object)) {
19900                        return Ternary.False;
19901                    }
19902                }
19903                else if (sourceFlags & TypeFlags.UnionOrIntersection || targetFlags & TypeFlags.UnionOrIntersection) {
19904                    if (result = unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState)) {
19905                        return result;
19906                    }
19907                    // The ordered decomposition above doesn't handle all cases. Specifically, we also need to handle:
19908                    // Source is instantiable (e.g. source has union or intersection constraint).
19909                    // Source is an object, target is a union (e.g. { a, b: boolean } <=> { a, b: true } | { a, b: false }).
19910                    // Source is an intersection, target is an object (e.g. { a } & { b } <=> { a, b }).
19911                    // Source is an intersection, target is a union (e.g. { a } & { b: boolean } <=> { a, b: true } | { a, b: false }).
19912                    // Source is an intersection, target instantiable (e.g. string & { tag } <=> T["a"] constrained to string & { tag }).
19913                    if (!(sourceFlags & TypeFlags.Instantiable ||
19914                        sourceFlags & TypeFlags.Object && targetFlags & TypeFlags.Union ||
19915                        sourceFlags & TypeFlags.Intersection && targetFlags & (TypeFlags.Object | TypeFlags.Union | TypeFlags.Instantiable))) {
19916                        return Ternary.False;
19917                    }
19918                }
19919
19920                // We limit alias variance probing to only object and conditional types since their alias behavior
19921                // is more predictable than other, interned types, which may or may not have an alias depending on
19922                // the order in which things were checked.
19923                if (sourceFlags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol && source.aliasTypeArguments &&
19924                    source.aliasSymbol === target.aliasSymbol && !(isMarkerType(source) || isMarkerType(target))) {
19925                    const variances = getAliasVariances(source.aliasSymbol);
19926                    if (variances === emptyArray) {
19927                        return Ternary.Unknown;
19928                    }
19929                    const varianceResult = relateVariances(source.aliasTypeArguments, target.aliasTypeArguments, variances, intersectionState);
19930                    if (varianceResult !== undefined) {
19931                        return varianceResult;
19932                    }
19933                }
19934
19935                // For a generic type T and a type U that is assignable to T, [...U] is assignable to T, U is assignable to readonly [...T],
19936                // and U is assignable to [...T] when U is constrained to a mutable array or tuple type.
19937                if (isSingleElementGenericTupleType(source) && !source.target.readonly && (result = isRelatedTo(getTypeArguments(source)[0], target, RecursionFlags.Source)) ||
19938                    isSingleElementGenericTupleType(target) && (target.target.readonly || isMutableArrayOrTuple(getBaseConstraintOfType(source) || source)) && (result = isRelatedTo(source, getTypeArguments(target)[0], RecursionFlags.Target))) {
19939                    return result;
19940                }
19941
19942                if (targetFlags & TypeFlags.TypeParameter) {
19943                    // A source type { [P in Q]: X } is related to a target type T if keyof T is related to Q and X is related to T[Q].
19944                    if (getObjectFlags(source) & ObjectFlags.Mapped && !(source as MappedType).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(source as MappedType), RecursionFlags.Both)) {
19945
19946                        if (!(getMappedTypeModifiers(source as MappedType) & MappedTypeModifiers.IncludeOptional)) {
19947                            const templateType = getTemplateTypeFromMappedType(source as MappedType);
19948                            const indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source as MappedType));
19949                            if (result = isRelatedTo(templateType, indexedAccessType, RecursionFlags.Both, reportErrors)) {
19950                                return result;
19951                            }
19952                        }
19953                    }
19954                    if (relation === comparableRelation && sourceFlags & TypeFlags.TypeParameter) {
19955                        // This is a carve-out in comparability to essentially forbid comparing a type parameter
19956                        // with another type parameter unless one extends the other. (Remember: comparability is mostly bidirectional!)
19957                        let constraint = getConstraintOfTypeParameter(source);
19958                        if (constraint && hasNonCircularBaseConstraint(source)) {
19959                            while (constraint && someType(constraint, c => !!(c.flags & TypeFlags.TypeParameter))) {
19960                                if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false)) {
19961                                    return result;
19962                                }
19963                                constraint = getConstraintOfTypeParameter(constraint);
19964                            }
19965                        }
19966                        return Ternary.False;
19967                    }
19968                }
19969                else if (targetFlags & TypeFlags.Index) {
19970                    const targetType = (target as IndexType).type;
19971                    // A keyof S is related to a keyof T if T is related to S.
19972                    if (sourceFlags & TypeFlags.Index) {
19973                        if (result = isRelatedTo(targetType, (source as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false)) {
19974                            return result;
19975                        }
19976                    }
19977                    if (isTupleType(targetType)) {
19978                        // An index type can have a tuple type target when the tuple type contains variadic elements.
19979                        // Check if the source is related to the known keys of the tuple type.
19980                        if (result = isRelatedTo(source, getKnownKeysOfTupleType(targetType), RecursionFlags.Target, reportErrors)) {
19981                            return result;
19982                        }
19983                    }
19984                    else {
19985                        // A type S is assignable to keyof T if S is assignable to keyof C, where C is the
19986                        // simplified form of T or, if T doesn't simplify, the constraint of T.
19987                        const constraint = getSimplifiedTypeOrConstraint(targetType);
19988                        if (constraint) {
19989                            // We require Ternary.True here such that circular constraints don't cause
19990                            // false positives. For example, given 'T extends { [K in keyof T]: string }',
19991                            // 'keyof T' has itself as its constraint and produces a Ternary.Maybe when
19992                            // related to other types.
19993                            if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), RecursionFlags.Target, reportErrors) === Ternary.True) {
19994                                return Ternary.True;
19995                            }
19996                        }
19997                        else if (isGenericMappedType(targetType)) {
19998                            // generic mapped types that don't simplify or have a constraint still have a very simple set of keys we can compare against
19999                            // - their nameType or constraintType.
20000                            // In many ways, this comparison is a deferred version of what `getIndexTypeForMappedType` does to actually resolve the keys for _non_-generic types
20001
20002                            const nameType = getNameTypeFromMappedType(targetType);
20003                            const constraintType = getConstraintTypeFromMappedType(targetType);
20004                            let targetKeys;
20005                            if (nameType && isMappedTypeWithKeyofConstraintDeclaration(targetType)) {
20006                                // we need to get the apparent mappings and union them with the generic mappings, since some properties may be
20007                                // missing from the `constraintType` which will otherwise be mapped in the object
20008                                const modifiersType = getApparentType(getModifiersTypeFromMappedType(targetType));
20009                                const mappedKeys: Type[] = [];
20010                                forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(
20011                                    modifiersType,
20012                                    TypeFlags.StringOrNumberLiteralOrUnique,
20013                                    /*stringsOnly*/ false,
20014                                    t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t)))
20015                                );
20016                                // We still need to include the non-apparent (and thus still generic) keys in the target side of the comparison (in case they're in the source side)
20017                                targetKeys = getUnionType([...mappedKeys, nameType]);
20018                            }
20019                            else {
20020                                targetKeys = nameType || constraintType;
20021                            }
20022                            if (isRelatedTo(source, targetKeys, RecursionFlags.Target, reportErrors) === Ternary.True) {
20023                                return Ternary.True;
20024                            }
20025                        }
20026                    }
20027                }
20028                else if (targetFlags & TypeFlags.IndexedAccess) {
20029                    if (sourceFlags & TypeFlags.IndexedAccess) {
20030                        // Relate components directly before falling back to constraint relationships
20031                        // A type S[K] is related to a type T[J] if S is related to T and K is related to J.
20032                        if (result = isRelatedTo((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType, RecursionFlags.Both, reportErrors)) {
20033                            result &= isRelatedTo((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType, RecursionFlags.Both, reportErrors);
20034                        }
20035                        if (result) {
20036                            return result;
20037                        }
20038                        if (reportErrors) {
20039                            originalErrorInfo = errorInfo;
20040                        }
20041                    }
20042                    // A type S is related to a type T[K] if S is related to C, where C is the base
20043                    // constraint of T[K] for writing.
20044                    if (relation === assignableRelation || relation === comparableRelation) {
20045                        const objectType = (target as IndexedAccessType).objectType;
20046                        const indexType = (target as IndexedAccessType).indexType;
20047                        const baseObjectType = getBaseConstraintOfType(objectType) || objectType;
20048                        const baseIndexType = getBaseConstraintOfType(indexType) || indexType;
20049                        if (!isGenericObjectType(baseObjectType) && !isGenericIndexType(baseIndexType)) {
20050                            const accessFlags = AccessFlags.Writing | (baseObjectType !== objectType ? AccessFlags.NoIndexSignatures : 0);
20051                            const constraint = getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, accessFlags);
20052                            if (constraint) {
20053                                if (reportErrors && originalErrorInfo) {
20054                                    // create a new chain for the constraint error
20055                                    resetErrorInfo(saveErrorInfo);
20056                                }
20057                                if (result = isRelatedTo(source, constraint, RecursionFlags.Target, reportErrors, /* headMessage */ undefined, intersectionState)) {
20058                                    return result;
20059                                }
20060                                // prefer the shorter chain of the constraint comparison chain, and the direct comparison chain
20061                                if (reportErrors && originalErrorInfo && errorInfo) {
20062                                    errorInfo = countMessageChainBreadth([originalErrorInfo]) <= countMessageChainBreadth([errorInfo]) ? originalErrorInfo : errorInfo;
20063                                }
20064                            }
20065                        }
20066                    }
20067                    if (reportErrors) {
20068                        originalErrorInfo = undefined;
20069                    }
20070                }
20071                else if (isGenericMappedType(target) && relation !== identityRelation) {
20072                    // Check if source type `S` is related to target type `{ [P in Q]: T }` or `{ [P in Q as R]: T}`.
20073                    const keysRemapped = !!target.declaration.nameType;
20074                    const templateType = getTemplateTypeFromMappedType(target);
20075                    const modifiers = getMappedTypeModifiers(target);
20076                    if (!(modifiers & MappedTypeModifiers.ExcludeOptional)) {
20077                        // If the mapped type has shape `{ [P in Q]: T[P] }`,
20078                        // source `S` is related to target if `T` = `S`, i.e. `S` is related to `{ [P in Q]: S[P] }`.
20079                        if (!keysRemapped && templateType.flags & TypeFlags.IndexedAccess && (templateType as IndexedAccessType).objectType === source &&
20080                            (templateType as IndexedAccessType).indexType === getTypeParameterFromMappedType(target)) {
20081                            return Ternary.True;
20082                        }
20083                        if (!isGenericMappedType(source)) {
20084                            // If target has shape `{ [P in Q as R]: T}`, then its keys have type `R`.
20085                            // If target has shape `{ [P in Q]: T }`, then its keys have type `Q`.
20086                            const targetKeys = keysRemapped ? getNameTypeFromMappedType(target)! : getConstraintTypeFromMappedType(target);
20087                            // Type of the keys of source type `S`, i.e. `keyof S`.
20088                            const sourceKeys = getIndexType(source, /*stringsOnly*/ undefined, /*noIndexSignatures*/ true);
20089                            const includeOptional = modifiers & MappedTypeModifiers.IncludeOptional;
20090                            const filteredByApplicability = includeOptional ? intersectTypes(targetKeys, sourceKeys) : undefined;
20091                            // A source type `S` is related to a target type `{ [P in Q]: T }` if `Q` is related to `keyof S` and `S[Q]` is related to `T`.
20092                            // A source type `S` is related to a target type `{ [P in Q as R]: T }` if `R` is related to `keyof S` and `S[R]` is related to `T.
20093                            // A source type `S` is related to a target type `{ [P in Q]?: T }` if some constituent `Q'` of `Q` is related to `keyof S` and `S[Q']` is related to `T`.
20094                            // A source type `S` is related to a target type `{ [P in Q as R]?: T }` if some constituent `R'` of `R` is related to `keyof S` and `S[R']` is related to `T`.
20095                            if (includeOptional
20096                                ? !(filteredByApplicability!.flags & TypeFlags.Never)
20097                                : isRelatedTo(targetKeys, sourceKeys, RecursionFlags.Both)) {
20098                                const templateType = getTemplateTypeFromMappedType(target);
20099                                const typeParameter = getTypeParameterFromMappedType(target);
20100
20101                                // Fastpath: When the template type has the form `Obj[P]` where `P` is the mapped type parameter, directly compare source `S` with `Obj`
20102                                // to avoid creating the (potentially very large) number of new intermediate types made by manufacturing `S[P]`.
20103                                const nonNullComponent = extractTypesOfKind(templateType, ~TypeFlags.Nullable);
20104                                if (!keysRemapped && nonNullComponent.flags & TypeFlags.IndexedAccess && (nonNullComponent as IndexedAccessType).indexType === typeParameter) {
20105                                    if (result = isRelatedTo(source, (nonNullComponent as IndexedAccessType).objectType, RecursionFlags.Target, reportErrors)) {
20106                                        return result;
20107                                    }
20108                                }
20109                                else {
20110                                    // We need to compare the type of a property on the source type `S` to the type of the same property on the target type,
20111                                    // so we need to construct an indexing type representing a property, and then use indexing type to index the source type for comparison.
20112
20113                                    // If the target type has shape `{ [P in Q]: T }`, then a property of the target has type `P`.
20114                                    // If the target type has shape `{ [P in Q]?: T }`, then a property of the target has type `P`,
20115                                    // but the property is optional, so we only want to compare properties `P` that are common between `keyof S` and `Q`.
20116                                    // If the target type has shape `{ [P in Q as R]: T }`, then a property of the target has type `R`.
20117                                    // If the target type has shape `{ [P in Q as R]?: T }`, then a property of the target has type `R`,
20118                                    // but the property is optional, so we only want to compare properties `R` that are common between `keyof S` and `R`.
20119                                    const indexingType = keysRemapped
20120                                        ? (filteredByApplicability || targetKeys)
20121                                        : filteredByApplicability
20122                                            ? getIntersectionType([filteredByApplicability, typeParameter])
20123                                            : typeParameter;
20124                                    const indexedAccessType = getIndexedAccessType(source, indexingType);
20125                                    // Compare `S[indexingType]` to `T`, where `T` is the type of a property of the target type.
20126                                    if (result = isRelatedTo(indexedAccessType, templateType, RecursionFlags.Both, reportErrors)) {
20127                                        return result;
20128                                    }
20129                                }
20130                            }
20131                            originalErrorInfo = errorInfo;
20132                            resetErrorInfo(saveErrorInfo);
20133                        }
20134                    }
20135                }
20136                else if (targetFlags & TypeFlags.Conditional) {
20137                    // If we reach 10 levels of nesting for the same conditional type, assume it is an infinitely expanding recursive
20138                    // conditional type and bail out with a Ternary.Maybe result.
20139                    if (isDeeplyNestedType(target, targetStack, targetDepth, 10)) {
20140                        return Ternary.Maybe;
20141                    }
20142                    const c = target as ConditionalType;
20143                    // We check for a relationship to a conditional type target only when the conditional type has no
20144                    // 'infer' positions and is not distributive or is distributive but doesn't reference the check type
20145                    // parameter in either of the result types.
20146                    if (!c.root.inferTypeParameters && !isDistributionDependent(c.root)) {
20147                        // Check if the conditional is always true or always false but still deferred for distribution purposes.
20148                        const skipTrue = !isTypeAssignableTo(getPermissiveInstantiation(c.checkType), getPermissiveInstantiation(c.extendsType));
20149                        const skipFalse = !skipTrue && isTypeAssignableTo(getRestrictiveInstantiation(c.checkType), getRestrictiveInstantiation(c.extendsType));
20150                        // TODO: Find a nice way to include potential conditional type breakdowns in error output, if they seem good (they usually don't)
20151                        if (result = skipTrue ? Ternary.True : isRelatedTo(source, getTrueTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) {
20152                            result &= skipFalse ? Ternary.True : isRelatedTo(source, getFalseTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
20153                            if (result) {
20154                                return result;
20155                            }
20156                        }
20157                    }
20158                }
20159                else if (targetFlags & TypeFlags.TemplateLiteral) {
20160                    if (sourceFlags & TypeFlags.TemplateLiteral) {
20161                        if (relation === comparableRelation) {
20162                            return templateLiteralTypesDefinitelyUnrelated(source as TemplateLiteralType, target as TemplateLiteralType) ? Ternary.False : Ternary.True;
20163                        }
20164                        // Report unreliable variance for type variables referenced in template literal type placeholders.
20165                        // For example, `foo-${number}` is related to `foo-${string}` even though number isn't related to string.
20166                        instantiateType(source, reportUnreliableMapper);
20167                    }
20168                    if (isTypeMatchedByTemplateLiteralType(source, target as TemplateLiteralType)) {
20169                        return Ternary.True;
20170                    }
20171                }
20172                else if (target.flags & TypeFlags.StringMapping) {
20173                    if (!(source.flags & TypeFlags.StringMapping)) {
20174                        if (isMemberOfStringMapping(source, target)) {
20175                            return Ternary.True;
20176                        }
20177                    }
20178                }
20179
20180                if (sourceFlags & TypeFlags.TypeVariable) {
20181                    // IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch
20182                    if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) {
20183                        const constraint = getConstraintOfType(source as TypeVariable) || unknownType;
20184                        // hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed
20185                        if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) {
20186                            return result;
20187                        }
20188                        // slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example
20189                        else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && constraint !== unknownType && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) {
20190                            return result;
20191                        }
20192                        if (isMappedTypeGenericIndexedAccess(source)) {
20193                            // For an indexed access type { [P in K]: E}[X], above we have already explored an instantiation of E with X
20194                            // substituted for P. We also want to explore type { [P in K]: E }[C], where C is the constraint of X.
20195                            const indexConstraint = getConstraintOfType((source as IndexedAccessType).indexType);
20196                            if (indexConstraint) {
20197                                if (result = isRelatedTo(getIndexedAccessType((source as IndexedAccessType).objectType, indexConstraint), target, RecursionFlags.Source, reportErrors)) {
20198                                    return result;
20199                                }
20200                            }
20201                        }
20202                    }
20203                }
20204                else if (sourceFlags & TypeFlags.Index) {
20205                    if (result = isRelatedTo(keyofConstraintType, target, RecursionFlags.Source, reportErrors)) {
20206                        return result;
20207                    }
20208                }
20209                else if (sourceFlags & TypeFlags.TemplateLiteral && !(targetFlags & TypeFlags.Object)) {
20210                    if (!(targetFlags & TypeFlags.TemplateLiteral)) {
20211                        const constraint = getBaseConstraintOfType(source);
20212                        if (constraint && constraint !== source && (result = isRelatedTo(constraint, target, RecursionFlags.Source, reportErrors))) {
20213                            return result;
20214                        }
20215                    }
20216                }
20217                else if (sourceFlags & TypeFlags.StringMapping) {
20218                    if (targetFlags & TypeFlags.StringMapping) {
20219                        if ((source as StringMappingType).symbol !== (target as StringMappingType).symbol) {
20220                            return Ternary.False;
20221                        }
20222                        if (result = isRelatedTo((source as StringMappingType).type, (target as StringMappingType).type, RecursionFlags.Both, reportErrors)) {
20223                            return result;
20224                        }
20225                    }
20226                    else {
20227                        const constraint = getBaseConstraintOfType(source);
20228                        if (constraint && (result = isRelatedTo(constraint, target, RecursionFlags.Source, reportErrors))) {
20229                            return result;
20230                        }
20231                    }
20232                }
20233                else if (sourceFlags & TypeFlags.Conditional) {
20234                    // If we reach 10 levels of nesting for the same conditional type, assume it is an infinitely expanding recursive
20235                    // conditional type and bail out with a Ternary.Maybe result.
20236                    if (isDeeplyNestedType(source, sourceStack, sourceDepth, 10)) {
20237                        return Ternary.Maybe;
20238                    }
20239                    if (targetFlags & TypeFlags.Conditional) {
20240                        // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if
20241                        // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2,
20242                        // and Y1 is related to Y2.
20243                        const sourceParams = (source as ConditionalType).root.inferTypeParameters;
20244                        let sourceExtends = (source as ConditionalType).extendsType;
20245                        let mapper: TypeMapper | undefined;
20246                        if (sourceParams) {
20247                            // If the source has infer type parameters, we instantiate them in the context of the target
20248                            const ctx = createInferenceContext(sourceParams, /*signature*/ undefined, InferenceFlags.None, isRelatedToWorker);
20249                            inferTypes(ctx.inferences, (target as ConditionalType).extendsType, sourceExtends, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
20250                            sourceExtends = instantiateType(sourceExtends, ctx.mapper);
20251                            mapper = ctx.mapper;
20252                        }
20253                        if (isTypeIdenticalTo(sourceExtends, (target as ConditionalType).extendsType) &&
20254                            (isRelatedTo((source as ConditionalType).checkType, (target as ConditionalType).checkType, RecursionFlags.Both) || isRelatedTo((target as ConditionalType).checkType, (source as ConditionalType).checkType, RecursionFlags.Both))) {
20255                            if (result = isRelatedTo(instantiateType(getTrueTypeFromConditionalType(source as ConditionalType), mapper), getTrueTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, reportErrors)) {
20256                                result &= isRelatedTo(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, reportErrors);
20257                            }
20258                            if (result) {
20259                                return result;
20260                            }
20261                        }
20262                    }
20263                    else {
20264                        // conditionals aren't related to one another via distributive constraint as it is much too inaccurate and allows way
20265                        // more assignments than are desirable (since it maps the source check type to its constraint, it loses information)
20266                        const distributiveConstraint = hasNonCircularBaseConstraint(source) ? getConstraintOfDistributiveConditionalType(source as ConditionalType) : undefined;
20267                        if (distributiveConstraint) {
20268                            if (result = isRelatedTo(distributiveConstraint, target, RecursionFlags.Source, reportErrors)) {
20269                                return result;
20270                            }
20271                        }
20272                    }
20273
20274                    // conditionals _can_ be related to one another via normal constraint, as, eg, `A extends B ? O : never` should be assignable to `O`
20275                    // when `O` is a conditional (`never` is trivially assignable to `O`, as is `O`!).
20276                    const defaultConstraint = getDefaultConstraintOfConditionalType(source as ConditionalType);
20277                    if (defaultConstraint) {
20278                        if (result = isRelatedTo(defaultConstraint, target, RecursionFlags.Source, reportErrors)) {
20279                            return result;
20280                        }
20281                    }
20282                }
20283                else {
20284                    // An empty object type is related to any mapped type that includes a '?' modifier.
20285                    if (relation !== subtypeRelation && relation !== strictSubtypeRelation && isPartialMappedType(target) && isEmptyObjectType(source)) {
20286                        return Ternary.True;
20287                    }
20288                    if (isGenericMappedType(target)) {
20289                        if (isGenericMappedType(source)) {
20290                            if (result = mappedTypeRelatedTo(source, target, reportErrors)) {
20291                                return result;
20292                            }
20293                        }
20294                        return Ternary.False;
20295                    }
20296                    const sourceIsPrimitive = !!(sourceFlags & TypeFlags.Primitive);
20297                    if (relation !== identityRelation) {
20298                        source = getApparentType(source);
20299                        sourceFlags = source.flags;
20300                    }
20301                    else if (isGenericMappedType(source)) {
20302                        return Ternary.False;
20303                    }
20304                    if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target &&
20305                        !isTupleType(source) && !(isMarkerType(source) || isMarkerType(target))) {
20306                        // When strictNullChecks is disabled, the element type of the empty array literal is undefinedWideningType,
20307                        // and an empty array literal wouldn't be assignable to a `never[]` without this check.
20308                        if (isEmptyArrayLiteralType(source)) {
20309                            return Ternary.True;
20310                        }
20311                        // We have type references to the same generic type, and the type references are not marker
20312                        // type references (which are intended by be compared structurally). Obtain the variance
20313                        // information for the type parameters and relate the type arguments accordingly.
20314                        const variances = getVariances((source as TypeReference).target);
20315                        // We return Ternary.Maybe for a recursive invocation of getVariances (signalled by emptyArray). This
20316                        // effectively means we measure variance only from type parameter occurrences that aren't nested in
20317                        // recursive instantiations of the generic type.
20318                        if (variances === emptyArray) {
20319                            return Ternary.Unknown;
20320                        }
20321                        const varianceResult = relateVariances(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), variances, intersectionState);
20322                        if (varianceResult !== undefined) {
20323                            return varianceResult;
20324                        }
20325                    }
20326                    else if (isReadonlyArrayType(target) ? isArrayOrTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
20327                        if (relation !== identityRelation) {
20328                            return isRelatedTo(getIndexTypeOfType(source, numberType) || anyType, getIndexTypeOfType(target, numberType) || anyType, RecursionFlags.Both, reportErrors);
20329                        }
20330                        else {
20331                            // By flags alone, we know that the `target` is a readonly array while the source is a normal array or tuple
20332                            // or `target` is an array and source is a tuple - in both cases the types cannot be identical, by construction
20333                            return Ternary.False;
20334                        }
20335                    }
20336                    // Consider a fresh empty object literal type "closed" under the subtype relationship - this way `{} <- {[idx: string]: any} <- fresh({})`
20337                    // and not `{} <- fresh({}) <- {[idx: string]: any}`
20338                    else if ((relation === subtypeRelation || relation === strictSubtypeRelation) && isEmptyObjectType(target) && getObjectFlags(target) & ObjectFlags.FreshLiteral && !isEmptyObjectType(source)) {
20339                        return Ternary.False;
20340                    }
20341                    // Even if relationship doesn't hold for unions, intersections, or generic type references,
20342                    // it may hold in a structural comparison.
20343                    // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
20344                    // to X. Failing both of those we want to check if the aggregation of A and B's members structurally
20345                    // relates to X. Thus, we include intersection types on the source side here.
20346                    if (sourceFlags & (TypeFlags.Object | TypeFlags.Intersection) && targetFlags & TypeFlags.Object) {
20347                        // Report structural errors only if we haven't reported any errors yet
20348                        const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo.errorInfo && !sourceIsPrimitive;
20349                        result = propertiesRelatedTo(source, target, reportStructuralErrors, /*excludedProperties*/ undefined, intersectionState);
20350                        if (result) {
20351                            result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors);
20352                            if (result) {
20353                                result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportStructuralErrors);
20354                                if (result) {
20355                                    result &= indexSignaturesRelatedTo(source, target, sourceIsPrimitive, reportStructuralErrors, intersectionState);
20356                                }
20357                            }
20358                        }
20359                        if (varianceCheckFailed && result) {
20360                            errorInfo = originalErrorInfo || errorInfo || saveErrorInfo.errorInfo; // Use variance error (there is no structural one) and return false
20361                        }
20362                        else if (result) {
20363                            return result;
20364                        }
20365                    }
20366                    // If S is an object type and T is a discriminated union, S may be related to T if
20367                    // there exists a constituent of T for every combination of the discriminants of S
20368                    // with respect to T. We do not report errors here, as we will use the existing
20369                    // error result from checking each constituent of the union.
20370                    if (sourceFlags & (TypeFlags.Object | TypeFlags.Intersection) && targetFlags & TypeFlags.Union) {
20371                        const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution);
20372                        if (objectOnlyTarget.flags & TypeFlags.Union) {
20373                            const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType);
20374                            if (result) {
20375                                return result;
20376                            }
20377                        }
20378                    }
20379                }
20380                return Ternary.False;
20381
20382                function countMessageChainBreadth(info: DiagnosticMessageChain[] | undefined): number {
20383                    if (!info) return 0;
20384                    return reduceLeft(info, (value, chain) => value + 1 + countMessageChainBreadth(chain.next), 0);
20385                }
20386
20387                function relateVariances(sourceTypeArguments: readonly Type[] | undefined, targetTypeArguments: readonly Type[] | undefined, variances: VarianceFlags[], intersectionState: IntersectionState) {
20388                    if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors, intersectionState)) {
20389                        return result;
20390                    }
20391                    if (some(variances, v => !!(v & VarianceFlags.AllowsStructuralFallback))) {
20392                        // If some type parameter was `Unmeasurable` or `Unreliable`, and we couldn't pass by assuming it was identical, then we
20393                        // have to allow a structural fallback check
20394                        // We elide the variance-based error elaborations, since those might not be too helpful, since we'll potentially
20395                        // be assuming identity of the type parameter.
20396                        originalErrorInfo = undefined;
20397                        resetErrorInfo(saveErrorInfo);
20398                        return undefined;
20399                    }
20400                    const allowStructuralFallback = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances);
20401                    varianceCheckFailed = !allowStructuralFallback;
20402                    // The type arguments did not relate appropriately, but it may be because we have no variance
20403                    // information (in which case typeArgumentsRelatedTo defaulted to covariance for all type
20404                    // arguments). It might also be the case that the target type has a 'void' type argument for
20405                    // a covariant type parameter that is only used in return positions within the generic type
20406                    // (in which case any type argument is permitted on the source side). In those cases we proceed
20407                    // with a structural comparison. Otherwise, we know for certain the instantiations aren't
20408                    // related and we can return here.
20409                    if (variances !== emptyArray && !allowStructuralFallback) {
20410                        // In some cases generic types that are covariant in regular type checking mode become
20411                        // invariant in --strictFunctionTypes mode because one or more type parameters are used in
20412                        // both co- and contravariant positions. In order to make it easier to diagnose *why* such
20413                        // types are invariant, if any of the type parameters are invariant we reset the reported
20414                        // errors and instead force a structural comparison (which will include elaborations that
20415                        // reveal the reason).
20416                        // We can switch on `reportErrors` here, since varianceCheckFailed guarantees we return `False`,
20417                        // we can return `False` early here to skip calculating the structural error message we don't need.
20418                        if (varianceCheckFailed && !(reportErrors && some(variances, v => (v & VarianceFlags.VarianceMask) === VarianceFlags.Invariant))) {
20419                            return Ternary.False;
20420                        }
20421                        // We remember the original error information so we can restore it in case the structural
20422                        // comparison unexpectedly succeeds. This can happen when the structural comparison result
20423                        // is a Ternary.Maybe for example caused by the recursion depth limiter.
20424                        originalErrorInfo = errorInfo;
20425                        resetErrorInfo(saveErrorInfo);
20426                    }
20427                }
20428            }
20429
20430            // A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is
20431            // related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice
20432            // that S and T are contra-variant whereas X and Y are co-variant.
20433            function mappedTypeRelatedTo(source: MappedType, target: MappedType, reportErrors: boolean): Ternary {
20434                const modifiersRelated = relation === comparableRelation || (relation === identityRelation ? getMappedTypeModifiers(source) === getMappedTypeModifiers(target) :
20435                    getCombinedMappedTypeOptionality(source) <= getCombinedMappedTypeOptionality(target));
20436                if (modifiersRelated) {
20437                    let result: Ternary;
20438                    const targetConstraint = getConstraintTypeFromMappedType(target);
20439                    const sourceConstraint = instantiateType(getConstraintTypeFromMappedType(source), getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMapper : reportUnreliableMapper);
20440                    if (result = isRelatedTo(targetConstraint, sourceConstraint, RecursionFlags.Both, reportErrors)) {
20441                        const mapper = createTypeMapper([getTypeParameterFromMappedType(source)], [getTypeParameterFromMappedType(target)]);
20442                        if (instantiateType(getNameTypeFromMappedType(source), mapper) === instantiateType(getNameTypeFromMappedType(target), mapper)) {
20443                            return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), RecursionFlags.Both, reportErrors);
20444                        }
20445                    }
20446                }
20447                return Ternary.False;
20448            }
20449
20450            function typeRelatedToDiscriminatedType(source: Type, target: UnionType) {
20451                // 1. Generate the combinations of discriminant properties & types 'source' can satisfy.
20452                //    a. If the number of combinations is above a set limit, the comparison is too complex.
20453                // 2. Filter 'target' to the subset of types whose discriminants exist in the matrix.
20454                //    a. If 'target' does not satisfy all discriminants in the matrix, 'source' is not related.
20455                // 3. For each type in the filtered 'target', determine if all non-discriminant properties of
20456                //    'target' are related to a property in 'source'.
20457                //
20458                // NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts
20459                //       for examples.
20460
20461                const sourceProperties = getPropertiesOfType(source);
20462                const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target);
20463                if (!sourcePropertiesFiltered) return Ternary.False;
20464
20465                // Though we could compute the number of combinations as we generate
20466                // the matrix, this would incur additional memory overhead due to
20467                // array allocations. To reduce this overhead, we first compute
20468                // the number of combinations to ensure we will not surpass our
20469                // fixed limit before incurring the cost of any allocations:
20470                let numCombinations = 1;
20471                for (const sourceProperty of sourcePropertiesFiltered) {
20472                    numCombinations *= countTypes(getNonMissingTypeOfSymbol(sourceProperty));
20473                    if (numCombinations > 25) {
20474                        // We've reached the complexity limit.
20475                        tracing?.instant(tracing.Phase.CheckTypes, "typeRelatedToDiscriminatedType_DepthLimit", { sourceId: source.id, targetId: target.id, numCombinations });
20476                        return Ternary.False;
20477                    }
20478                }
20479
20480                // Compute the set of types for each discriminant property.
20481                const sourceDiscriminantTypes: Type[][] = new Array<Type[]>(sourcePropertiesFiltered.length);
20482                const excludedProperties = new Set<__String>();
20483                for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
20484                    const sourceProperty = sourcePropertiesFiltered[i];
20485                    const sourcePropertyType = getNonMissingTypeOfSymbol(sourceProperty);
20486                    sourceDiscriminantTypes[i] = sourcePropertyType.flags & TypeFlags.Union
20487                        ? (sourcePropertyType as UnionType).types
20488                        : [sourcePropertyType];
20489                    excludedProperties.add(sourceProperty.escapedName);
20490                }
20491
20492                // Match each combination of the cartesian product of discriminant properties to one or more
20493                // constituents of 'target'. If any combination does not have a match then 'source' is not relatable.
20494                const discriminantCombinations = cartesianProduct(sourceDiscriminantTypes);
20495                const matchingTypes: Type[] = [];
20496                for (const combination of discriminantCombinations) {
20497                    let hasMatch = false;
20498                    outer: for (const type of target.types) {
20499                        for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
20500                            const sourceProperty = sourcePropertiesFiltered[i];
20501                            const targetProperty = getPropertyOfType(type, sourceProperty.escapedName);
20502                            if (!targetProperty) continue outer;
20503                            if (sourceProperty === targetProperty) continue;
20504                            // We compare the source property to the target in the context of a single discriminant type.
20505                            const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
20506                            // If the target property could not be found, or if the properties were not related,
20507                            // then this constituent is not a match.
20508                            if (!related) {
20509                                continue outer;
20510                            }
20511                        }
20512                        pushIfUnique(matchingTypes, type, equateValues);
20513                        hasMatch = true;
20514                    }
20515                    if (!hasMatch) {
20516                        // We failed to match any type for this combination.
20517                        return Ternary.False;
20518                    }
20519                }
20520
20521                // Compare the remaining non-discriminant properties of each match.
20522                let result = Ternary.True;
20523                for (const type of matchingTypes) {
20524                    result &= propertiesRelatedTo(source, type, /*reportErrors*/ false, excludedProperties, IntersectionState.None);
20525                    if (result) {
20526                        result &= signaturesRelatedTo(source, type, SignatureKind.Call, /*reportStructuralErrors*/ false);
20527                        if (result) {
20528                            result &= signaturesRelatedTo(source, type, SignatureKind.Construct, /*reportStructuralErrors*/ false);
20529                            if (result && !(isTupleType(source) && isTupleType(type))) {
20530                                // Comparing numeric index types when both `source` and `type` are tuples is unnecessary as the
20531                                // element types should be sufficiently covered by `propertiesRelatedTo`. It also causes problems
20532                                // with index type assignability as the types for the excluded discriminants are still included
20533                                // in the index type.
20534                                result &= indexSignaturesRelatedTo(source, type, /*sourceIsPrimitive*/ false, /*reportStructuralErrors*/ false, IntersectionState.None);
20535                            }
20536                        }
20537                    }
20538                    if (!result) {
20539                        return result;
20540                    }
20541                }
20542                return result;
20543            }
20544
20545            function excludeProperties(properties: Symbol[], excludedProperties: Set<__String> | undefined) {
20546                if (!excludedProperties || properties.length === 0) return properties;
20547                let result: Symbol[] | undefined;
20548                for (let i = 0; i < properties.length; i++) {
20549                    if (!excludedProperties.has(properties[i].escapedName)) {
20550                        if (result) {
20551                            result.push(properties[i]);
20552                        }
20553                    }
20554                    else if (!result) {
20555                        result = properties.slice(0, i);
20556                    }
20557                }
20558                return result || properties;
20559            }
20560
20561            function isPropertySymbolTypeRelated(sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
20562                const targetIsOptional = strictNullChecks && !!(getCheckFlags(targetProp) & CheckFlags.Partial);
20563                const effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), /*isProperty*/ false, targetIsOptional);
20564                const effectiveSource = getTypeOfSourceProperty(sourceProp);
20565                return isRelatedTo(effectiveSource, effectiveTarget, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
20566            }
20567
20568            function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary {
20569                const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
20570                const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
20571                if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
20572                    if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
20573                        if (reportErrors) {
20574                            if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) {
20575                                reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
20576                            }
20577                            else {
20578                                reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp),
20579                                    typeToString(sourcePropFlags & ModifierFlags.Private ? source : target),
20580                                    typeToString(sourcePropFlags & ModifierFlags.Private ? target : source));
20581                            }
20582                        }
20583                        return Ternary.False;
20584                    }
20585                }
20586                else if (targetPropFlags & ModifierFlags.Protected) {
20587                    if (!isValidOverrideOf(sourceProp, targetProp)) {
20588                        if (reportErrors) {
20589                            reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp),
20590                                typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target));
20591                        }
20592                        return Ternary.False;
20593                    }
20594                }
20595                else if (sourcePropFlags & ModifierFlags.Protected) {
20596                    if (reportErrors) {
20597                        reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2,
20598                            symbolToString(targetProp), typeToString(source), typeToString(target));
20599                    }
20600                    return Ternary.False;
20601                }
20602
20603                // Ensure {readonly a: whatever} is not a subtype of {a: whatever},
20604                // while {a: whatever} is a subtype of {readonly a: whatever}.
20605                // This ensures the subtype relationship is ordered, and preventing declaration order
20606                // from deciding which type "wins" in union subtype reduction.
20607                // They're still assignable to one another, since `readonly` doesn't affect assignability.
20608                // This is only applied during the strictSubtypeRelation -- currently used in subtype reduction
20609                if (
20610                    relation === strictSubtypeRelation &&
20611                    isReadonlySymbol(sourceProp) && !isReadonlySymbol(targetProp)
20612                ) {
20613                    return Ternary.False;
20614                }
20615                // If the target comes from a partial union prop, allow `undefined` in the target type
20616                const related = isPropertySymbolTypeRelated(sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState);
20617                if (!related) {
20618                    if (reportErrors) {
20619                        reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
20620                    }
20621                    return Ternary.False;
20622                }
20623                // When checking for comparability, be more lenient with optional properties.
20624                if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && targetProp.flags & SymbolFlags.ClassMember && !(targetProp.flags & SymbolFlags.Optional)) {
20625                    // TypeScript 1.0 spec (April 2014): 3.8.3
20626                    // S is a subtype of a type T, and T is a supertype of S if ...
20627                    // S' and T are object types and, for each member M in T..
20628                    // M is a property and S' contains a property N where
20629                    // if M is a required property, N is also a required property
20630                    // (M - property in T)
20631                    // (N - property in S)
20632                    if (reportErrors) {
20633                        reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2,
20634                            symbolToString(targetProp), typeToString(source), typeToString(target));
20635                    }
20636                    return Ternary.False;
20637                }
20638                return related;
20639            }
20640
20641            function reportUnmatchedProperty(source: Type, target: Type, unmatchedProperty: Symbol, requireOptionalProperties: boolean) {
20642                let shouldSkipElaboration = false;
20643                // give specific error in case where private names have the same description
20644                if (unmatchedProperty.valueDeclaration
20645                    && isNamedDeclaration(unmatchedProperty.valueDeclaration)
20646                    && isPrivateIdentifier(unmatchedProperty.valueDeclaration.name)
20647                    && source.symbol
20648                    && source.symbol.flags & SymbolFlags.Class) {
20649                    const privateIdentifierDescription = unmatchedProperty.valueDeclaration.name.escapedText;
20650                    const symbolTableKey = getSymbolNameForPrivateIdentifier(source.symbol, privateIdentifierDescription);
20651                    if (symbolTableKey && getPropertyOfType(source, symbolTableKey)) {
20652                        const sourceName = factory.getDeclarationName(source.symbol.valueDeclaration);
20653                        const targetName = factory.getDeclarationName(target.symbol.valueDeclaration);
20654                        reportError(
20655                            Diagnostics.Property_0_in_type_1_refers_to_a_different_member_that_cannot_be_accessed_from_within_type_2,
20656                            diagnosticName(privateIdentifierDescription),
20657                            diagnosticName(sourceName.escapedText === "" ? anon : sourceName),
20658                            diagnosticName(targetName.escapedText === "" ? anon : targetName));
20659                        return;
20660                    }
20661                }
20662                const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false));
20663                if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code &&
20664                    headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) {
20665                    shouldSkipElaboration = true; // Retain top-level error for interface implementing issues, otherwise omit it
20666                }
20667                if (props.length === 1) {
20668                    const propName = symbolToString(unmatchedProperty, /*enclosingDeclaration*/ undefined, SymbolFlags.None, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteComputedProps);
20669                    reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, ...getTypeNamesForErrorDisplay(source, target));
20670                    if (length(unmatchedProperty.declarations)) {
20671                        associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations![0], Diagnostics._0_is_declared_here, propName));
20672                    }
20673                    if (shouldSkipElaboration && errorInfo) {
20674                        overrideNextErrorInfo++;
20675                    }
20676                }
20677                else if (tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ false)) {
20678                    if (props.length > 5) { // arbitrary cutoff for too-long list form
20679                        reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4);
20680                    }
20681                    else {
20682                        reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", "));
20683                    }
20684                    if (shouldSkipElaboration && errorInfo) {
20685                        overrideNextErrorInfo++;
20686                    }
20687                }
20688                // No array like or unmatched property error - just issue top level error (errorInfo = undefined)
20689            }
20690
20691            function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean, excludedProperties: Set<__String> | undefined, intersectionState: IntersectionState): Ternary {
20692                if (relation === identityRelation) {
20693                    return propertiesIdenticalTo(source, target, excludedProperties);
20694                }
20695                let result = Ternary.True;
20696                if (isTupleType(target)) {
20697                    if (isArrayOrTupleType(source)) {
20698                        if (!target.target.readonly && (isReadonlyArrayType(source) || isTupleType(source) && source.target.readonly)) {
20699                            return Ternary.False;
20700                        }
20701                        const sourceArity = getTypeReferenceArity(source);
20702                        const targetArity = getTypeReferenceArity(target);
20703                        const sourceRestFlag = isTupleType(source) ? source.target.combinedFlags & ElementFlags.Rest : ElementFlags.Rest;
20704                        const targetRestFlag = target.target.combinedFlags & ElementFlags.Rest;
20705                        const sourceMinLength = isTupleType(source) ? source.target.minLength : 0;
20706                        const targetMinLength = target.target.minLength;
20707                        if (!sourceRestFlag && sourceArity < targetMinLength) {
20708                            if (reportErrors) {
20709                                reportError(Diagnostics.Source_has_0_element_s_but_target_requires_1, sourceArity, targetMinLength);
20710                            }
20711                            return Ternary.False;
20712                        }
20713                        if (!targetRestFlag && targetArity < sourceMinLength) {
20714                            if (reportErrors) {
20715                                reportError(Diagnostics.Source_has_0_element_s_but_target_allows_only_1, sourceMinLength, targetArity);
20716                            }
20717                            return Ternary.False;
20718                        }
20719                        if (!targetRestFlag && (sourceRestFlag || targetArity < sourceArity)) {
20720                            if (reportErrors) {
20721                                if (sourceMinLength < targetMinLength) {
20722                                    reportError(Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, targetMinLength);
20723                                }
20724                                else {
20725                                    reportError(Diagnostics.Target_allows_only_0_element_s_but_source_may_have_more, targetArity);
20726                                }
20727                            }
20728                            return Ternary.False;
20729                        }
20730                        const sourceTypeArguments = getTypeArguments(source);
20731                        const targetTypeArguments = getTypeArguments(target);
20732                        const startCount = Math.min(isTupleType(source) ? getStartElementCount(source.target, ElementFlags.NonRest) : 0, getStartElementCount(target.target, ElementFlags.NonRest));
20733                        const endCount = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.NonRest) : 0, targetRestFlag ? getEndElementCount(target.target, ElementFlags.NonRest) : 0);
20734                        let canExcludeDiscriminants = !!excludedProperties;
20735                        for (let i = 0; i < targetArity; i++) {
20736                            const sourceIndex = i < targetArity - endCount ? i : i + sourceArity - targetArity;
20737                            const sourceFlags = isTupleType(source) && (i < startCount || i >= targetArity - endCount) ? source.target.elementFlags[sourceIndex] : ElementFlags.Rest;
20738                            const targetFlags = target.target.elementFlags[i];
20739                            if (targetFlags & ElementFlags.Variadic && !(sourceFlags & ElementFlags.Variadic)) {
20740                                if (reportErrors) {
20741                                    reportError(Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, i);
20742                                }
20743                                return Ternary.False;
20744                            }
20745                            if (sourceFlags & ElementFlags.Variadic && !(targetFlags & ElementFlags.Variable)) {
20746                                if (reportErrors) {
20747                                    reportError(Diagnostics.Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, sourceIndex, i);
20748                                }
20749                                return Ternary.False;
20750                            }
20751                            if (targetFlags & ElementFlags.Required && !(sourceFlags & ElementFlags.Required)) {
20752                                if (reportErrors) {
20753                                    reportError(Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, i);
20754                                }
20755                                return Ternary.False;
20756                            }
20757                            // We can only exclude discriminant properties if we have not yet encountered a variable-length element.
20758                            if (canExcludeDiscriminants) {
20759                                if (sourceFlags & ElementFlags.Variable || targetFlags & ElementFlags.Variable) {
20760                                    canExcludeDiscriminants = false;
20761                                }
20762                                if (canExcludeDiscriminants && excludedProperties?.has(("" + i) as __String)) {
20763                                    continue;
20764                                }
20765                            }
20766                            const sourceType = !isTupleType(source) ? sourceTypeArguments[0] :
20767                                i < startCount || i >= targetArity - endCount ? removeMissingType(sourceTypeArguments[sourceIndex], !!(sourceFlags & targetFlags & ElementFlags.Optional)) :
20768                                getElementTypeOfSliceOfTupleType(source, startCount, endCount) || neverType;
20769                            const targetType = targetTypeArguments[i];
20770                            const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) :
20771                                removeMissingType(targetType, !!(targetFlags & ElementFlags.Optional));
20772                            const related = isRelatedTo(sourceType, targetCheckType, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState);
20773                            if (!related) {
20774                                if (reportErrors && (targetArity > 1 || sourceArity > 1)) {
20775                                    if (i < startCount || i >= targetArity - endCount || sourceArity - startCount - endCount === 1) {
20776                                        reportIncompatibleError(Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourceIndex, i);
20777                                    }
20778                                    else {
20779                                        reportIncompatibleError(Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, startCount, sourceArity - endCount - 1, i);
20780                                    }
20781                                }
20782                                return Ternary.False;
20783                            }
20784                            result &= related;
20785                        }
20786                        return result;
20787                    }
20788                    if (target.target.combinedFlags & ElementFlags.Variable) {
20789                        return Ternary.False;
20790                    }
20791                }
20792                const requireOptionalProperties = (relation === subtypeRelation || relation === strictSubtypeRelation) && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source);
20793                const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false);
20794                if (unmatchedProperty) {
20795                    if (reportErrors && shouldReportUnmatchedPropertyError(source, target)) {
20796                        reportUnmatchedProperty(source, target, unmatchedProperty, requireOptionalProperties);
20797                    }
20798                    return Ternary.False;
20799                }
20800                if (isObjectLiteralType(target)) {
20801                    for (const sourceProp of excludeProperties(getPropertiesOfType(source), excludedProperties)) {
20802                        if (!getPropertyOfObjectType(target, sourceProp.escapedName)) {
20803                            const sourceType = getTypeOfSymbol(sourceProp);
20804                            if (!(sourceType.flags & TypeFlags.Undefined)) {
20805                                if (reportErrors) {
20806                                    reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target));
20807                                }
20808                                return Ternary.False;
20809                            }
20810                        }
20811                    }
20812                }
20813                // We only call this for union target types when we're attempting to do excess property checking - in those cases, we want to get _all possible props_
20814                // from the target union, across all members
20815                const properties = getPropertiesOfType(target);
20816                const numericNamesOnly = isTupleType(source) && isTupleType(target);
20817                for (const targetProp of excludeProperties(properties, excludedProperties)) {
20818                    const name = targetProp.escapedName;
20819                    if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
20820                        const sourceProp = getPropertyOfType(source, name);
20821                        if (sourceProp && sourceProp !== targetProp) {
20822                            const related = propertyRelatedTo(source, target, sourceProp, targetProp, getNonMissingTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
20823                            if (!related) {
20824                                return Ternary.False;
20825                            }
20826                            result &= related;
20827                        }
20828                    }
20829                }
20830                return result;
20831            }
20832
20833            function propertiesIdenticalTo(source: Type, target: Type, excludedProperties: Set<__String> | undefined): Ternary {
20834                if (!(source.flags & TypeFlags.Object && target.flags & TypeFlags.Object)) {
20835                    return Ternary.False;
20836                }
20837                const sourceProperties = excludeProperties(getPropertiesOfObjectType(source), excludedProperties);
20838                const targetProperties = excludeProperties(getPropertiesOfObjectType(target), excludedProperties);
20839                if (sourceProperties.length !== targetProperties.length) {
20840                    return Ternary.False;
20841                }
20842                let result = Ternary.True;
20843                for (const sourceProp of sourceProperties) {
20844                    const targetProp = getPropertyOfObjectType(target, sourceProp.escapedName);
20845                    if (!targetProp) {
20846                        return Ternary.False;
20847                    }
20848                    const related = compareProperties(sourceProp, targetProp, isRelatedTo);
20849                    if (!related) {
20850                        return Ternary.False;
20851                    }
20852                    result &= related;
20853                }
20854                return result;
20855            }
20856
20857            function signaturesRelatedTo(source: Type, target: Type, kind: SignatureKind, reportErrors: boolean): Ternary {
20858                if (relation === identityRelation) {
20859                    return signaturesIdenticalTo(source, target, kind);
20860                }
20861                if (target === anyFunctionType || source === anyFunctionType) {
20862                    return Ternary.True;
20863                }
20864
20865                const sourceIsJSConstructor = source.symbol && isJSConstructor(source.symbol.valueDeclaration);
20866                const targetIsJSConstructor = target.symbol && isJSConstructor(target.symbol.valueDeclaration);
20867
20868                const sourceSignatures = getSignaturesOfType(source, (sourceIsJSConstructor && kind === SignatureKind.Construct) ?
20869                    SignatureKind.Call : kind);
20870                const targetSignatures = getSignaturesOfType(target, (targetIsJSConstructor && kind === SignatureKind.Construct) ?
20871                    SignatureKind.Call : kind);
20872
20873                if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) {
20874                    const sourceIsAbstract = !!(sourceSignatures[0].flags & SignatureFlags.Abstract);
20875                    const targetIsAbstract = !!(targetSignatures[0].flags & SignatureFlags.Abstract);
20876                    if (sourceIsAbstract && !targetIsAbstract) {
20877                        // An abstract constructor type is not assignable to a non-abstract constructor type
20878                        // as it would otherwise be possible to new an abstract class. Note that the assignability
20879                        // check we perform for an extends clause excludes construct signatures from the target,
20880                        // so this check never proceeds.
20881                        if (reportErrors) {
20882                            reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type);
20883                        }
20884                        return Ternary.False;
20885                    }
20886                    if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) {
20887                        return Ternary.False;
20888                    }
20889                }
20890
20891                let result = Ternary.True;
20892                const incompatibleReporter = kind === SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn : reportIncompatibleCallSignatureReturn;
20893                const sourceObjectFlags = getObjectFlags(source);
20894                const targetObjectFlags = getObjectFlags(target);
20895                if (sourceObjectFlags & ObjectFlags.Instantiated && targetObjectFlags & ObjectFlags.Instantiated && source.symbol === target.symbol ||
20896                    sourceObjectFlags & ObjectFlags.Reference && targetObjectFlags & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target) {
20897                    // We have instantiations of the same anonymous type (which typically will be the type of a
20898                    // method). Simply do a pairwise comparison of the signatures in the two signature lists instead
20899                    // of the much more expensive N * M comparison matrix we explore below. We erase type parameters
20900                    // as they are known to always be the same.
20901                    for (let i = 0; i < targetSignatures.length; i++) {
20902                        const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors, incompatibleReporter(sourceSignatures[i], targetSignatures[i]));
20903                        if (!related) {
20904                            return Ternary.False;
20905                        }
20906                        result &= related;
20907                    }
20908                }
20909                else if (sourceSignatures.length === 1 && targetSignatures.length === 1) {
20910                    // For simple functions (functions with a single signature) we only erase type parameters for
20911                    // the comparable relation. Otherwise, if the source signature is generic, we instantiate it
20912                    // in the context of the target signature before checking the relationship. Ideally we'd do
20913                    // this regardless of the number of signatures, but the potential costs are prohibitive due
20914                    // to the quadratic nature of the logic below.
20915                    const eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks;
20916                    const sourceSignature = first(sourceSignatures);
20917                    const targetSignature = first(targetSignatures);
20918                    result = signatureRelatedTo(sourceSignature, targetSignature, eraseGenerics, reportErrors, incompatibleReporter(sourceSignature, targetSignature));
20919                    if (!result && reportErrors && kind === SignatureKind.Construct && (sourceObjectFlags & targetObjectFlags) &&
20920                        (targetSignature.declaration?.kind === SyntaxKind.Constructor || sourceSignature.declaration?.kind === SyntaxKind.Constructor)) {
20921                        const constructSignatureToString = (signature: Signature) =>
20922                            signatureToString(signature, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrowStyleSignature, kind);
20923                        reportError(Diagnostics.Type_0_is_not_assignable_to_type_1, constructSignatureToString(sourceSignature), constructSignatureToString(targetSignature));
20924                        reportError(Diagnostics.Types_of_construct_signatures_are_incompatible);
20925                        return result;
20926                    }
20927                }
20928                else {
20929                    outer: for (const t of targetSignatures) {
20930                        const saveErrorInfo = captureErrorCalculationState();
20931                        // Only elaborate errors from the first failure
20932                        let shouldElaborateErrors = reportErrors;
20933                        for (const s of sourceSignatures) {
20934                            const related = signatureRelatedTo(s, t, /*erase*/ true, shouldElaborateErrors, incompatibleReporter(s, t));
20935                            if (related) {
20936                                result &= related;
20937                                resetErrorInfo(saveErrorInfo);
20938                                continue outer;
20939                            }
20940                            shouldElaborateErrors = false;
20941                        }
20942                        if (shouldElaborateErrors) {
20943                            reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1,
20944                                typeToString(source),
20945                                signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind));
20946                        }
20947                        return Ternary.False;
20948                    }
20949                }
20950                return result;
20951            }
20952
20953            function shouldReportUnmatchedPropertyError(source: Type, target: Type): boolean {
20954                const typeCallSignatures = getSignaturesOfStructuredType(source, SignatureKind.Call);
20955                const typeConstructSignatures = getSignaturesOfStructuredType(source, SignatureKind.Construct);
20956                const typeProperties = getPropertiesOfObjectType(source);
20957                if ((typeCallSignatures.length || typeConstructSignatures.length) && !typeProperties.length) {
20958                    if ((getSignaturesOfType(target, SignatureKind.Call).length && typeCallSignatures.length) ||
20959                        (getSignaturesOfType(target, SignatureKind.Construct).length && typeConstructSignatures.length)) {
20960                        return true; // target has similar signature kinds to source, still focus on the unmatched property
20961                    }
20962                    return false;
20963                }
20964                return true;
20965            }
20966
20967            function reportIncompatibleCallSignatureReturn(siga: Signature, sigb: Signature) {
20968                if (siga.parameters.length === 0 && sigb.parameters.length === 0) {
20969                    return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target));
20970                }
20971                return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target));
20972            }
20973
20974            function reportIncompatibleConstructSignatureReturn(siga: Signature, sigb: Signature) {
20975                if (siga.parameters.length === 0 && sigb.parameters.length === 0) {
20976                    return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target));
20977                }
20978                return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target));
20979            }
20980
20981            /**
20982             * See signatureAssignableTo, compareSignaturesIdentical
20983             */
20984            function signatureRelatedTo(source: Signature, target: Signature, erase: boolean, reportErrors: boolean, incompatibleReporter: (source: Type, target: Type) => void): Ternary {
20985                return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target,
20986                    relation === strictSubtypeRelation ? SignatureCheckMode.StrictArity : 0, reportErrors, reportError, incompatibleReporter, isRelatedToWorker, reportUnreliableMapper);
20987            }
20988
20989            function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary {
20990                const sourceSignatures = getSignaturesOfType(source, kind);
20991                const targetSignatures = getSignaturesOfType(target, kind);
20992                if (sourceSignatures.length !== targetSignatures.length) {
20993                    return Ternary.False;
20994                }
20995                let result = Ternary.True;
20996                for (let i = 0; i < sourceSignatures.length; i++) {
20997                    const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo);
20998                    if (!related) {
20999                        return Ternary.False;
21000                    }
21001                    result &= related;
21002                }
21003                return result;
21004            }
21005
21006            function membersRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean): Ternary {
21007                let result = Ternary.True;
21008                const keyType = targetInfo.keyType;
21009                const props = source.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(source as IntersectionType) : getPropertiesOfObjectType(source);
21010                for (const prop of props) {
21011                    // Skip over ignored JSX and symbol-named members
21012                    if (isIgnoredJsxProperty(source, prop)) {
21013                        continue;
21014                    }
21015                    if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), keyType)) {
21016                        const propType = getNonMissingTypeOfSymbol(prop);
21017                        const type = exactOptionalPropertyTypes || propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional)
21018                            ? propType
21019                            : getTypeWithFacts(propType, TypeFacts.NEUndefined);
21020                        const related = isRelatedTo(type, targetInfo.type, RecursionFlags.Both, reportErrors);
21021                        if (!related) {
21022                            if (reportErrors) {
21023                                reportError(Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop));
21024                            }
21025                            return Ternary.False;
21026                        }
21027                        result &= related;
21028                    }
21029                }
21030                for (const info of getIndexInfosOfType(source)) {
21031                    if (isApplicableIndexType(info.keyType, keyType)) {
21032                        const related = indexInfoRelatedTo(info, targetInfo, reportErrors);
21033                        if (!related) {
21034                            return Ternary.False;
21035                        }
21036                        result &= related;
21037                    }
21038                }
21039                return result;
21040            }
21041
21042            function indexInfoRelatedTo(sourceInfo: IndexInfo, targetInfo: IndexInfo, reportErrors: boolean) {
21043                const related = isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both, reportErrors);
21044                if (!related && reportErrors) {
21045                    if (sourceInfo.keyType === targetInfo.keyType) {
21046                        reportError(Diagnostics._0_index_signatures_are_incompatible, typeToString(sourceInfo.keyType));
21047                    }
21048                    else {
21049                        reportError(Diagnostics._0_and_1_index_signatures_are_incompatible, typeToString(sourceInfo.keyType), typeToString(targetInfo.keyType));
21050                    }
21051                }
21052                return related;
21053            }
21054
21055            function indexSignaturesRelatedTo(source: Type, target: Type, sourceIsPrimitive: boolean, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
21056                if (relation === identityRelation) {
21057                    return indexSignaturesIdenticalTo(source, target);
21058                }
21059                const indexInfos = getIndexInfosOfType(target);
21060                const targetHasStringIndex = some(indexInfos, info => info.keyType === stringType);
21061                let result = Ternary.True;
21062                for (const targetInfo of indexInfos) {
21063                    const related = !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True :
21064                        isGenericMappedType(source) && targetHasStringIndex ? isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, RecursionFlags.Both, reportErrors) :
21065                        typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState);
21066                    if (!related) {
21067                        return Ternary.False;
21068                    }
21069                    result &= related;
21070                }
21071                return result;
21072            }
21073
21074            function typeRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
21075                const sourceInfo = getApplicableIndexInfo(source, targetInfo.keyType);
21076                if (sourceInfo) {
21077                    return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors);
21078                }
21079                if (!(intersectionState & IntersectionState.Source) && isObjectTypeWithInferableIndex(source)) {
21080                    // Intersection constituents are never considered to have an inferred index signature
21081                    return membersRelatedToIndexInfo(source, targetInfo, reportErrors);
21082                }
21083                if (reportErrors) {
21084                    reportError(Diagnostics.Index_signature_for_type_0_is_missing_in_type_1, typeToString(targetInfo.keyType), typeToString(source));
21085                }
21086                return Ternary.False;
21087            }
21088
21089            function indexSignaturesIdenticalTo(source: Type, target: Type): Ternary {
21090                const sourceInfos = getIndexInfosOfType(source);
21091                const targetInfos = getIndexInfosOfType(target);
21092                if (sourceInfos.length !== targetInfos.length) {
21093                    return Ternary.False;
21094                }
21095                for (const targetInfo of targetInfos) {
21096                    const sourceInfo = getIndexInfoOfType(source, targetInfo.keyType);
21097                    if (!(sourceInfo && isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both) && sourceInfo.isReadonly === targetInfo.isReadonly)) {
21098                        return Ternary.False;
21099                    }
21100                }
21101                return Ternary.True;
21102            }
21103
21104            function constructorVisibilitiesAreCompatible(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) {
21105                if (!sourceSignature.declaration || !targetSignature.declaration) {
21106                    return true;
21107                }
21108
21109                const sourceAccessibility = getSelectedEffectiveModifierFlags(sourceSignature.declaration, ModifierFlags.NonPublicAccessibilityModifier);
21110                const targetAccessibility = getSelectedEffectiveModifierFlags(targetSignature.declaration, ModifierFlags.NonPublicAccessibilityModifier);
21111
21112                // A public, protected and private signature is assignable to a private signature.
21113                if (targetAccessibility === ModifierFlags.Private) {
21114                    return true;
21115                }
21116
21117                // A public and protected signature is assignable to a protected signature.
21118                if (targetAccessibility === ModifierFlags.Protected && sourceAccessibility !== ModifierFlags.Private) {
21119                    return true;
21120                }
21121
21122                // Only a public signature is assignable to public signature.
21123                if (targetAccessibility !== ModifierFlags.Protected && !sourceAccessibility) {
21124                    return true;
21125                }
21126
21127                if (reportErrors) {
21128                    reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility));
21129                }
21130
21131                return false;
21132            }
21133        }
21134
21135        function typeCouldHaveTopLevelSingletonTypes(type: Type): boolean {
21136            // Okay, yes, 'boolean' is a union of 'true | false', but that's not useful
21137            // in error reporting scenarios. If you need to use this function but that detail matters,
21138            // feel free to add a flag.
21139            if (type.flags & TypeFlags.Boolean) {
21140                return false;
21141            }
21142
21143            if (type.flags & TypeFlags.UnionOrIntersection) {
21144                return !!forEach((type as IntersectionType).types, typeCouldHaveTopLevelSingletonTypes);
21145            }
21146
21147            if (type.flags & TypeFlags.Instantiable) {
21148                const constraint = getConstraintOfType(type);
21149                if (constraint && constraint !== type) {
21150                    return typeCouldHaveTopLevelSingletonTypes(constraint);
21151                }
21152            }
21153
21154            return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral) || !!(type.flags & TypeFlags.StringMapping);
21155        }
21156
21157        function getExactOptionalUnassignableProperties(source: Type, target: Type) {
21158            if (isTupleType(source) && isTupleType(target)) return emptyArray;
21159            return getPropertiesOfType(target)
21160                .filter(targetProp => isExactOptionalPropertyMismatch(getTypeOfPropertyOfType(source, targetProp.escapedName), getTypeOfSymbol(targetProp)));
21161        }
21162
21163        function isExactOptionalPropertyMismatch(source: Type | undefined, target: Type | undefined) {
21164            return !!source && !!target && maybeTypeOfKind(source, TypeFlags.Undefined) && !!containsMissingType(target);
21165        }
21166
21167        function getExactOptionalProperties(type: Type) {
21168            return getPropertiesOfType(type).filter(targetProp => containsMissingType(getTypeOfSymbol(targetProp)));
21169        }
21170
21171        function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) {
21172            return findMatchingDiscriminantType(source, target, isRelatedTo, /*skipPartial*/ true) ||
21173                findMatchingTypeReferenceOrTypeAliasReference(source, target) ||
21174                findBestTypeForObjectLiteral(source, target) ||
21175                findBestTypeForInvokable(source, target) ||
21176                findMostOverlappyType(source, target);
21177        }
21178
21179        function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: undefined, skipPartial?: boolean): Type | undefined;
21180        function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue: Type, skipPartial?: boolean): Type;
21181        function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: Type, skipPartial?: boolean) {
21182            // undefined=unknown, true=discriminated, false=not discriminated
21183            // The state of each type progresses from left to right. Discriminated types stop at 'true'.
21184            const discriminable = target.types.map(_ => undefined) as (boolean | undefined)[];
21185            for (const [getDiscriminatingType, propertyName] of discriminators) {
21186                const targetProp = getUnionOrIntersectionProperty(target, propertyName);
21187                if (skipPartial && targetProp && getCheckFlags(targetProp) & CheckFlags.ReadPartial) {
21188                    continue;
21189                }
21190                let i = 0;
21191                for (const type of target.types) {
21192                    const targetType = getTypeOfPropertyOfType(type, propertyName);
21193                    if (targetType && related(getDiscriminatingType(), targetType)) {
21194                        discriminable[i] = discriminable[i] === undefined ? true : discriminable[i];
21195                    }
21196                    else {
21197                        discriminable[i] = false;
21198                    }
21199                    i++;
21200                }
21201            }
21202            const match = discriminable.indexOf(/*searchElement*/ true);
21203            if (match === -1) {
21204                return defaultValue;
21205            }
21206            // make sure exactly 1 matches before returning it
21207            let nextMatch = discriminable.indexOf(/*searchElement*/ true, match + 1);
21208            while (nextMatch !== -1) {
21209                if (!isTypeIdenticalTo(target.types[match], target.types[nextMatch])) {
21210                    return defaultValue;
21211                }
21212                nextMatch = discriminable.indexOf(/*searchElement*/ true, nextMatch + 1);
21213            }
21214            return target.types[match];
21215        }
21216
21217        /**
21218         * A type is 'weak' if it is an object type with at least one optional property
21219         * and no required properties, call/construct signatures or index signatures
21220         */
21221        function isWeakType(type: Type): boolean {
21222            if (type.flags & TypeFlags.Object) {
21223                const resolved = resolveStructuredTypeMembers(type as ObjectType);
21224                return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 && resolved.indexInfos.length === 0 &&
21225                    resolved.properties.length > 0 && every(resolved.properties, p => !!(p.flags & SymbolFlags.Optional));
21226            }
21227            if (type.flags & TypeFlags.Intersection) {
21228                return every((type as IntersectionType).types, isWeakType);
21229            }
21230            return false;
21231        }
21232
21233        function hasCommonProperties(source: Type, target: Type, isComparingJsxAttributes: boolean) {
21234            for (const prop of getPropertiesOfType(source)) {
21235                if (isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
21236                    return true;
21237                }
21238            }
21239            return false;
21240        }
21241
21242        function getVariances(type: GenericType): VarianceFlags[] {
21243            // Arrays and tuples are known to be covariant, no need to spend time computing this.
21244            return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple ?
21245                arrayVariances :
21246                getVariancesWorker(type.symbol, type.typeParameters);
21247        }
21248
21249        function getAliasVariances(symbol: Symbol) {
21250            return getVariancesWorker(symbol, getSymbolLinks(symbol).typeParameters);
21251        }
21252
21253        // Return an array containing the variance of each type parameter. The variance is effectively
21254        // a digest of the type comparisons that occur for each type argument when instantiations of the
21255        // generic type are structurally compared. We infer the variance information by comparing
21256        // instantiations of the generic type for type arguments with known relations. The function
21257        // returns the emptyArray singleton when invoked recursively for the given generic type.
21258        function getVariancesWorker(symbol: Symbol, typeParameters: readonly TypeParameter[] = emptyArray): VarianceFlags[] {
21259            const links = getSymbolLinks(symbol);
21260            if (!links.variances) {
21261                tracing?.push(tracing.Phase.CheckTypes, "getVariancesWorker", { arity: typeParameters.length, id: getTypeId(getDeclaredTypeOfSymbol(symbol)) });
21262                links.variances = emptyArray;
21263                const variances = [];
21264                for (const tp of typeParameters) {
21265                    const modifiers = getVarianceModifiers(tp);
21266                    let variance = modifiers & ModifierFlags.Out ?
21267                        modifiers & ModifierFlags.In ? VarianceFlags.Invariant : VarianceFlags.Covariant :
21268                        modifiers & ModifierFlags.In ? VarianceFlags.Contravariant : undefined;
21269                    if (variance === undefined) {
21270                        let unmeasurable = false;
21271                        let unreliable = false;
21272                        const oldHandler = outofbandVarianceMarkerHandler;
21273                        outofbandVarianceMarkerHandler = (onlyUnreliable) => onlyUnreliable ? unreliable = true : unmeasurable = true;
21274                        // We first compare instantiations where the type parameter is replaced with
21275                        // marker types that have a known subtype relationship. From this we can infer
21276                        // invariance, covariance, contravariance or bivariance.
21277                        const typeWithSuper = createMarkerType(symbol, tp, markerSuperType);
21278                        const typeWithSub = createMarkerType(symbol, tp, markerSubType);
21279                        variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? VarianceFlags.Covariant : 0) |
21280                            (isTypeAssignableTo(typeWithSuper, typeWithSub) ? VarianceFlags.Contravariant : 0);
21281                        // If the instantiations appear to be related bivariantly it may be because the
21282                        // type parameter is independent (i.e. it isn't witnessed anywhere in the generic
21283                        // type). To determine this we compare instantiations where the type parameter is
21284                        // replaced with marker types that are known to be unrelated.
21285                        if (variance === VarianceFlags.Bivariant && isTypeAssignableTo(createMarkerType(symbol, tp, markerOtherType), typeWithSuper)) {
21286                            variance = VarianceFlags.Independent;
21287                        }
21288                        outofbandVarianceMarkerHandler = oldHandler;
21289                        if (unmeasurable || unreliable) {
21290                            if (unmeasurable) {
21291                                variance |= VarianceFlags.Unmeasurable;
21292                            }
21293                            if (unreliable) {
21294                                variance |= VarianceFlags.Unreliable;
21295                            }
21296                        }
21297                    }
21298                    variances.push(variance);
21299                }
21300                links.variances = variances;
21301                tracing?.pop({ variances: variances.map(Debug.formatVariance) });
21302            }
21303            return links.variances;
21304        }
21305
21306        function createMarkerType(symbol: Symbol, source: TypeParameter, target: Type) {
21307            const mapper = makeUnaryTypeMapper(source, target);
21308            const type = getDeclaredTypeOfSymbol(symbol);
21309            if (isErrorType(type)) {
21310                return type;
21311            }
21312            const result = symbol.flags & SymbolFlags.TypeAlias ?
21313                getTypeAliasInstantiation(symbol, instantiateTypes(getSymbolLinks(symbol).typeParameters!, mapper)) :
21314                createTypeReference(type as GenericType, instantiateTypes((type as GenericType).typeParameters, mapper));
21315            markerTypes.add(getTypeId(result));
21316            return result;
21317        }
21318
21319        function isMarkerType(type: Type) {
21320            return markerTypes.has(getTypeId(type));
21321        }
21322
21323        function getVarianceModifiers(tp: TypeParameter): ModifierFlags {
21324            return (some(tp.symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.In)) ? ModifierFlags.In : 0) |
21325                (some(tp.symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.Out)) ? ModifierFlags.Out: 0);
21326        }
21327
21328        // Return true if the given type reference has a 'void' type argument for a covariant type parameter.
21329        // See comment at call in recursiveTypeRelatedTo for when this case matters.
21330        function hasCovariantVoidArgument(typeArguments: readonly Type[], variances: VarianceFlags[]): boolean {
21331            for (let i = 0; i < variances.length; i++) {
21332                if ((variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Covariant && typeArguments[i].flags & TypeFlags.Void) {
21333                    return true;
21334                }
21335            }
21336            return false;
21337        }
21338
21339        function isUnconstrainedTypeParameter(type: Type) {
21340            return type.flags & TypeFlags.TypeParameter && !getConstraintOfTypeParameter(type as TypeParameter);
21341        }
21342
21343        function isNonDeferredTypeReference(type: Type): type is TypeReference {
21344            return !!(getObjectFlags(type) & ObjectFlags.Reference) && !(type as TypeReference).node;
21345        }
21346
21347        function isTypeReferenceWithGenericArguments(type: Type): boolean {
21348            return isNonDeferredTypeReference(type) && some(getTypeArguments(type), t => !!(t.flags & TypeFlags.TypeParameter) || isTypeReferenceWithGenericArguments(t));
21349        }
21350
21351        function getGenericTypeReferenceRelationKey(source: TypeReference, target: TypeReference, postFix: string, ignoreConstraints: boolean) {
21352            const typeParameters: Type[] = [];
21353            let constraintMarker = "";
21354            const sourceId = getTypeReferenceId(source, 0);
21355            const targetId = getTypeReferenceId(target, 0);
21356            return `${constraintMarker}${sourceId},${targetId}${postFix}`;
21357            // getTypeReferenceId(A<T, number, U>) returns "111=0-12=1"
21358            // where A.id=111 and number.id=12
21359            function getTypeReferenceId(type: TypeReference, depth = 0) {
21360                let result = "" + type.target.id;
21361                for (const t of getTypeArguments(type)) {
21362                    if (t.flags & TypeFlags.TypeParameter) {
21363                        if (ignoreConstraints || isUnconstrainedTypeParameter(t)) {
21364                            let index = typeParameters.indexOf(t);
21365                            if (index < 0) {
21366                                index = typeParameters.length;
21367                                typeParameters.push(t);
21368                            }
21369                            result += "=" + index;
21370                            continue;
21371                        }
21372                        // We mark type references that reference constrained type parameters such that we know to obtain
21373                        // and look for a "broadest equivalent key" in the cache.
21374                        constraintMarker = "*";
21375                    }
21376                    else if (depth < 4 && isTypeReferenceWithGenericArguments(t)) {
21377                        result += "<" + getTypeReferenceId(t as TypeReference, depth + 1) + ">";
21378                        continue;
21379                    }
21380                    result += "-" + t.id;
21381                }
21382                return result;
21383            }
21384        }
21385
21386        /**
21387         * To improve caching, the relation key for two generic types uses the target's id plus ids of the type parameters.
21388         * For other cases, the types ids are used.
21389         */
21390        function getRelationKey(source: Type, target: Type, intersectionState: IntersectionState, relation: ESMap<string, RelationComparisonResult>, ignoreConstraints: boolean) {
21391            if (relation === identityRelation && source.id > target.id) {
21392                const temp = source;
21393                source = target;
21394                target = temp;
21395            }
21396            const postFix = intersectionState ? ":" + intersectionState : "";
21397            return isTypeReferenceWithGenericArguments(source) && isTypeReferenceWithGenericArguments(target) ?
21398                getGenericTypeReferenceRelationKey(source as TypeReference, target as TypeReference, postFix, ignoreConstraints) :
21399                `${source.id},${target.id}${postFix}`;
21400        }
21401
21402        // Invoke the callback for each underlying property symbol of the given symbol and return the first
21403        // value that isn't undefined.
21404        function forEachProperty<T>(prop: Symbol, callback: (p: Symbol) => T): T | undefined {
21405            if (getCheckFlags(prop) & CheckFlags.Synthetic) {
21406                for (const t of (prop as TransientSymbol).containingType!.types) {
21407                    const p = getPropertyOfType(t, prop.escapedName);
21408                    const result = p && forEachProperty(p, callback);
21409                    if (result) {
21410                        return result;
21411                    }
21412                }
21413                return undefined;
21414            }
21415            return callback(prop);
21416        }
21417
21418        // Return the declaring class type of a property or undefined if property not declared in class
21419        function getDeclaringClass(prop: Symbol) {
21420            return prop.parent && prop.parent.flags & SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)!) as InterfaceType : undefined;
21421        }
21422
21423        // Return the inherited type of the given property or undefined if property doesn't exist in a base class.
21424        function getTypeOfPropertyInBaseClass(property: Symbol) {
21425            const classType = getDeclaringClass(property);
21426            const baseClassType = classType && getBaseTypes(classType)[0];
21427            return baseClassType && getTypeOfPropertyOfType(baseClassType, property.escapedName);
21428        }
21429
21430        // Return true if some underlying source property is declared in a class that derives
21431        // from the given base class.
21432        function isPropertyInClassDerivedFrom(prop: Symbol, baseClass: Type | undefined) {
21433            return forEachProperty(prop, sp => {
21434                const sourceClass = getDeclaringClass(sp);
21435                return sourceClass ? hasBaseType(sourceClass, baseClass) : false;
21436            });
21437        }
21438
21439        // Return true if source property is a valid override of protected parts of target property.
21440        function isValidOverrideOf(sourceProp: Symbol, targetProp: Symbol) {
21441            return !forEachProperty(targetProp, tp => getDeclarationModifierFlagsFromSymbol(tp) & ModifierFlags.Protected ?
21442                !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false);
21443        }
21444
21445        // Return true if the given class derives from each of the declaring classes of the protected
21446        // constituents of the given property.
21447        function isClassDerivedFromDeclaringClasses<T extends Type>(checkClass: T, prop: Symbol, writing: boolean) {
21448            return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ?
21449                !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass;
21450        }
21451
21452        // Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons
21453        // for maxDepth or more occurrences or instantiations of the type have been recorded on the given stack. It is possible,
21454        // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely
21455        // expanding. Effectively, we will generate a false positive when two types are structurally equal to at least maxDepth
21456        // levels, but unequal at some level beyond that.
21457        // In addition, this will also detect when an indexed access has been chained off of maxDepth more times (which is
21458        // essentially the dual of the structural comparison), and likewise mark the type as deeply nested, potentially adding
21459        // false positives for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][P3][P4][P5]`).
21460        // It also detects when a recursive type reference has expanded maxDepth or more times, e.g. if the true branch of
21461        // `type A<T> = null extends T ? [A<NonNullable<T>>] : [T]`
21462        // has expanded into `[A<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T>>>>>>]`. In such cases we need
21463        // to terminate the expansion, and we do so here.
21464        function isDeeplyNestedType(type: Type, stack: Type[], depth: number, maxDepth = 3): boolean {
21465            if (depth >= maxDepth) {
21466                const identity = getRecursionIdentity(type);
21467                let count = 0;
21468                let lastTypeId = 0;
21469                for (let i = 0; i < depth; i++) {
21470                    const t = stack[i];
21471                    if (getRecursionIdentity(t) === identity) {
21472                        // We only count occurrences with a higher type id than the previous occurrence, since higher
21473                        // type ids are an indicator of newer instantiations caused by recursion.
21474                        if (t.id >= lastTypeId) {
21475                            count++;
21476                            if (count >= maxDepth) {
21477                                return true;
21478                            }
21479                        }
21480                        lastTypeId = t.id;
21481                    }
21482                }
21483            }
21484            return false;
21485        }
21486
21487        // The recursion identity of a type is an object identity that is shared among multiple instantiations of the type.
21488        // We track recursion identities in order to identify deeply nested and possibly infinite type instantiations with
21489        // the same origin. For example, when type parameters are in scope in an object type such as { x: T }, all
21490        // instantiations of that type have the same recursion identity. The default recursion identity is the object
21491        // identity of the type, meaning that every type is unique. Generally, types with constituents that could circularly
21492        // reference the type have a recursion identity that differs from the object identity.
21493        function getRecursionIdentity(type: Type): object {
21494            // Object and array literals are known not to contain recursive references and don't need a recursion identity.
21495            if (type.flags & TypeFlags.Object && !isObjectOrArrayLiteralType(type)) {
21496                if (getObjectFlags(type) && ObjectFlags.Reference && (type as TypeReference).node) {
21497                    // Deferred type references are tracked through their associated AST node. This gives us finer
21498                    // granularity than using their associated target because each manifest type reference has a
21499                    // unique AST node.
21500                    return (type as TypeReference).node!;
21501                }
21502                if (type.symbol && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class)) {
21503                    // We track all object types that have an associated symbol (representing the origin of the type), but
21504                    // exclude the static side of classes from this check since it shares its symbol with the instance side.
21505                    return type.symbol;
21506                }
21507                if (isTupleType(type)) {
21508                    // Tuple types are tracked through their target type
21509                    return type.target;
21510                }
21511            }
21512            if (type.flags & TypeFlags.TypeParameter) {
21513                return type.symbol;
21514            }
21515            if (type.flags & TypeFlags.IndexedAccess) {
21516                // Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P][Q] it is A
21517                do {
21518                    type = (type as IndexedAccessType).objectType;
21519                } while (type.flags & TypeFlags.IndexedAccess);
21520                return type;
21521            }
21522            if (type.flags & TypeFlags.Conditional) {
21523                // The root object represents the origin of the conditional type
21524                return (type as ConditionalType).root;
21525            }
21526            return type;
21527        }
21528
21529        function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
21530            return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False;
21531        }
21532
21533        function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary {
21534            // Two members are considered identical when
21535            // - they are public properties with identical names, optionality, and types,
21536            // - they are private or protected properties originating in the same declaration and having identical types
21537            if (sourceProp === targetProp) {
21538                return Ternary.True;
21539            }
21540            const sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & ModifierFlags.NonPublicAccessibilityModifier;
21541            const targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & ModifierFlags.NonPublicAccessibilityModifier;
21542            if (sourcePropAccessibility !== targetPropAccessibility) {
21543                return Ternary.False;
21544            }
21545            if (sourcePropAccessibility) {
21546                if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) {
21547                    return Ternary.False;
21548                }
21549            }
21550            else {
21551                if ((sourceProp.flags & SymbolFlags.Optional) !== (targetProp.flags & SymbolFlags.Optional)) {
21552                    return Ternary.False;
21553                }
21554            }
21555            if (isReadonlySymbol(sourceProp) !== isReadonlySymbol(targetProp)) {
21556                return Ternary.False;
21557            }
21558            return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
21559        }
21560
21561        function isMatchingSignature(source: Signature, target: Signature, partialMatch: boolean) {
21562            const sourceParameterCount = getParameterCount(source);
21563            const targetParameterCount = getParameterCount(target);
21564            const sourceMinArgumentCount = getMinArgumentCount(source);
21565            const targetMinArgumentCount = getMinArgumentCount(target);
21566            const sourceHasRestParameter = hasEffectiveRestParameter(source);
21567            const targetHasRestParameter = hasEffectiveRestParameter(target);
21568            // A source signature matches a target signature if the two signatures have the same number of required,
21569            // optional, and rest parameters.
21570            if (sourceParameterCount === targetParameterCount &&
21571                sourceMinArgumentCount === targetMinArgumentCount &&
21572                sourceHasRestParameter === targetHasRestParameter) {
21573                return true;
21574            }
21575            // A source signature partially matches a target signature if the target signature has no fewer required
21576            // parameters
21577            if (partialMatch && sourceMinArgumentCount <= targetMinArgumentCount) {
21578                return true;
21579            }
21580            return false;
21581        }
21582
21583        /**
21584         * See signatureRelatedTo, compareSignaturesIdentical
21585         */
21586        function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
21587            // TODO (drosen): De-duplicate code between related functions.
21588            if (source === target) {
21589                return Ternary.True;
21590            }
21591            if (!(isMatchingSignature(source, target, partialMatch))) {
21592                return Ternary.False;
21593            }
21594            // Check that the two signatures have the same number of type parameters.
21595            if (length(source.typeParameters) !== length(target.typeParameters)) {
21596                return Ternary.False;
21597            }
21598            // Check that type parameter constraints and defaults match. If they do, instantiate the source
21599            // signature with the type parameters of the target signature and continue the comparison.
21600            if (target.typeParameters) {
21601                const mapper = createTypeMapper(source.typeParameters!, target.typeParameters);
21602                for (let i = 0; i < target.typeParameters.length; i++) {
21603                    const s = source.typeParameters![i];
21604                    const t = target.typeParameters[i];
21605                    if (!(s === t || compareTypes(instantiateType(getConstraintFromTypeParameter(s), mapper) || unknownType, getConstraintFromTypeParameter(t) || unknownType) &&
21606                        compareTypes(instantiateType(getDefaultFromTypeParameter(s), mapper) || unknownType, getDefaultFromTypeParameter(t) || unknownType))) {
21607                        return Ternary.False;
21608                    }
21609                }
21610                source = instantiateSignature(source, mapper, /*eraseTypeParameters*/ true);
21611            }
21612            let result = Ternary.True;
21613            if (!ignoreThisTypes) {
21614                const sourceThisType = getThisTypeOfSignature(source);
21615                if (sourceThisType) {
21616                    const targetThisType = getThisTypeOfSignature(target);
21617                    if (targetThisType) {
21618                        const related = compareTypes(sourceThisType, targetThisType);
21619                        if (!related) {
21620                            return Ternary.False;
21621                        }
21622                        result &= related;
21623                    }
21624                }
21625            }
21626            const targetLen = getParameterCount(target);
21627            for (let i = 0; i < targetLen; i++) {
21628                const s = getTypeAtPosition(source, i);
21629                const t = getTypeAtPosition(target, i);
21630                const related = compareTypes(t, s);
21631                if (!related) {
21632                    return Ternary.False;
21633                }
21634                result &= related;
21635            }
21636            if (!ignoreReturnTypes) {
21637                const sourceTypePredicate = getTypePredicateOfSignature(source);
21638                const targetTypePredicate = getTypePredicateOfSignature(target);
21639                result &= sourceTypePredicate || targetTypePredicate ?
21640                    compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes) :
21641                    compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
21642            }
21643            return result;
21644        }
21645
21646        function compareTypePredicatesIdentical(source: TypePredicate | undefined, target: TypePredicate | undefined, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
21647            return !(source && target && typePredicateKindsMatch(source, target)) ? Ternary.False :
21648                source.type === target.type ? Ternary.True :
21649                source.type && target.type ? compareTypes(source.type, target.type) :
21650                Ternary.False;
21651        }
21652
21653        function literalTypesWithSameBaseType(types: Type[]): boolean {
21654            let commonBaseType: Type | undefined;
21655            for (const t of types) {
21656                if (!(t.flags & TypeFlags.Never)) {
21657                    const baseType = getBaseTypeOfLiteralType(t);
21658                    commonBaseType ??= baseType;
21659                    if (baseType === t || baseType !== commonBaseType) {
21660                        return false;
21661                    }
21662                }
21663            }
21664            return true;
21665        }
21666
21667        function getCombinedTypeFlags(types: Type[]): TypeFlags {
21668            return reduceLeft(types, (flags, t) => flags | (t.flags & TypeFlags.Union ? getCombinedTypeFlags((t as UnionType).types) : t.flags), 0);
21669        }
21670
21671        function getCommonSupertype(types: Type[]): Type {
21672            if (types.length === 1) {
21673                return types[0];
21674            }
21675            // Remove nullable types from each of the candidates.
21676            const primaryTypes = strictNullChecks ? sameMap(types, t => filterType(t, u => !(u.flags & TypeFlags.Nullable))) : types;
21677            // When the candidate types are all literal types with the same base type, return a union
21678            // of those literal types. Otherwise, return the leftmost type for which no type to the
21679            // right is a supertype.
21680            const superTypeOrUnion = literalTypesWithSameBaseType(primaryTypes) ?
21681                getUnionType(primaryTypes) :
21682                reduceLeft(primaryTypes, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!;
21683            // Add any nullable types that occurred in the candidates back to the result.
21684            return primaryTypes === types ? superTypeOrUnion : getNullableType(superTypeOrUnion, getCombinedTypeFlags(types) & TypeFlags.Nullable);
21685        }
21686
21687        // Return the leftmost type for which no type to the right is a subtype.
21688        function getCommonSubtype(types: Type[]) {
21689            return reduceLeft(types, (s, t) => isTypeSubtypeOf(t, s) ? t : s)!;
21690        }
21691
21692        function isArrayType(type: Type): type is TypeReference {
21693            return !!(getObjectFlags(type) & ObjectFlags.Reference) && ((type as TypeReference).target === globalArrayType || (type as TypeReference).target === globalReadonlyArrayType);
21694        }
21695
21696        function isReadonlyArrayType(type: Type): boolean {
21697            return !!(getObjectFlags(type) & ObjectFlags.Reference) && (type as TypeReference).target === globalReadonlyArrayType;
21698        }
21699
21700        function isArrayOrTupleType(type: Type): type is TypeReference {
21701            return isArrayType(type) || isTupleType(type);
21702        }
21703
21704        function isMutableArrayOrTuple(type: Type): boolean {
21705            return isArrayType(type) && !isReadonlyArrayType(type) || isTupleType(type) && !type.target.readonly;
21706        }
21707
21708        function getElementTypeOfArrayType(type: Type): Type | undefined {
21709            return isArrayType(type) ? getTypeArguments(type)[0] : undefined;
21710        }
21711
21712        function isArrayLikeType(type: Type): boolean {
21713            // A type is array-like if it is a reference to the global Array or global ReadonlyArray type,
21714            // or if it is not the undefined or null type and if it is assignable to ReadonlyArray<any>
21715            return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
21716        }
21717
21718        function getSingleBaseForNonAugmentingSubtype(type: Type) {
21719            if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) {
21720                return undefined;
21721            }
21722            if (getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeCalculated) {
21723                return getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeExists ? (type as TypeReference).cachedEquivalentBaseType : undefined;
21724            }
21725            (type as TypeReference).objectFlags |= ObjectFlags.IdenticalBaseTypeCalculated;
21726            const target = (type as TypeReference).target as InterfaceType;
21727            if (getObjectFlags(target) & ObjectFlags.Class) {
21728                const baseTypeNode = getBaseTypeNodeOfClass(target);
21729                // A base type expression may circularly reference the class itself (e.g. as an argument to function call), so we only
21730                // check for base types specified as simple qualified names.
21731                if (baseTypeNode && baseTypeNode.expression.kind !== SyntaxKind.Identifier && baseTypeNode.expression.kind !== SyntaxKind.PropertyAccessExpression) {
21732                    return undefined;
21733                }
21734            }
21735            const bases = getBaseTypes(target);
21736            if (bases.length !== 1) {
21737                return undefined;
21738            }
21739            if (getMembersOfSymbol(type.symbol).size) {
21740                return undefined; // If the interface has any members, they may subtype members in the base, so we should do a full structural comparison
21741            }
21742            let instantiatedBase = !length(target.typeParameters) ? bases[0] : instantiateType(bases[0], createTypeMapper(target.typeParameters!, getTypeArguments(type as TypeReference).slice(0, target.typeParameters!.length)));
21743            if (length(getTypeArguments(type as TypeReference)) > length(target.typeParameters)) {
21744                instantiatedBase = getTypeWithThisArgument(instantiatedBase, last(getTypeArguments(type as TypeReference)));
21745            }
21746            (type as TypeReference).objectFlags |= ObjectFlags.IdenticalBaseTypeExists;
21747            return (type as TypeReference).cachedEquivalentBaseType = instantiatedBase;
21748        }
21749
21750        function isEmptyLiteralType(type: Type): boolean {
21751            return strictNullChecks ? type === implicitNeverType : type === undefinedWideningType;
21752        }
21753
21754        function isEmptyArrayLiteralType(type: Type): boolean {
21755            const elementType = getElementTypeOfArrayType(type);
21756            return !!elementType && isEmptyLiteralType(elementType);
21757        }
21758
21759        function isTupleLikeType(type: Type): boolean {
21760            return isTupleType(type) || !!getPropertyOfType(type, "0" as __String);
21761        }
21762
21763        function isArrayOrTupleLikeType(type: Type): boolean {
21764            return isArrayLikeType(type) || isTupleLikeType(type);
21765        }
21766
21767        function getTupleElementType(type: Type, index: number) {
21768            const propType = getTypeOfPropertyOfType(type, "" + index as __String);
21769            if (propType) {
21770                return propType;
21771            }
21772            if (everyType(type, isTupleType)) {
21773                return mapType(type, t => getRestTypeOfTupleType(t as TupleTypeReference) || undefinedType);
21774            }
21775            return undefined;
21776        }
21777
21778        function isNeitherUnitTypeNorNever(type: Type): boolean {
21779            return !(type.flags & (TypeFlags.Unit | TypeFlags.Never));
21780        }
21781
21782        function isUnitType(type: Type): boolean {
21783            return !!(type.flags & TypeFlags.Unit);
21784        }
21785
21786        function isUnitLikeType(type: Type): boolean {
21787            // Intersections that reduce to 'never' (e.g. 'T & null' where 'T extends {}') are not unit types.
21788            const t = getBaseConstraintOrType(type);
21789            // Scan intersections such that tagged literal types are considered unit types.
21790            return t.flags & TypeFlags.Intersection ? some((t as IntersectionType).types, isUnitType) : isUnitType(t);
21791        }
21792
21793        function extractUnitType(type: Type) {
21794            return type.flags & TypeFlags.Intersection ? find((type as IntersectionType).types, isUnitType) || type : type;
21795        }
21796
21797        function isLiteralType(type: Type): boolean {
21798            return type.flags & TypeFlags.Boolean ? true :
21799                type.flags & TypeFlags.Union ? type.flags & TypeFlags.EnumLiteral ? true : every((type as UnionType).types, isUnitType) :
21800                isUnitType(type);
21801        }
21802
21803        function getBaseTypeOfLiteralType(type: Type): Type {
21804            return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type as LiteralType) :
21805                type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType :
21806                type.flags & TypeFlags.NumberLiteral ? numberType :
21807                type.flags & TypeFlags.BigIntLiteral ? bigintType :
21808                type.flags & TypeFlags.BooleanLiteral ? booleanType :
21809                type.flags & TypeFlags.Union ? getBaseTypeOfLiteralTypeUnion(type as UnionType) :
21810                type;
21811        }
21812
21813        function getBaseTypeOfLiteralTypeUnion(type: UnionType) {
21814            const key = `B${getTypeId(type)}`;
21815            return getCachedType(key) ?? setCachedType(key, mapType(type, getBaseTypeOfLiteralType));
21816        }
21817
21818        function getWidenedLiteralType(type: Type): Type {
21819            return type.flags & TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type as LiteralType) :
21820                type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType :
21821                type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType :
21822                type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType :
21823                type.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(type) ? booleanType :
21824                type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedLiteralType) :
21825                type;
21826        }
21827
21828        function getWidenedUniqueESSymbolType(type: Type): Type {
21829            return type.flags & TypeFlags.UniqueESSymbol ? esSymbolType :
21830                type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedUniqueESSymbolType) :
21831                type;
21832        }
21833
21834        function getWidenedLiteralLikeTypeForContextualType(type: Type, contextualType: Type | undefined) {
21835            if (!isLiteralOfContextualType(type, contextualType)) {
21836                type = getWidenedUniqueESSymbolType(getWidenedLiteralType(type));
21837            }
21838            return getRegularTypeOfLiteralType(type);
21839        }
21840
21841        function getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded(type: Type | undefined, contextualSignatureReturnType: Type | undefined, isAsync: boolean) {
21842            if (type && isUnitType(type)) {
21843                const contextualType = !contextualSignatureReturnType ? undefined :
21844                    isAsync ? getPromisedTypeOfPromise(contextualSignatureReturnType) :
21845                    contextualSignatureReturnType;
21846                type = getWidenedLiteralLikeTypeForContextualType(type, contextualType);
21847            }
21848            return type;
21849        }
21850
21851        function getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(type: Type | undefined, contextualSignatureReturnType: Type | undefined, kind: IterationTypeKind, isAsyncGenerator: boolean) {
21852            if (type && isUnitType(type)) {
21853                const contextualType = !contextualSignatureReturnType ? undefined :
21854                    getIterationTypeOfGeneratorFunctionReturnType(kind, contextualSignatureReturnType, isAsyncGenerator);
21855                type = getWidenedLiteralLikeTypeForContextualType(type, contextualType);
21856            }
21857            return type;
21858        }
21859
21860        /**
21861         * Check if a Type was written as a tuple type literal.
21862         * Prefer using isTupleLikeType() unless the use of `elementTypes`/`getTypeArguments` is required.
21863         */
21864        function isTupleType(type: Type): type is TupleTypeReference {
21865            return !!(getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target.objectFlags & ObjectFlags.Tuple);
21866        }
21867
21868        function isGenericTupleType(type: Type): type is TupleTypeReference {
21869            return isTupleType(type) && !!(type.target.combinedFlags & ElementFlags.Variadic);
21870        }
21871
21872        function isSingleElementGenericTupleType(type: Type): type is TupleTypeReference {
21873            return isGenericTupleType(type) && type.target.elementFlags.length === 1;
21874        }
21875
21876        function getRestTypeOfTupleType(type: TupleTypeReference) {
21877            return getElementTypeOfSliceOfTupleType(type, type.target.fixedLength);
21878        }
21879
21880        function getRestArrayTypeOfTupleType(type: TupleTypeReference) {
21881            const restType = getRestTypeOfTupleType(type);
21882            return restType && createArrayType(restType);
21883        }
21884
21885        function getElementTypeOfSliceOfTupleType(type: TupleTypeReference, index: number, endSkipCount = 0, writing = false) {
21886            const length = getTypeReferenceArity(type) - endSkipCount;
21887            if (index < length) {
21888                const typeArguments = getTypeArguments(type);
21889                const elementTypes: Type[] = [];
21890                for (let i = index; i < length; i++) {
21891                    const t = typeArguments[i];
21892                    elementTypes.push(type.target.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t);
21893                }
21894                return writing ? getIntersectionType(elementTypes) : getUnionType(elementTypes);
21895            }
21896            return undefined;
21897        }
21898
21899        function isTupleTypeStructureMatching(t1: TupleTypeReference, t2: TupleTypeReference) {
21900            return getTypeReferenceArity(t1) === getTypeReferenceArity(t2) &&
21901                every(t1.target.elementFlags, (f, i) => (f & ElementFlags.Variable) === (t2.target.elementFlags[i] & ElementFlags.Variable));
21902        }
21903
21904        function isZeroBigInt({value}: BigIntLiteralType) {
21905            return value.base10Value === "0";
21906        }
21907
21908        function removeDefinitelyFalsyTypes(type: Type): Type {
21909            return filterType(type, t => !!(getTypeFacts(t) & TypeFacts.Truthy));
21910        }
21911
21912        function extractDefinitelyFalsyTypes(type: Type): Type {
21913            return mapType(type, getDefinitelyFalsyPartOfType);
21914        }
21915
21916        function getDefinitelyFalsyPartOfType(type: Type): Type {
21917            return type.flags & TypeFlags.String ? emptyStringType :
21918                type.flags & TypeFlags.Number ? zeroType :
21919                type.flags & TypeFlags.BigInt ? zeroBigIntType :
21920                type === regularFalseType ||
21921                type === falseType ||
21922                type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null | TypeFlags.AnyOrUnknown) ||
21923                type.flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === "" ||
21924                type.flags & TypeFlags.NumberLiteral && (type as NumberLiteralType).value === 0 ||
21925                type.flags & TypeFlags.BigIntLiteral && isZeroBigInt(type as BigIntLiteralType) ? type :
21926                neverType;
21927        }
21928
21929        /**
21930         * Add undefined or null or both to a type if they are missing.
21931         * @param type - type to add undefined and/or null to if not present
21932         * @param flags - Either TypeFlags.Undefined or TypeFlags.Null, or both
21933         */
21934        function getNullableType(type: Type, flags: TypeFlags): Type {
21935            const missing = (flags & ~type.flags) & (TypeFlags.Undefined | TypeFlags.Null);
21936            return missing === 0 ? type :
21937                missing === TypeFlags.Undefined ? getUnionType([type, undefinedType]) :
21938                missing === TypeFlags.Null ? getUnionType([type, nullType]) :
21939                getUnionType([type, undefinedType, nullType]);
21940        }
21941
21942        function getOptionalType(type: Type, isProperty = false): Type {
21943            Debug.assert(strictNullChecks);
21944            const missingOrUndefined = isProperty ? missingType : undefinedType;
21945            return type.flags & TypeFlags.Undefined || type.flags & TypeFlags.Union && (type as UnionType).types[0] === missingOrUndefined ? type : getUnionType([type, missingOrUndefined]);
21946        }
21947
21948        function getGlobalNonNullableTypeInstantiation(type: Type) {
21949            if (!deferredGlobalNonNullableTypeAlias) {
21950                deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol;
21951            }
21952            return deferredGlobalNonNullableTypeAlias !== unknownSymbol ?
21953                getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]) :
21954                getIntersectionType([type, emptyObjectType]);
21955        }
21956
21957        function getNonNullableType(type: Type): Type {
21958            return strictNullChecks ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
21959        }
21960
21961        function addOptionalTypeMarker(type: Type) {
21962            return strictNullChecks ? getUnionType([type, optionalType]) : type;
21963        }
21964
21965        function removeOptionalTypeMarker(type: Type): Type {
21966            return strictNullChecks ? removeType(type, optionalType) : type;
21967        }
21968
21969        function propagateOptionalTypeMarker(type: Type, node: OptionalChain, wasOptional: boolean) {
21970            return wasOptional ? isOutermostOptionalChain(node) ? getOptionalType(type) : addOptionalTypeMarker(type) : type;
21971        }
21972
21973        function getOptionalExpressionType(exprType: Type, expression: Expression) {
21974            return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) :
21975                isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) :
21976                exprType;
21977        }
21978
21979        function removeMissingType(type: Type, isOptional: boolean) {
21980            return exactOptionalPropertyTypes && isOptional ? removeType(type, missingType) : type;
21981        }
21982
21983        function containsMissingType(type: Type) {
21984            return exactOptionalPropertyTypes && (type === missingType || type.flags & TypeFlags.Union && containsType((type as UnionType).types, missingType));
21985        }
21986
21987        function removeMissingOrUndefinedType(type: Type): Type {
21988            return exactOptionalPropertyTypes ? removeType(type, missingType) : getTypeWithFacts(type, TypeFacts.NEUndefined);
21989        }
21990
21991        /**
21992         * Is source potentially coercible to target type under `==`.
21993         * Assumes that `source` is a constituent of a union, hence
21994         * the boolean literal flag on the LHS, but not on the RHS.
21995         *
21996         * This does not fully replicate the semantics of `==`. The
21997         * intention is to catch cases that are clearly not right.
21998         *
21999         * Comparing (string | number) to number should not remove the
22000         * string element.
22001         *
22002         * Comparing (string | number) to 1 will remove the string
22003         * element, though this is not sound. This is a pragmatic
22004         * choice.
22005         *
22006         * @see narrowTypeByEquality
22007         *
22008         * @param source
22009         * @param target
22010         */
22011        function isCoercibleUnderDoubleEquals(source: Type, target: Type): boolean {
22012            return ((source.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.BooleanLiteral)) !== 0)
22013                && ((target.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.Boolean)) !== 0);
22014        }
22015
22016        /**
22017         * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module
22018         * with no call or construct signatures.
22019         */
22020        function isObjectTypeWithInferableIndex(type: Type): boolean {
22021            const objectFlags = getObjectFlags(type);
22022            return type.flags & TypeFlags.Intersection
22023                ? every((type as IntersectionType).types, isObjectTypeWithInferableIndex)
22024                : !!(
22025                    type.symbol
22026                    && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.Enum | SymbolFlags.ValueModule)) !== 0
22027                    && !(type.symbol.flags & SymbolFlags.Class)
22028                    && !typeHasCallOrConstructSignatures(type)
22029                ) || !!(
22030                    objectFlags & ObjectFlags.ObjectRestType
22031                ) || !!(objectFlags & ObjectFlags.ReverseMapped && isObjectTypeWithInferableIndex((type as ReverseMappedType).source));
22032        }
22033
22034        function createSymbolWithType(source: Symbol, type: Type | undefined) {
22035            const symbol = createSymbol(source.flags, source.escapedName, getCheckFlags(source) & CheckFlags.Readonly);
22036            symbol.declarations = source.declarations;
22037            symbol.parent = source.parent;
22038            symbol.type = type;
22039            symbol.target = source;
22040            if (source.valueDeclaration) {
22041                symbol.valueDeclaration = source.valueDeclaration;
22042            }
22043            const nameType = getSymbolLinks(source).nameType;
22044            if (nameType) {
22045                symbol.nameType = nameType;
22046            }
22047            return symbol;
22048        }
22049
22050        function transformTypeOfMembers(type: Type, f: (propertyType: Type) => Type) {
22051            const members = createSymbolTable();
22052            for (const property of getPropertiesOfObjectType(type)) {
22053                const original = getTypeOfSymbol(property);
22054                const updated = f(original);
22055                members.set(property.escapedName, updated === original ? property : createSymbolWithType(property, updated));
22056            }
22057            return members;
22058        }
22059
22060        /**
22061         * If the the provided object literal is subject to the excess properties check,
22062         * create a new that is exempt. Recursively mark object literal members as exempt.
22063         * Leave signatures alone since they are not subject to the check.
22064         */
22065        function getRegularTypeOfObjectLiteral(type: Type): Type {
22066            if (!(isObjectLiteralType(type) && getObjectFlags(type) & ObjectFlags.FreshLiteral)) {
22067                return type;
22068            }
22069            const regularType = (type as FreshObjectLiteralType).regularType;
22070            if (regularType) {
22071                return regularType;
22072            }
22073
22074            const resolved = type as ResolvedType;
22075            const members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral);
22076            const regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.indexInfos);
22077            regularNew.flags = resolved.flags;
22078            regularNew.objectFlags |= resolved.objectFlags & ~ObjectFlags.FreshLiteral;
22079            (type as FreshObjectLiteralType).regularType = regularNew;
22080            return regularNew;
22081        }
22082
22083        function createWideningContext(parent: WideningContext | undefined, propertyName: __String | undefined, siblings: Type[] | undefined): WideningContext {
22084            return { parent, propertyName, siblings, resolvedProperties: undefined };
22085        }
22086
22087        function getSiblingsOfContext(context: WideningContext): Type[] {
22088            if (!context.siblings) {
22089                const siblings: Type[] = [];
22090                for (const type of getSiblingsOfContext(context.parent!)) {
22091                    if (isObjectLiteralType(type)) {
22092                        const prop = getPropertyOfObjectType(type, context.propertyName!);
22093                        if (prop) {
22094                            forEachType(getTypeOfSymbol(prop), t => {
22095                                siblings.push(t);
22096                            });
22097                        }
22098                    }
22099                }
22100                context.siblings = siblings;
22101            }
22102            return context.siblings;
22103        }
22104
22105        function getPropertiesOfContext(context: WideningContext): Symbol[] {
22106            if (!context.resolvedProperties) {
22107                const names = new Map<string, Symbol>() as UnderscoreEscapedMap<Symbol>;
22108                for (const t of getSiblingsOfContext(context)) {
22109                    if (isObjectLiteralType(t) && !(getObjectFlags(t) & ObjectFlags.ContainsSpread)) {
22110                        for (const prop of getPropertiesOfType(t)) {
22111                            names.set(prop.escapedName, prop);
22112                        }
22113                    }
22114                }
22115                context.resolvedProperties = arrayFrom(names.values());
22116            }
22117            return context.resolvedProperties;
22118        }
22119
22120        function getWidenedProperty(prop: Symbol, context: WideningContext | undefined): Symbol {
22121            if (!(prop.flags & SymbolFlags.Property)) {
22122                // Since get accessors already widen their return value there is no need to
22123                // widen accessor based properties here.
22124                return prop;
22125            }
22126            const original = getTypeOfSymbol(prop);
22127            const propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined);
22128            const widened = getWidenedTypeWithContext(original, propContext);
22129            return widened === original ? prop : createSymbolWithType(prop, widened);
22130        }
22131
22132        function getUndefinedProperty(prop: Symbol) {
22133            const cached = undefinedProperties.get(prop.escapedName);
22134            if (cached) {
22135                return cached;
22136            }
22137            const result = createSymbolWithType(prop, missingType);
22138            result.flags |= SymbolFlags.Optional;
22139            undefinedProperties.set(prop.escapedName, result);
22140            return result;
22141        }
22142
22143        function getWidenedTypeOfObjectLiteral(type: Type, context: WideningContext | undefined): Type {
22144            const members = createSymbolTable();
22145            for (const prop of getPropertiesOfObjectType(type)) {
22146                members.set(prop.escapedName, getWidenedProperty(prop, context));
22147            }
22148            if (context) {
22149                for (const prop of getPropertiesOfContext(context)) {
22150                    if (!members.has(prop.escapedName)) {
22151                        members.set(prop.escapedName, getUndefinedProperty(prop));
22152                    }
22153                }
22154            }
22155            const result = createAnonymousType(type.symbol, members, emptyArray, emptyArray,
22156                sameMap(getIndexInfosOfType(type), info => createIndexInfo(info.keyType, getWidenedType(info.type), info.isReadonly)));
22157            result.objectFlags |= (getObjectFlags(type) & (ObjectFlags.JSLiteral | ObjectFlags.NonInferrableType)); // Retain js literal flag through widening
22158            return result;
22159        }
22160
22161        function getWidenedType(type: Type) {
22162            return getWidenedTypeWithContext(type, /*context*/ undefined);
22163        }
22164
22165        function getWidenedTypeWithContext(type: Type, context: WideningContext | undefined): Type {
22166            if (getObjectFlags(type) & ObjectFlags.RequiresWidening) {
22167                if (context === undefined && type.widened) {
22168                    return type.widened;
22169                }
22170                let result: Type | undefined;
22171                if (type.flags & (TypeFlags.Any | TypeFlags.Nullable)) {
22172                    result = anyType;
22173                }
22174                else if (isObjectLiteralType(type)) {
22175                    result = getWidenedTypeOfObjectLiteral(type, context);
22176                }
22177                else if (type.flags & TypeFlags.Union) {
22178                    const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (type as UnionType).types);
22179                    const widenedTypes = sameMap((type as UnionType).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext));
22180                    // Widening an empty object literal transitions from a highly restrictive type to
22181                    // a highly inclusive one. For that reason we perform subtype reduction here if the
22182                    // union includes empty object types (e.g. reducing {} | string to just {}).
22183                    result = getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal);
22184                }
22185                else if (type.flags & TypeFlags.Intersection) {
22186                    result = getIntersectionType(sameMap((type as IntersectionType).types, getWidenedType));
22187                }
22188                else if (isArrayOrTupleType(type)) {
22189                    result = createTypeReference(type.target, sameMap(getTypeArguments(type), getWidenedType));
22190                }
22191                if (result && context === undefined) {
22192                    type.widened = result;
22193                }
22194                return result || type;
22195            }
22196            return type;
22197        }
22198
22199        /**
22200         * Reports implicit any errors that occur as a result of widening 'null' and 'undefined'
22201         * to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to
22202         * getWidenedType. But in some cases getWidenedType is called without reporting errors
22203         * (type argument inference is an example).
22204         *
22205         * The return value indicates whether an error was in fact reported. The particular circumstances
22206         * are on a best effort basis. Currently, if the null or undefined that causes widening is inside
22207         * an object literal property (arbitrarily deeply), this function reports an error. If no error is
22208         * reported, reportImplicitAnyError is a suitable fallback to report a general error.
22209         */
22210        function reportWideningErrorsInType(type: Type): boolean {
22211            let errorReported = false;
22212            if (getObjectFlags(type) & ObjectFlags.ContainsWideningType) {
22213                if (type.flags & TypeFlags.Union) {
22214                    if (some((type as UnionType).types, isEmptyObjectType)) {
22215                        errorReported = true;
22216                    }
22217                    else {
22218                        for (const t of (type as UnionType).types) {
22219                            if (reportWideningErrorsInType(t)) {
22220                                errorReported = true;
22221                            }
22222                        }
22223                    }
22224                }
22225                if (isArrayOrTupleType(type)) {
22226                    for (const t of getTypeArguments(type)) {
22227                        if (reportWideningErrorsInType(t)) {
22228                            errorReported = true;
22229                        }
22230                    }
22231                }
22232                if (isObjectLiteralType(type)) {
22233                    for (const p of getPropertiesOfObjectType(type)) {
22234                        const t = getTypeOfSymbol(p);
22235                        if (getObjectFlags(t) & ObjectFlags.ContainsWideningType) {
22236                            if (!reportWideningErrorsInType(t)) {
22237                                error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t)));
22238                            }
22239                            errorReported = true;
22240                        }
22241                    }
22242                }
22243            }
22244            return errorReported;
22245        }
22246
22247        function reportImplicitAny(declaration: Declaration, type: Type, wideningKind?: WideningKind) {
22248            const typeAsString = typeToString(getWidenedType(type));
22249            if (isInJSFile(declaration) && !isCheckJsEnabledForFile(getSourceFileOfNode(declaration), compilerOptions)) {
22250                // Only report implicit any errors/suggestions in TS and ts-check JS files
22251                return;
22252            }
22253            let diagnostic: DiagnosticMessage;
22254            switch (declaration.kind) {
22255                case SyntaxKind.BinaryExpression:
22256                case SyntaxKind.PropertyDeclaration:
22257                case SyntaxKind.PropertySignature:
22258                    diagnostic = noImplicitAny ? Diagnostics.Member_0_implicitly_has_an_1_type : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage;
22259                    break;
22260                case SyntaxKind.Parameter:
22261                    const param = declaration as ParameterDeclaration;
22262                    if (isIdentifier(param.name) &&
22263                        (isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) &&
22264                        param.parent.parameters.indexOf(param) > -1 &&
22265                        (resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) ||
22266                        param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) {
22267                        const newName = "arg" + param.parent.parameters.indexOf(param);
22268                        const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : "");
22269                        errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName);
22270                        return;
22271                    }
22272                    diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ?
22273                        noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage :
22274                        noImplicitAny ? Diagnostics.Parameter_0_implicitly_has_an_1_type : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage;
22275                    break;
22276                case SyntaxKind.BindingElement:
22277                    diagnostic = Diagnostics.Binding_element_0_implicitly_has_an_1_type;
22278                    if (!noImplicitAny) {
22279                        // Don't issue a suggestion for binding elements since the codefix doesn't yet support them.
22280                        return;
22281                    }
22282                    break;
22283                case SyntaxKind.JSDocFunctionType:
22284                    error(declaration, Diagnostics.Function_type_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
22285                    return;
22286                case SyntaxKind.FunctionDeclaration:
22287                case SyntaxKind.MethodDeclaration:
22288                case SyntaxKind.MethodSignature:
22289                case SyntaxKind.GetAccessor:
22290                case SyntaxKind.SetAccessor:
22291                case SyntaxKind.FunctionExpression:
22292                case SyntaxKind.ArrowFunction:
22293                    if (noImplicitAny && !(declaration as NamedDeclaration).name) {
22294                        if (wideningKind === WideningKind.GeneratorYield) {
22295                            error(declaration, Diagnostics.Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, typeAsString);
22296                        }
22297                        else {
22298                            error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
22299                        }
22300                        return;
22301                    }
22302                    diagnostic = !noImplicitAny ? Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage :
22303                        wideningKind === WideningKind.GeneratorYield ? Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_yield_type :
22304                        Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type;
22305                    break;
22306                case SyntaxKind.MappedType:
22307                    if (noImplicitAny) {
22308                        error(declaration, Diagnostics.Mapped_object_type_implicitly_has_an_any_template_type);
22309                    }
22310                    return;
22311                default:
22312                    diagnostic = noImplicitAny ? Diagnostics.Variable_0_implicitly_has_an_1_type : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage;
22313            }
22314            errorOrSuggestion(noImplicitAny, declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString);
22315        }
22316
22317        function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) {
22318            addLazyDiagnostic(() => {
22319                if (noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) {
22320                    // Report implicit any error within type if possible, otherwise report error on declaration
22321                    if (!reportWideningErrorsInType(type)) {
22322                        reportImplicitAny(declaration, type, wideningKind);
22323                    }
22324                }
22325            });
22326        }
22327
22328        function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
22329            const sourceCount = getParameterCount(source);
22330            const targetCount = getParameterCount(target);
22331            const sourceRestType = getEffectiveRestType(source);
22332            const targetRestType = getEffectiveRestType(target);
22333            const targetNonRestCount = targetRestType ? targetCount - 1 : targetCount;
22334            const paramCount = sourceRestType ? targetNonRestCount : Math.min(sourceCount, targetNonRestCount);
22335            const sourceThisType = getThisTypeOfSignature(source);
22336            if (sourceThisType) {
22337                const targetThisType = getThisTypeOfSignature(target);
22338                if (targetThisType) {
22339                    callback(sourceThisType, targetThisType);
22340                }
22341            }
22342            for (let i = 0; i < paramCount; i++) {
22343                callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
22344            }
22345            if (targetRestType) {
22346                callback(getRestTypeAtPosition(source, paramCount), targetRestType);
22347            }
22348        }
22349
22350        function applyToReturnTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
22351            const sourceTypePredicate = getTypePredicateOfSignature(source);
22352            const targetTypePredicate = getTypePredicateOfSignature(target);
22353            if (sourceTypePredicate && targetTypePredicate && typePredicateKindsMatch(sourceTypePredicate, targetTypePredicate) && sourceTypePredicate.type && targetTypePredicate.type) {
22354                callback(sourceTypePredicate.type, targetTypePredicate.type);
22355            }
22356            else {
22357                callback(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
22358            }
22359        }
22360
22361        function createInferenceContext(typeParameters: readonly TypeParameter[], signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer): InferenceContext {
22362            return createInferenceContextWorker(typeParameters.map(createInferenceInfo), signature, flags, compareTypes || compareTypesAssignable);
22363        }
22364
22365        function cloneInferenceContext<T extends InferenceContext | undefined>(context: T, extraFlags: InferenceFlags = 0): InferenceContext | T & undefined {
22366            return context && createInferenceContextWorker(map(context.inferences, cloneInferenceInfo), context.signature, context.flags | extraFlags, context.compareTypes);
22367        }
22368
22369        function createInferenceContextWorker(inferences: InferenceInfo[], signature: Signature | undefined, flags: InferenceFlags, compareTypes: TypeComparer): InferenceContext {
22370            const context: InferenceContext = {
22371                inferences,
22372                signature,
22373                flags,
22374                compareTypes,
22375                mapper: reportUnmeasurableMapper, // initialize to a noop mapper so the context object is available, but the underlying object shape is right upon construction
22376                nonFixingMapper: reportUnmeasurableMapper,
22377            };
22378            context.mapper = makeFixingMapperForContext(context);
22379            context.nonFixingMapper = makeNonFixingMapperForContext(context);
22380            return context;
22381        }
22382
22383        function makeFixingMapperForContext(context: InferenceContext) {
22384            return makeDeferredTypeMapper(map(context.inferences, i => i.typeParameter), map(context.inferences, (inference, i) => () => {
22385                if (!inference.isFixed) {
22386                    // Before we commit to a particular inference (and thus lock out any further inferences),
22387                    // we infer from any intra-expression inference sites we have collected.
22388                    inferFromIntraExpressionSites(context);
22389                    clearCachedInferences(context.inferences);
22390                    inference.isFixed = true;
22391                }
22392                return getInferredType(context, i);
22393            }));
22394        }
22395
22396        function makeNonFixingMapperForContext(context: InferenceContext) {
22397            return makeDeferredTypeMapper(map(context.inferences, i => i.typeParameter), map(context.inferences, (_, i) => () => {
22398                return getInferredType(context, i);
22399            }));
22400        }
22401
22402        function clearCachedInferences(inferences: InferenceInfo[]) {
22403            for (const inference of inferences) {
22404                if (!inference.isFixed) {
22405                    inference.inferredType = undefined;
22406                }
22407            }
22408        }
22409
22410        function addIntraExpressionInferenceSite(context: InferenceContext, node: Expression | MethodDeclaration, type: Type) {
22411            (context.intraExpressionInferenceSites ??= []).push({ node, type });
22412        }
22413
22414        // We collect intra-expression inference sites within object and array literals to handle cases where
22415        // inferred types flow between context sensitive element expressions. For example:
22416        //
22417        //   declare function foo<T>(arg: [(n: number) => T, (x: T) => void]): void;
22418        //   foo([_a => 0, n => n.toFixed()]);
22419        //
22420        // Above, both arrow functions in the tuple argument are context sensitive, thus both are omitted from the
22421        // pass that collects inferences from the non-context sensitive parts of the arguments. In the subsequent
22422        // pass where nothing is omitted, we need to commit to an inference for T in order to contextually type the
22423        // parameter in the second arrow function, but we want to first infer from the return type of the first
22424        // arrow function. This happens automatically when the arrow functions are discrete arguments (because we
22425        // infer from each argument before processing the next), but when the arrow functions are elements of an
22426        // object or array literal, we need to perform intra-expression inferences early.
22427        function inferFromIntraExpressionSites(context: InferenceContext) {
22428            if (context.intraExpressionInferenceSites) {
22429                for (const { node, type } of context.intraExpressionInferenceSites) {
22430                    const contextualType = node.kind === SyntaxKind.MethodDeclaration ?
22431                        getContextualTypeForObjectLiteralMethod(node as MethodDeclaration, ContextFlags.NoConstraints) :
22432                        getContextualType(node, ContextFlags.NoConstraints);
22433                    if (contextualType) {
22434                        inferTypes(context.inferences, type, contextualType);
22435                    }
22436                }
22437                context.intraExpressionInferenceSites = undefined;
22438            }
22439        }
22440
22441        function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
22442            return {
22443                typeParameter,
22444                candidates: undefined,
22445                contraCandidates: undefined,
22446                inferredType: undefined,
22447                priority: undefined,
22448                topLevel: true,
22449                isFixed: false,
22450                impliedArity: undefined
22451            };
22452        }
22453
22454        function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo {
22455            return {
22456                typeParameter: inference.typeParameter,
22457                candidates: inference.candidates && inference.candidates.slice(),
22458                contraCandidates: inference.contraCandidates && inference.contraCandidates.slice(),
22459                inferredType: inference.inferredType,
22460                priority: inference.priority,
22461                topLevel: inference.topLevel,
22462                isFixed: inference.isFixed,
22463                impliedArity: inference.impliedArity
22464            };
22465        }
22466
22467        function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined {
22468            const inferences = filter(context.inferences, hasInferenceCandidates);
22469            return inferences.length ?
22470                createInferenceContextWorker(map(inferences, cloneInferenceInfo), context.signature, context.flags, context.compareTypes) :
22471                undefined;
22472        }
22473
22474        function getMapperFromContext<T extends InferenceContext | undefined>(context: T): TypeMapper | T & undefined {
22475            return context && context.mapper;
22476        }
22477
22478        // Return true if the given type could possibly reference a type parameter for which
22479        // we perform type inference (i.e. a type parameter of a generic function). We cache
22480        // results for union and intersection types for performance reasons.
22481        function couldContainTypeVariables(type: Type): boolean {
22482            const objectFlags = getObjectFlags(type);
22483            if (objectFlags & ObjectFlags.CouldContainTypeVariablesComputed) {
22484                return !!(objectFlags & ObjectFlags.CouldContainTypeVariables);
22485            }
22486            const result = !!(type.flags & TypeFlags.Instantiable ||
22487                type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && (
22488                    objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || forEach(getTypeArguments(type as TypeReference), couldContainTypeVariables)) ||
22489                    objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ||
22490                    objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType)) ||
22491                type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((type as UnionOrIntersectionType).types, couldContainTypeVariables));
22492            if (type.flags & TypeFlags.ObjectFlagsType) {
22493                (type as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | (result ? ObjectFlags.CouldContainTypeVariables : 0);
22494            }
22495            return result;
22496        }
22497
22498        function isNonGenericTopLevelType(type: Type) {
22499            if (type.aliasSymbol && !type.aliasTypeArguments) {
22500                const declaration = getDeclarationOfKind(type.aliasSymbol, SyntaxKind.TypeAliasDeclaration);
22501                return !!(declaration && findAncestor(declaration.parent, n => n.kind === SyntaxKind.SourceFile ? true : n.kind === SyntaxKind.ModuleDeclaration ? false : "quit"));
22502            }
22503            return false;
22504        }
22505
22506        function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean {
22507            return !!(type === typeParameter ||
22508                type.flags & TypeFlags.UnionOrIntersection && some((type as UnionOrIntersectionType).types, t => isTypeParameterAtTopLevel(t, typeParameter)) ||
22509                type.flags & TypeFlags.Conditional && (getTrueTypeFromConditionalType(type as ConditionalType) === typeParameter || getFalseTypeFromConditionalType(type as ConditionalType) === typeParameter));
22510        }
22511
22512        /** Create an object with properties named in the string literal type. Every property has type `any` */
22513        function createEmptyObjectTypeFromStringLiteral(type: Type) {
22514            const members = createSymbolTable();
22515            forEachType(type, t => {
22516                if (!(t.flags & TypeFlags.StringLiteral)) {
22517                    return;
22518                }
22519                const name = escapeLeadingUnderscores((t as StringLiteralType).value);
22520                const literalProp = createSymbol(SymbolFlags.Property, name);
22521                literalProp.type = anyType;
22522                if (t.symbol) {
22523                    literalProp.declarations = t.symbol.declarations;
22524                    literalProp.valueDeclaration = t.symbol.valueDeclaration;
22525                }
22526                members.set(name, literalProp);
22527            });
22528            const indexInfos = type.flags & TypeFlags.String ? [createIndexInfo(stringType, emptyObjectType, /*isReadonly*/ false)] : emptyArray;
22529            return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfos);
22530        }
22531
22532        /**
22533         * Infer a suitable input type for a homomorphic mapped type { [P in keyof T]: X }. We construct
22534         * an object type with the same set of properties as the source type, where the type of each
22535         * property is computed by inferring from the source property type to X for the type
22536         * variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for).
22537         */
22538        function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, constraint: IndexType): Type | undefined {
22539            if (inInferTypeForHomomorphicMappedType) {
22540                return undefined;
22541            }
22542            const key = source.id + "," + target.id + "," + constraint.id;
22543            if (reverseMappedCache.has(key)) {
22544                return reverseMappedCache.get(key);
22545            }
22546            inInferTypeForHomomorphicMappedType = true;
22547            const type = createReverseMappedType(source, target, constraint);
22548            inInferTypeForHomomorphicMappedType = false;
22549            reverseMappedCache.set(key, type);
22550            return type;
22551        }
22552
22553        // We consider a type to be partially inferable if it isn't marked non-inferable or if it is
22554        // an object literal type with at least one property of an inferable type. For example, an object
22555        // literal { a: 123, b: x => true } is marked non-inferable because it contains a context sensitive
22556        // arrow function, but is considered partially inferable because property 'a' has an inferable type.
22557        function isPartiallyInferableType(type: Type): boolean {
22558            return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) ||
22559                isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) ||
22560                isTupleType(type) && some(getTypeArguments(type), isPartiallyInferableType);
22561        }
22562
22563        function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) {
22564            // We consider a source type reverse mappable if it has a string index signature or if
22565            // it has one or more properties and is of a partially inferable type.
22566            if (!(getIndexInfoOfType(source, stringType) || getPropertiesOfType(source).length !== 0 && isPartiallyInferableType(source))) {
22567                return undefined;
22568            }
22569            // For arrays and tuples we infer new arrays and tuples where the reverse mapping has been
22570            // applied to the element type(s).
22571            if (isArrayType(source)) {
22572                return createArrayType(inferReverseMappedType(getTypeArguments(source)[0], target, constraint), isReadonlyArrayType(source));
22573            }
22574            if (isTupleType(source)) {
22575                const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
22576                const elementFlags = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
22577                    sameMap(source.target.elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) :
22578                    source.target.elementFlags;
22579                return createTupleType(elementTypes, elementFlags, source.target.readonly, source.target.labeledElementDeclarations);
22580            }
22581            // For all other object types we infer a new object type where the reverse mapping has been
22582            // applied to the type of each property.
22583            const reversed = createObjectType(ObjectFlags.ReverseMapped | ObjectFlags.Anonymous, /*symbol*/ undefined) as ReverseMappedType;
22584            reversed.source = source;
22585            reversed.mappedType = target;
22586            reversed.constraintType = constraint;
22587            return reversed;
22588        }
22589
22590        function getTypeOfReverseMappedSymbol(symbol: ReverseMappedSymbol) {
22591            const links = getSymbolLinks(symbol);
22592            if (!links.type) {
22593                links.type = inferReverseMappedType(symbol.propertyType, symbol.mappedType, symbol.constraintType);
22594            }
22595            return links.type;
22596        }
22597
22598        function inferReverseMappedType(sourceType: Type, target: MappedType, constraint: IndexType): Type {
22599            const typeParameter = getIndexedAccessType(constraint.type, getTypeParameterFromMappedType(target)) as TypeParameter;
22600            const templateType = getTemplateTypeFromMappedType(target);
22601            const inference = createInferenceInfo(typeParameter);
22602            inferTypes([inference], sourceType, templateType);
22603            return getTypeFromInference(inference) || unknownType;
22604        }
22605
22606        function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): IterableIterator<Symbol> {
22607            const properties = getPropertiesOfType(target);
22608            for (const targetProp of properties) {
22609                // TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass
22610                if (isStaticPrivateIdentifierProperty(targetProp)) {
22611                    continue;
22612                }
22613                if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial)) {
22614                    const sourceProp = getPropertyOfType(source, targetProp.escapedName);
22615                    if (!sourceProp) {
22616                        yield targetProp;
22617                    }
22618                    else if (matchDiscriminantProperties) {
22619                        const targetType = getTypeOfSymbol(targetProp);
22620                        if (targetType.flags & TypeFlags.Unit) {
22621                            const sourceType = getTypeOfSymbol(sourceProp);
22622                            if (!(sourceType.flags & TypeFlags.Any || getRegularTypeOfLiteralType(sourceType) === getRegularTypeOfLiteralType(targetType))) {
22623                                yield targetProp;
22624                            }
22625                        }
22626                    }
22627                }
22628            }
22629        }
22630
22631        function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): Symbol | undefined {
22632            const result = getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties).next();
22633            if (!result.done) return result.value;
22634        }
22635
22636        function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) {
22637            return !(target.target.combinedFlags & ElementFlags.Variadic) && target.target.minLength > source.target.minLength ||
22638                !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength);
22639        }
22640
22641        function typesDefinitelyUnrelated(source: Type, target: Type) {
22642            // Two tuple types with incompatible arities are definitely unrelated.
22643            // Two object types that each have a property that is unmatched in the other are definitely unrelated.
22644            return isTupleType(source) && isTupleType(target) ? tupleTypesDefinitelyUnrelated(source, target) :
22645                !!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ true) &&
22646                !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ false);
22647        }
22648
22649        function getTypeFromInference(inference: InferenceInfo) {
22650            return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) :
22651                inference.contraCandidates ? getIntersectionType(inference.contraCandidates) :
22652                undefined;
22653        }
22654
22655        function hasSkipDirectInferenceFlag(node: Node) {
22656            return !!getNodeLinks(node).skipDirectInference;
22657        }
22658
22659        function isFromInferenceBlockedSource(type: Type) {
22660            return !!(type.symbol && some(type.symbol.declarations, hasSkipDirectInferenceFlag));
22661        }
22662
22663        function templateLiteralTypesDefinitelyUnrelated(source: TemplateLiteralType, target: TemplateLiteralType) {
22664            // Two template literal types with diffences in their starting or ending text spans are definitely unrelated.
22665            const sourceStart = source.texts[0];
22666            const targetStart = target.texts[0];
22667            const sourceEnd = source.texts[source.texts.length - 1];
22668            const targetEnd = target.texts[target.texts.length - 1];
22669            const startLen = Math.min(sourceStart.length, targetStart.length);
22670            const endLen = Math.min(sourceEnd.length, targetEnd.length);
22671            return sourceStart.slice(0, startLen) !== targetStart.slice(0, startLen) ||
22672                sourceEnd.slice(sourceEnd.length - endLen) !== targetEnd.slice(targetEnd.length - endLen);
22673        }
22674
22675        /**
22676         * Tests whether the provided string can be parsed as a number.
22677         * @param s The string to test.
22678         * @param roundTripOnly Indicates the resulting number matches the input when converted back to a string.
22679         */
22680        function isValidNumberString(s: string, roundTripOnly: boolean): boolean {
22681            if (s === "") return false;
22682            const n = +s;
22683            return isFinite(n) && (!roundTripOnly || "" + n === s);
22684        }
22685
22686        /**
22687         * @param text a valid bigint string excluding a trailing `n`, but including a possible prefix `-`. Use `isValidBigIntString(text, roundTripOnly)` before calling this function.
22688         */
22689        function parseBigIntLiteralType(text: string) {
22690            const negative = text.startsWith("-");
22691            const base10Value = parsePseudoBigInt(`${negative ? text.slice(1) : text}n`);
22692            return getBigIntLiteralType({ negative, base10Value });
22693        }
22694
22695        /**
22696         * Tests whether the provided string can be parsed as a bigint.
22697         * @param s The string to test.
22698         * @param roundTripOnly Indicates the resulting bigint matches the input when converted back to a string.
22699         */
22700        function isValidBigIntString(s: string, roundTripOnly: boolean): boolean {
22701            if (s === "") return false;
22702            const scanner = createScanner(ScriptTarget.ESNext, /*skipTrivia*/ false);
22703            let success = true;
22704            scanner.setOnError(() => success = false);
22705            scanner.setText(s + "n");
22706            let result = scanner.scan();
22707            const negative = result === SyntaxKind.MinusToken;
22708            if (negative) {
22709                result = scanner.scan();
22710            }
22711            const flags = scanner.getTokenFlags();
22712            // validate that
22713            // * scanning proceeded without error
22714            // * a bigint can be scanned, and that when it is scanned, it is
22715            // * the full length of the input string (so the scanner is one character beyond the augmented input length)
22716            // * it does not contain a numeric seperator (the `BigInt` constructor does not accept a numeric seperator in its input)
22717            return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator)
22718                && (!roundTripOnly || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) }));
22719        }
22720
22721        function isMemberOfStringMapping(source: Type, target: Type): boolean {
22722            if (target.flags & (TypeFlags.String | TypeFlags.Any)) {
22723                return true;
22724            }
22725            if (target.flags & TypeFlags.TemplateLiteral) {
22726                return isTypeAssignableTo(source, target);
22727            }
22728            if (target.flags & TypeFlags.StringMapping) {
22729                // We need to see whether applying the same mappings of the target
22730                // onto the source would produce an identical type *and* that
22731                // it's compatible with the inner-most non-string-mapped type.
22732                //
22733                // The intuition here is that if same mappings don't affect the source at all,
22734                // and the source is compatible with the unmapped target, then they must
22735                // still reside in the same domain.
22736                const mappingStack = [];
22737                while (target.flags & TypeFlags.StringMapping) {
22738                    mappingStack.unshift(target.symbol);
22739                    target = (target as StringMappingType).type;
22740                }
22741                const mappedSource = reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source);
22742                return mappedSource === source && isMemberOfStringMapping(source, target);
22743            }
22744            return false;
22745        }
22746
22747        function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean {
22748            if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) {
22749                return true;
22750            }
22751            if (source.flags & TypeFlags.StringLiteral) {
22752                const value = (source as StringLiteralType).value;
22753                return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) ||
22754                    target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) ||
22755                    target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName ||
22756                    target.flags & TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target));
22757            }
22758            if (source.flags & TypeFlags.TemplateLiteral) {
22759                const texts = (source as TemplateLiteralType).texts;
22760                return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as TemplateLiteralType).types[0], target);
22761            }
22762            return isTypeAssignableTo(source, target);
22763        }
22764
22765        function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined {
22766            return source.flags & TypeFlags.StringLiteral ? inferFromLiteralPartsToTemplateLiteral([(source as StringLiteralType).value], emptyArray, target) :
22767                source.flags & TypeFlags.TemplateLiteral ?
22768                    arraysEqual((source as TemplateLiteralType).texts, target.texts) ? map((source as TemplateLiteralType).types, getStringLikeTypeForType) :
22769                    inferFromLiteralPartsToTemplateLiteral((source as TemplateLiteralType).texts, (source as TemplateLiteralType).types, target) :
22770                undefined;
22771        }
22772
22773        function isTypeMatchedByTemplateLiteralType(source: Type, target: TemplateLiteralType): boolean {
22774            const inferences = inferTypesFromTemplateLiteralType(source, target);
22775            return !!inferences && every(inferences, (r, i) => isValidTypeForTemplateLiteralPlaceholder(r, target.types[i]));
22776        }
22777
22778        function getStringLikeTypeForType(type: Type) {
22779            return type.flags & (TypeFlags.Any | TypeFlags.StringLike) ? type : getTemplateLiteralType(["", ""], [type]);
22780        }
22781
22782        // This function infers from the text parts and type parts of a source literal to a target template literal. The number
22783        // of text parts is always one more than the number of type parts, and a source string literal is treated as a source
22784        // with one text part and zero type parts. The function returns an array of inferred string or template literal types
22785        // corresponding to the placeholders in the target template literal, or undefined if the source doesn't match the target.
22786        //
22787        // We first check that the starting source text part matches the starting target text part, and that the ending source
22788        // text part ends matches the ending target text part. We then iterate through the remaining target text parts, finding
22789        // a match for each in the source and inferring string or template literal types created from the segments of the source
22790        // that occur between the matches. During this iteration, seg holds the index of the current text part in the sourceTexts
22791        // array and pos holds the current character position in the current text part.
22792        //
22793        // Consider inference from type `<<${string}>.<${number}-${number}>>` to type `<${string}.${string}>`, i.e.
22794        //   sourceTexts = ['<<', '>.<', '-', '>>']
22795        //   sourceTypes = [string, number, number]
22796        //   target.texts = ['<', '.', '>']
22797        // We first match '<' in the target to the start of '<<' in the source and '>' in the target to the end of '>>' in
22798        // the source. The first match for the '.' in target occurs at character 1 in the source text part at index 1, and thus
22799        // the first inference is the template literal type `<${string}>`. The remainder of the source makes up the second
22800        // inference, the template literal type `<${number}-${number}>`.
22801        function inferFromLiteralPartsToTemplateLiteral(sourceTexts: readonly string[], sourceTypes: readonly Type[], target: TemplateLiteralType): Type[] | undefined {
22802            const lastSourceIndex = sourceTexts.length - 1;
22803            const sourceStartText = sourceTexts[0];
22804            const sourceEndText = sourceTexts[lastSourceIndex];
22805            const targetTexts = target.texts;
22806            const lastTargetIndex = targetTexts.length - 1;
22807            const targetStartText = targetTexts[0];
22808            const targetEndText = targetTexts[lastTargetIndex];
22809            if (lastSourceIndex === 0 && sourceStartText.length < targetStartText.length + targetEndText.length ||
22810                !sourceStartText.startsWith(targetStartText) || !sourceEndText.endsWith(targetEndText)) return undefined;
22811            const remainingEndText = sourceEndText.slice(0, sourceEndText.length - targetEndText.length);
22812            const matches: Type[] = [];
22813            let seg = 0;
22814            let pos = targetStartText.length;
22815            for (let i = 1; i < lastTargetIndex; i++) {
22816                const delim = targetTexts[i];
22817                if (delim.length > 0) {
22818                    let s = seg;
22819                    let p = pos;
22820                    while (true) {
22821                        p = getSourceText(s).indexOf(delim, p);
22822                        if (p >= 0) break;
22823                        s++;
22824                        if (s === sourceTexts.length) return undefined;
22825                        p = 0;
22826                    }
22827                    addMatch(s, p);
22828                    pos += delim.length;
22829                }
22830                else if (pos < getSourceText(seg).length) {
22831                    addMatch(seg, pos + 1);
22832                }
22833                else if (seg < lastSourceIndex) {
22834                    addMatch(seg + 1, 0);
22835                }
22836                else {
22837                    return undefined;
22838                }
22839            }
22840            addMatch(lastSourceIndex, getSourceText(lastSourceIndex).length);
22841            return matches;
22842            function getSourceText(index: number) {
22843                return index < lastSourceIndex ? sourceTexts[index] : remainingEndText;
22844            }
22845            function addMatch(s: number, p: number) {
22846                const matchType = s === seg ?
22847                    getStringLiteralType(getSourceText(s).slice(pos, p)) :
22848                    getTemplateLiteralType(
22849                        [sourceTexts[seg].slice(pos), ...sourceTexts.slice(seg + 1, s), getSourceText(s).slice(0, p)],
22850                        sourceTypes.slice(seg, s));
22851                matches.push(matchType);
22852                seg = s;
22853                pos = p;
22854            }
22855        }
22856
22857        function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, contravariant = false) {
22858            let bivariant = false;
22859            let propagationType: Type;
22860            let inferencePriority = InferencePriority.MaxValue;
22861            let allowComplexConstraintInference = true;
22862            let visited: ESMap<string, number>;
22863            let sourceStack: object[];
22864            let targetStack: object[];
22865            let expandingFlags = ExpandingFlags.None;
22866            inferFromTypes(originalSource, originalTarget);
22867
22868            function inferFromTypes(source: Type, target: Type): void {
22869                if (!couldContainTypeVariables(target)) {
22870                    return;
22871                }
22872                if (source === wildcardType) {
22873                    // We are inferring from an 'any' type. We want to infer this type for every type parameter
22874                    // referenced in the target type, so we record it as the propagation type and infer from the
22875                    // target to itself. Then, as we find candidates we substitute the propagation type.
22876                    const savePropagationType = propagationType;
22877                    propagationType = source;
22878                    inferFromTypes(target, target);
22879                    propagationType = savePropagationType;
22880                    return;
22881                }
22882                if (source.aliasSymbol && source.aliasSymbol === target.aliasSymbol) {
22883                    if (source.aliasTypeArguments) {
22884                        // Source and target are types originating in the same generic type alias declaration.
22885                        // Simply infer from source type arguments to target type arguments.
22886                        inferFromTypeArguments(source.aliasTypeArguments, target.aliasTypeArguments!, getAliasVariances(source.aliasSymbol));
22887                    }
22888                    // And if there weren't any type arguments, there's no reason to run inference as the types must be the same.
22889                    return;
22890                }
22891                if (source === target && source.flags & TypeFlags.UnionOrIntersection) {
22892                    // When source and target are the same union or intersection type, just relate each constituent
22893                    // type to itself.
22894                    for (const t of (source as UnionOrIntersectionType).types) {
22895                        inferFromTypes(t, t);
22896                    }
22897                    return;
22898                }
22899                if (target.flags & TypeFlags.Union) {
22900                    // First, infer between identically matching source and target constituents and remove the
22901                    // matching types.
22902                    const [tempSources, tempTargets] = inferFromMatchingTypes(source.flags & TypeFlags.Union ? (source as UnionType).types : [source], (target as UnionType).types, isTypeOrBaseIdenticalTo);
22903                    // Next, infer between closely matching source and target constituents and remove
22904                    // the matching types. Types closely match when they are instantiations of the same
22905                    // object type or instantiations of the same type alias.
22906                    const [sources, targets] = inferFromMatchingTypes(tempSources, tempTargets, isTypeCloselyMatchedBy);
22907                    if (targets.length === 0) {
22908                        return;
22909                    }
22910                    target = getUnionType(targets);
22911                    if (sources.length === 0) {
22912                        // All source constituents have been matched and there is nothing further to infer from.
22913                        // However, simply making no inferences is undesirable because it could ultimately mean
22914                        // inferring a type parameter constraint. Instead, make a lower priority inference from
22915                        // the full source to whatever remains in the target. For example, when inferring from
22916                        // string to 'string | T', make a lower priority inference of string for T.
22917                        inferWithPriority(source, target, InferencePriority.NakedTypeVariable);
22918                        return;
22919                    }
22920                    source = getUnionType(sources);
22921                }
22922                else if (target.flags & TypeFlags.Intersection && some((target as IntersectionType).types,
22923                    t => !!getInferenceInfoForType(t) || (isGenericMappedType(t) && !!getInferenceInfoForType(getHomomorphicTypeVariable(t) || neverType)))) {
22924                    // We reduce intersection types only when they contain naked type parameters. For example, when
22925                    // inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and
22926                    // infer { extra: any } for T. But when inferring to 'string[] & Iterable<T>' we want to keep the
22927                    // string[] on the source side and infer string for T.
22928                    // Likewise, we consider a homomorphic mapped type constrainted to the target type parameter as similar to a "naked type variable"
22929                    // in such scenarios.
22930                    if (!(source.flags & TypeFlags.Union)) {
22931                        // Infer between identically matching source and target constituents and remove the matching types.
22932                        const [sources, targets] = inferFromMatchingTypes(source.flags & TypeFlags.Intersection ? (source as IntersectionType).types : [source], (target as IntersectionType).types, isTypeIdenticalTo);
22933                        if (sources.length === 0 || targets.length === 0) {
22934                            return;
22935                        }
22936                        source = getIntersectionType(sources);
22937                        target = getIntersectionType(targets);
22938                    }
22939                }
22940                else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) {
22941                    target = getActualTypeVariable(target);
22942                }
22943                if (target.flags & TypeFlags.TypeVariable) {
22944                    // Skip inference if the source is "blocked", which is used by the language service to
22945                    // prevent inference on nodes currently being edited.
22946                    if (isFromInferenceBlockedSource(source)) {
22947                        return;
22948                    }
22949                    const inference = getInferenceInfoForType(target);
22950                    if (inference) {
22951                        // If target is a type parameter, make an inference, unless the source type contains
22952                        // a "non-inferrable" type. Types with this flag set are markers used to prevent inference.
22953                        //
22954                        // For example:
22955                        //     - anyFunctionType is a wildcard type that's used to avoid contextually typing functions;
22956                        //       it's internal, so should not be exposed to the user by adding it as a candidate.
22957                        //     - autoType (and autoArrayType) is a special "any" used in control flow; like anyFunctionType,
22958                        //       it's internal and should not be observable.
22959                        //     - silentNeverType is returned by getInferredType when instantiating a generic function for
22960                        //       inference (and a type variable has no mapping).
22961                        //
22962                        // This flag is infectious; if we produce Box<never> (where never is silentNeverType), Box<never> is
22963                        // also non-inferrable.
22964                        //
22965                        // As a special case, also ignore nonInferrableAnyType, which is a special form of the any type
22966                        // used as a stand-in for binding elements when they are being inferred.
22967                        if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === nonInferrableAnyType) {
22968                            return;
22969                        }
22970                        if (!inference.isFixed) {
22971                            if (inference.priority === undefined || priority < inference.priority) {
22972                                inference.candidates = undefined;
22973                                inference.contraCandidates = undefined;
22974                                inference.topLevel = true;
22975                                inference.priority = priority;
22976                            }
22977                            if (priority === inference.priority) {
22978                                const candidate = propagationType || source;
22979                                // We make contravariant inferences only if we are in a pure contravariant position,
22980                                // i.e. only if we have not descended into a bivariant position.
22981                                if (contravariant && !bivariant) {
22982                                    if (!contains(inference.contraCandidates, candidate)) {
22983                                        inference.contraCandidates = append(inference.contraCandidates, candidate);
22984                                        clearCachedInferences(inferences);
22985                                    }
22986                                }
22987                                else if (!contains(inference.candidates, candidate)) {
22988                                    inference.candidates = append(inference.candidates, candidate);
22989                                    clearCachedInferences(inferences);
22990                                }
22991                            }
22992                            if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, target as TypeParameter)) {
22993                                inference.topLevel = false;
22994                                clearCachedInferences(inferences);
22995                            }
22996                        }
22997                        inferencePriority = Math.min(inferencePriority, priority);
22998                        return;
22999                    }
23000                    // Infer to the simplified version of an indexed access, if possible, to (hopefully) expose more bare type parameters to the inference engine
23001                    const simplified = getSimplifiedType(target, /*writing*/ false);
23002                    if (simplified !== target) {
23003                        inferFromTypes(source, simplified);
23004                    }
23005                    else if (target.flags & TypeFlags.IndexedAccess) {
23006                        const indexType = getSimplifiedType((target as IndexedAccessType).indexType, /*writing*/ false);
23007                        // Generally simplifications of instantiable indexes are avoided to keep relationship checking correct, however if our target is an access, we can consider
23008                        // that key of that access to be "instantiated", since we're looking to find the infernce goal in any way we can.
23009                        if (indexType.flags & TypeFlags.Instantiable) {
23010                            const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false), indexType, /*writing*/ false);
23011                            if (simplified && simplified !== target) {
23012                                inferFromTypes(source, simplified);
23013                            }
23014                        }
23015                    }
23016                }
23017                if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (
23018                    (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target)) &&
23019                    !((source as TypeReference).node && (target as TypeReference).node)) {
23020                    // If source and target are references to the same generic type, infer from type arguments
23021                    inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target));
23022                }
23023                else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) {
23024                    inferFromContravariantTypes((source as IndexType).type, (target as IndexType).type);
23025                }
23026                else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) {
23027                    const empty = createEmptyObjectTypeFromStringLiteral(source);
23028                    inferFromContravariantTypesWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof);
23029                }
23030                else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) {
23031                    inferFromTypes((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType);
23032                    inferFromTypes((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType);
23033                }
23034                else if (source.flags & TypeFlags.StringMapping && target.flags & TypeFlags.StringMapping) {
23035                    if ((source as StringMappingType).symbol === (target as StringMappingType).symbol) {
23036                        inferFromTypes((source as StringMappingType).type, (target as StringMappingType).type);
23037                    }
23038                }
23039                else if (source.flags & TypeFlags.Substitution) {
23040                    inferFromTypes((source as SubstitutionType).baseType, target);
23041                    inferWithPriority(getSubstitutionIntersection(source as SubstitutionType), target, InferencePriority.SubstituteSource); // Make substitute inference at a lower priority
23042                }
23043                else if (target.flags & TypeFlags.Conditional) {
23044                    invokeOnce(source, target, inferToConditionalType);
23045                }
23046                else if (target.flags & TypeFlags.UnionOrIntersection) {
23047                    inferToMultipleTypes(source, (target as UnionOrIntersectionType).types, target.flags);
23048                }
23049                else if (source.flags & TypeFlags.Union) {
23050                    // Source is a union or intersection type, infer from each constituent type
23051                    const sourceTypes = (source as UnionOrIntersectionType).types;
23052                    for (const sourceType of sourceTypes) {
23053                        inferFromTypes(sourceType, target);
23054                    }
23055                }
23056                else if (target.flags & TypeFlags.TemplateLiteral) {
23057                    inferToTemplateLiteralType(source, target as TemplateLiteralType);
23058                }
23059                else {
23060                    source = getReducedType(source);
23061                    if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) {
23062                        const apparentSource = getApparentType(source);
23063                        // getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type.
23064                        // If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes`
23065                        // with the simplified source.
23066                        if (apparentSource !== source && allowComplexConstraintInference && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
23067                            // TODO: The `allowComplexConstraintInference` flag is a hack! This forbids inference from complex constraints within constraints!
23068                            // This isn't required algorithmically, but rather is used to lower the memory burden caused by performing inference
23069                            // that is _too good_ in projects with complicated constraints (eg, fp-ts). In such cases, if we did not limit ourselves
23070                            // here, we might produce more valid inferences for types, causing us to do more checks and perform more instantiations
23071                            // (in addition to the extra stack depth here) which, in turn, can push the already close process over its limit.
23072                            // TL;DR: If we ever become generally more memory efficient (or our resource budget ever increases), we should just
23073                            // remove this `allowComplexConstraintInference` flag.
23074                            allowComplexConstraintInference = false;
23075                            return inferFromTypes(apparentSource, target);
23076                        }
23077                        source = apparentSource;
23078                    }
23079                    if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
23080                        invokeOnce(source, target, inferFromObjectTypes);
23081                    }
23082                }
23083            }
23084
23085            function inferWithPriority(source: Type, target: Type, newPriority: InferencePriority) {
23086                const savePriority = priority;
23087                priority |= newPriority;
23088                inferFromTypes(source, target);
23089                priority = savePriority;
23090            }
23091
23092            function inferFromContravariantTypesWithPriority(source: Type, target: Type, newPriority: InferencePriority) {
23093                const savePriority = priority;
23094                priority |= newPriority;
23095                inferFromContravariantTypes(source, target);
23096                priority = savePriority;
23097            }
23098
23099            function inferToMultipleTypesWithPriority(source: Type, targets: Type[], targetFlags: TypeFlags, newPriority: InferencePriority) {
23100                const savePriority = priority;
23101                priority |= newPriority;
23102                inferToMultipleTypes(source, targets, targetFlags);
23103                priority = savePriority;
23104            }
23105
23106            function invokeOnce(source: Type, target: Type, action: (source: Type, target: Type) => void) {
23107                const key = source.id + "," + target.id;
23108                const status = visited && visited.get(key);
23109                if (status !== undefined) {
23110                    inferencePriority = Math.min(inferencePriority, status);
23111                    return;
23112                }
23113                (visited || (visited = new Map<string, number>())).set(key, InferencePriority.Circularity);
23114                const saveInferencePriority = inferencePriority;
23115                inferencePriority = InferencePriority.MaxValue;
23116                // We stop inferring and report a circularity if we encounter duplicate recursion identities on both
23117                // the source side and the target side.
23118                const saveExpandingFlags = expandingFlags;
23119                const sourceIdentity = getRecursionIdentity(source);
23120                const targetIdentity = getRecursionIdentity(target);
23121                if (contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source;
23122                if (contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target;
23123                if (expandingFlags !== ExpandingFlags.Both) {
23124                    (sourceStack || (sourceStack = [])).push(sourceIdentity);
23125                    (targetStack || (targetStack = [])).push(targetIdentity);
23126                    action(source, target);
23127                    targetStack.pop();
23128                    sourceStack.pop();
23129                }
23130                else {
23131                    inferencePriority = InferencePriority.Circularity;
23132                }
23133                expandingFlags = saveExpandingFlags;
23134                visited.set(key, inferencePriority);
23135                inferencePriority = Math.min(inferencePriority, saveInferencePriority);
23136            }
23137
23138            function inferFromMatchingTypes(sources: Type[], targets: Type[], matches: (s: Type, t: Type) => boolean): [Type[], Type[]] {
23139                let matchedSources: Type[] | undefined;
23140                let matchedTargets: Type[] | undefined;
23141                for (const t of targets) {
23142                    for (const s of sources) {
23143                        if (matches(s, t)) {
23144                            inferFromTypes(s, t);
23145                            matchedSources = appendIfUnique(matchedSources, s);
23146                            matchedTargets = appendIfUnique(matchedTargets, t);
23147                        }
23148                    }
23149                }
23150                return [
23151                    matchedSources ? filter(sources, t => !contains(matchedSources, t)) : sources,
23152                    matchedTargets ? filter(targets, t => !contains(matchedTargets, t)) : targets,
23153                ];
23154            }
23155
23156            function inferFromTypeArguments(sourceTypes: readonly Type[], targetTypes: readonly Type[], variances: readonly VarianceFlags[]) {
23157                const count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length;
23158                for (let i = 0; i < count; i++) {
23159                    if (i < variances.length && (variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Contravariant) {
23160                        inferFromContravariantTypes(sourceTypes[i], targetTypes[i]);
23161                    }
23162                    else {
23163                        inferFromTypes(sourceTypes[i], targetTypes[i]);
23164                    }
23165                }
23166            }
23167
23168            function inferFromContravariantTypes(source: Type, target: Type) {
23169                contravariant = !contravariant;
23170                inferFromTypes(source, target);
23171                contravariant = !contravariant;
23172            }
23173
23174            function inferFromContravariantTypesIfStrictFunctionTypes(source: Type, target: Type) {
23175                if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) {
23176                    inferFromContravariantTypes(source, target);
23177                }
23178                else {
23179                    inferFromTypes(source, target);
23180                }
23181            }
23182
23183            function getInferenceInfoForType(type: Type) {
23184                if (type.flags & TypeFlags.TypeVariable) {
23185                    for (const inference of inferences) {
23186                        if (type === inference.typeParameter) {
23187                            return inference;
23188                        }
23189                    }
23190                }
23191                return undefined;
23192            }
23193
23194            function getSingleTypeVariableFromIntersectionTypes(types: Type[]) {
23195                let typeVariable: Type | undefined;
23196                for (const type of types) {
23197                    const t = type.flags & TypeFlags.Intersection && find((type as IntersectionType).types, t => !!getInferenceInfoForType(t));
23198                    if (!t || typeVariable && t !== typeVariable) {
23199                        return undefined;
23200                    }
23201                    typeVariable = t;
23202                }
23203                return typeVariable;
23204            }
23205
23206            function inferToMultipleTypes(source: Type, targets: Type[], targetFlags: TypeFlags) {
23207                let typeVariableCount = 0;
23208                if (targetFlags & TypeFlags.Union) {
23209                    let nakedTypeVariable: Type | undefined;
23210                    const sources = source.flags & TypeFlags.Union ? (source as UnionType).types : [source];
23211                    const matched = new Array<boolean>(sources.length);
23212                    let inferenceCircularity = false;
23213                    // First infer to types that are not naked type variables. For each source type we
23214                    // track whether inferences were made from that particular type to some target with
23215                    // equal priority (i.e. of equal quality) to what we would infer for a naked type
23216                    // parameter.
23217                    for (const t of targets) {
23218                        if (getInferenceInfoForType(t)) {
23219                            nakedTypeVariable = t;
23220                            typeVariableCount++;
23221                        }
23222                        else {
23223                            for (let i = 0; i < sources.length; i++) {
23224                                const saveInferencePriority = inferencePriority;
23225                                inferencePriority = InferencePriority.MaxValue;
23226                                inferFromTypes(sources[i], t);
23227                                if (inferencePriority === priority) matched[i] = true;
23228                                inferenceCircularity = inferenceCircularity || inferencePriority === InferencePriority.Circularity;
23229                                inferencePriority = Math.min(inferencePriority, saveInferencePriority);
23230                            }
23231                        }
23232                    }
23233                    if (typeVariableCount === 0) {
23234                        // If every target is an intersection of types containing a single naked type variable,
23235                        // make a lower priority inference to that type variable. This handles inferring from
23236                        // 'A | B' to 'T & (X | Y)' where we want to infer 'A | B' for T.
23237                        const intersectionTypeVariable = getSingleTypeVariableFromIntersectionTypes(targets);
23238                        if (intersectionTypeVariable) {
23239                            inferWithPriority(source, intersectionTypeVariable, InferencePriority.NakedTypeVariable);
23240                        }
23241                        return;
23242                    }
23243                    // If the target has a single naked type variable and no inference circularities were
23244                    // encountered above (meaning we explored the types fully), create a union of the source
23245                    // types from which no inferences have been made so far and infer from that union to the
23246                    // naked type variable.
23247                    if (typeVariableCount === 1 && !inferenceCircularity) {
23248                        const unmatched = flatMap(sources, (s, i) => matched[i] ? undefined : s);
23249                        if (unmatched.length) {
23250                            inferFromTypes(getUnionType(unmatched), nakedTypeVariable!);
23251                            return;
23252                        }
23253                    }
23254                }
23255                else {
23256                    // We infer from types that are not naked type variables first so that inferences we
23257                    // make from nested naked type variables and given slightly higher priority by virtue
23258                    // of being first in the candidates array.
23259                    for (const t of targets) {
23260                        if (getInferenceInfoForType(t)) {
23261                            typeVariableCount++;
23262                        }
23263                        else {
23264                            inferFromTypes(source, t);
23265                        }
23266                    }
23267                }
23268                // Inferences directly to naked type variables are given lower priority as they are
23269                // less specific. For example, when inferring from Promise<string> to T | Promise<T>,
23270                // we want to infer string for T, not Promise<string> | string. For intersection types
23271                // we only infer to single naked type variables.
23272                if (targetFlags & TypeFlags.Intersection ? typeVariableCount === 1 : typeVariableCount > 0) {
23273                    for (const t of targets) {
23274                        if (getInferenceInfoForType(t)) {
23275                            inferWithPriority(source, t, InferencePriority.NakedTypeVariable);
23276                        }
23277                    }
23278                }
23279            }
23280
23281            function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean {
23282                if (constraintType.flags & TypeFlags.Union) {
23283                    let result = false;
23284                    for (const type of (constraintType as UnionType).types) {
23285                        result = inferToMappedType(source, target, type) || result;
23286                    }
23287                    return result;
23288                }
23289                if (constraintType.flags & TypeFlags.Index) {
23290                    // We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X },
23291                    // where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source
23292                    // type and then make a secondary inference from that type to T. We make a secondary inference
23293                    // such that direct inferences to T get priority over inferences to Partial<T>, for example.
23294                    const inference = getInferenceInfoForType((constraintType as IndexType).type);
23295                    if (inference && !inference.isFixed && !isFromInferenceBlockedSource(source)) {
23296                        const inferredType = inferTypeForHomomorphicMappedType(source, target, constraintType as IndexType);
23297                        if (inferredType) {
23298                            // We assign a lower priority to inferences made from types containing non-inferrable
23299                            // types because we may only have a partial result (i.e. we may have failed to make
23300                            // reverse inferences for some properties).
23301                            inferWithPriority(inferredType, inference.typeParameter,
23302                                getObjectFlags(source) & ObjectFlags.NonInferrableType ?
23303                                    InferencePriority.PartialHomomorphicMappedType :
23304                                    InferencePriority.HomomorphicMappedType);
23305                        }
23306                    }
23307                    return true;
23308                }
23309                if (constraintType.flags & TypeFlags.TypeParameter) {
23310                    // We're inferring from some source type S to a mapped type { [P in K]: X }, where K is a type
23311                    // parameter. First infer from 'keyof S' to K.
23312                    inferWithPriority(getIndexType(source), constraintType, InferencePriority.MappedTypeConstraint);
23313                    // If K is constrained to a type C, also infer to C. Thus, for a mapped type { [P in K]: X },
23314                    // where K extends keyof T, we make the same inferences as for a homomorphic mapped type
23315                    // { [P in keyof T]: X }. This enables us to make meaningful inferences when the target is a
23316                    // Pick<T, K>.
23317                    const extendedConstraint = getConstraintOfType(constraintType);
23318                    if (extendedConstraint && inferToMappedType(source, target, extendedConstraint)) {
23319                        return true;
23320                    }
23321                    // If no inferences can be made to K's constraint, infer from a union of the property types
23322                    // in the source to the template type X.
23323                    const propTypes = map(getPropertiesOfType(source), getTypeOfSymbol);
23324                    const indexTypes = map(getIndexInfosOfType(source), info => info !== enumNumberIndexInfo ? info.type : neverType);
23325                    inferFromTypes(getUnionType(concatenate(propTypes, indexTypes)), getTemplateTypeFromMappedType(target));
23326                    return true;
23327                }
23328                return false;
23329            }
23330
23331            function inferToConditionalType(source: Type, target: ConditionalType) {
23332                if (source.flags & TypeFlags.Conditional) {
23333                    inferFromTypes((source as ConditionalType).checkType, target.checkType);
23334                    inferFromTypes((source as ConditionalType).extendsType, target.extendsType);
23335                    inferFromTypes(getTrueTypeFromConditionalType(source as ConditionalType), getTrueTypeFromConditionalType(target));
23336                    inferFromTypes(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target));
23337                }
23338                else {
23339                    const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)];
23340                    inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0);
23341                }
23342            }
23343
23344            function inferToTemplateLiteralType(source: Type, target: TemplateLiteralType) {
23345                const matches = inferTypesFromTemplateLiteralType(source, target);
23346                const types = target.types;
23347                // When the target template literal contains only placeholders (meaning that inference is intended to extract
23348                // single characters and remainder strings) and inference fails to produce matches, we want to infer 'never' for
23349                // each placeholder such that instantiation with the inferred value(s) produces 'never', a type for which an
23350                // assignment check will fail. If we make no inferences, we'll likely end up with the constraint 'string' which,
23351                // upon instantiation, would collapse all the placeholders to just 'string', and an assignment check might
23352                // succeed. That would be a pointless and confusing outcome.
23353                if (matches || every(target.texts, s => s.length === 0)) {
23354                    for (let i = 0; i < types.length; i++) {
23355                        const source = matches ? matches[i] : neverType;
23356                        const target = types[i];
23357
23358                        // If we are inferring from a string literal type to a type variable whose constraint includes one of the
23359                        // allowed template literal placeholder types, infer from a literal type corresponding to the constraint.
23360                        if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) {
23361                            const inferenceContext = getInferenceInfoForType(target);
23362                            const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined;
23363                            if (constraint && !isTypeAny(constraint)) {
23364                                const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint];
23365                                let allTypeFlags: TypeFlags = reduceLeft(constraintTypes, (flags, t) => flags | t.flags, 0 as TypeFlags);
23366
23367                                // If the constraint contains `string`, we don't need to look for a more preferred type
23368                                if (!(allTypeFlags & TypeFlags.String)) {
23369                                    const str = (source as StringLiteralType).value;
23370
23371                                    // If the type contains `number` or a number literal and the string isn't a valid number, exclude numbers
23372                                    if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) {
23373                                        allTypeFlags &= ~TypeFlags.NumberLike;
23374                                    }
23375
23376                                    // If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints
23377                                    if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) {
23378                                        allTypeFlags &= ~TypeFlags.BigIntLike;
23379                                    }
23380
23381                                    // for each type in the constraint, find the highest priority matching type
23382                                    const matchingType = reduceLeft(constraintTypes, (left, right) =>
23383                                        !(right.flags & allTypeFlags) ? left :
23384                                        left.flags & TypeFlags.String ? left : right.flags & TypeFlags.String ? source :
23385                                        left.flags & TypeFlags.TemplateLiteral ? left : right.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as TemplateLiteralType) ? source :
23386                                        left.flags & TypeFlags.StringMapping ? left : right.flags & TypeFlags.StringMapping && str === applyStringMapping(right.symbol, str) ? source :
23387                                        left.flags & TypeFlags.StringLiteral ? left : right.flags & TypeFlags.StringLiteral && (right as StringLiteralType).value === str ? right :
23388                                        left.flags & TypeFlags.Number ? left : right.flags & TypeFlags.Number ? getNumberLiteralType(+str) :
23389                                        left.flags & TypeFlags.Enum ? left : right.flags & TypeFlags.Enum ? getNumberLiteralType(+str) :
23390                                        left.flags & TypeFlags.NumberLiteral ? left : right.flags & TypeFlags.NumberLiteral && (right as NumberLiteralType).value === +str ? right :
23391                                        left.flags & TypeFlags.BigInt ? left : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) :
23392                                        left.flags & TypeFlags.BigIntLiteral ? left : right.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((right as BigIntLiteralType).value) === str ? right :
23393                                        left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : str === "false" ? falseType : booleanType :
23394                                        left.flags & TypeFlags.BooleanLiteral ? left : right.flags & TypeFlags.BooleanLiteral && (right as IntrinsicType).intrinsicName === str ? right :
23395                                        left.flags & TypeFlags.Undefined ? left : right.flags & TypeFlags.Undefined && (right as IntrinsicType).intrinsicName === str ? right :
23396                                        left.flags & TypeFlags.Null ? left : right.flags & TypeFlags.Null && (right as IntrinsicType).intrinsicName === str ? right :
23397                                        left,
23398                                        neverType as Type);
23399
23400                                    if (!(matchingType.flags & TypeFlags.Never)) {
23401                                        inferFromTypes(matchingType, target);
23402                                        continue;
23403                                    }
23404                                }
23405                            }
23406                        }
23407
23408                        inferFromTypes(source, target);
23409                    }
23410                }
23411            }
23412
23413            function inferFromObjectTypes(source: Type, target: Type) {
23414                if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (
23415                    (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target))) {
23416                    // If source and target are references to the same generic type, infer from type arguments
23417                    inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target));
23418                    return;
23419                }
23420                if (isGenericMappedType(source) && isGenericMappedType(target)) {
23421                    // The source and target types are generic types { [P in S]: X } and { [P in T]: Y }, so we infer
23422                    // from S to T and from X to Y.
23423                    inferFromTypes(getConstraintTypeFromMappedType(source), getConstraintTypeFromMappedType(target));
23424                    inferFromTypes(getTemplateTypeFromMappedType(source), getTemplateTypeFromMappedType(target));
23425                    const sourceNameType = getNameTypeFromMappedType(source);
23426                    const targetNameType = getNameTypeFromMappedType(target);
23427                    if (sourceNameType && targetNameType) inferFromTypes(sourceNameType, targetNameType);
23428                }
23429                if (getObjectFlags(target) & ObjectFlags.Mapped && !(target as MappedType).declaration.nameType) {
23430                    const constraintType = getConstraintTypeFromMappedType(target as MappedType);
23431                    if (inferToMappedType(source, target as MappedType, constraintType)) {
23432                        return;
23433                    }
23434                }
23435                // Infer from the members of source and target only if the two types are possibly related
23436                if (!typesDefinitelyUnrelated(source, target)) {
23437                    if (isArrayOrTupleType(source)) {
23438                        if (isTupleType(target)) {
23439                            const sourceArity = getTypeReferenceArity(source);
23440                            const targetArity = getTypeReferenceArity(target);
23441                            const elementTypes = getTypeArguments(target);
23442                            const elementFlags = target.target.elementFlags;
23443                            // When source and target are tuple types with the same structure (fixed, variadic, and rest are matched
23444                            // to the same kind in each position), simply infer between the element types.
23445                            if (isTupleType(source) && isTupleTypeStructureMatching(source, target)) {
23446                                for (let i = 0; i < targetArity; i++) {
23447                                    inferFromTypes(getTypeArguments(source)[i], elementTypes[i]);
23448                                }
23449                                return;
23450                            }
23451                            const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0;
23452                            const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0,
23453                                target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0);
23454                            // Infer between starting fixed elements.
23455                            for (let i = 0; i < startLength; i++) {
23456                                inferFromTypes(getTypeArguments(source)[i], elementTypes[i]);
23457                            }
23458                            if (!isTupleType(source) || sourceArity - startLength - endLength === 1 && source.target.elementFlags[startLength] & ElementFlags.Rest) {
23459                                // Single rest element remains in source, infer from that to every element in target
23460                                const restType = getTypeArguments(source)[startLength];
23461                                for (let i = startLength; i < targetArity - endLength; i++) {
23462                                    inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]);
23463                                }
23464                            }
23465                            else {
23466                                const middleLength = targetArity - startLength - endLength;
23467                                if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
23468                                    // Middle of target is [...T, ...U] and source is tuple type
23469                                    const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
23470                                    if (targetInfo && targetInfo.impliedArity !== undefined) {
23471                                        // Infer slices from source based on implied arity of T.
23472                                        inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
23473                                        inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]);
23474                                    }
23475                                }
23476                                else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) {
23477                                    // Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source.
23478                                    // If target ends in optional element(s), make a lower priority a speculative inference.
23479                                    const endsInOptional = target.target.elementFlags[targetArity - 1] & ElementFlags.Optional;
23480                                    const sourceSlice = isTupleType(source) ? sliceTupleType(source, startLength, endLength) : createArrayType(getTypeArguments(source)[0]);
23481                                    inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0);
23482                                }
23483                                else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) {
23484                                    // Middle of target is exactly one rest element. If middle of source is not empty, infer union of middle element types.
23485                                    const restType = isTupleType(source) ? getElementTypeOfSliceOfTupleType(source, startLength, endLength) : getTypeArguments(source)[0];
23486                                    if (restType) {
23487                                        inferFromTypes(restType, elementTypes[startLength]);
23488                                    }
23489                                }
23490                            }
23491                            // Infer between ending fixed elements
23492                            for (let i = 0; i < endLength; i++) {
23493                                inferFromTypes(getTypeArguments(source)[sourceArity - i - 1], elementTypes[targetArity - i - 1]);
23494                            }
23495                            return;
23496                        }
23497                        if (isArrayType(target)) {
23498                            inferFromIndexTypes(source, target);
23499                            return;
23500                        }
23501                    }
23502                    inferFromProperties(source, target);
23503                    inferFromSignatures(source, target, SignatureKind.Call);
23504                    inferFromSignatures(source, target, SignatureKind.Construct);
23505                    inferFromIndexTypes(source, target);
23506                }
23507            }
23508
23509            function inferFromProperties(source: Type, target: Type) {
23510                const properties = getPropertiesOfObjectType(target);
23511                for (const targetProp of properties) {
23512                    const sourceProp = getPropertyOfType(source, targetProp.escapedName);
23513                    if (sourceProp && !some(sourceProp.declarations, hasSkipDirectInferenceFlag)) {
23514                        inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
23515                    }
23516                }
23517            }
23518
23519            function inferFromSignatures(source: Type, target: Type, kind: SignatureKind) {
23520                const sourceSignatures = getSignaturesOfType(source, kind);
23521                const targetSignatures = getSignaturesOfType(target, kind);
23522                const sourceLen = sourceSignatures.length;
23523                const targetLen = targetSignatures.length;
23524                const len = sourceLen < targetLen ? sourceLen : targetLen;
23525                for (let i = 0; i < len; i++) {
23526                    inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]));
23527                }
23528            }
23529
23530            function inferFromSignature(source: Signature, target: Signature) {
23531                const saveBivariant = bivariant;
23532                const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
23533                // Once we descend into a bivariant signature we remain bivariant for all nested inferences
23534                bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor;
23535                applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes);
23536                bivariant = saveBivariant;
23537                applyToReturnTypes(source, target, inferFromTypes);
23538            }
23539
23540            function inferFromIndexTypes(source: Type, target: Type) {
23541                // Inferences across mapped type index signatures are pretty much the same a inferences to homomorphic variables
23542                const priority = (getObjectFlags(source) & getObjectFlags(target) & ObjectFlags.Mapped) ? InferencePriority.HomomorphicMappedType : 0;
23543                const indexInfos = getIndexInfosOfType(target);
23544                if (isObjectTypeWithInferableIndex(source)) {
23545                    for (const targetInfo of indexInfos) {
23546                        const propTypes: Type[] = [];
23547                        for (const prop of getPropertiesOfType(source)) {
23548                            if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), targetInfo.keyType)) {
23549                                const propType = getTypeOfSymbol(prop);
23550                                propTypes.push(prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType);
23551                            }
23552                        }
23553                        for (const info of getIndexInfosOfType(source)) {
23554                            if (isApplicableIndexType(info.keyType, targetInfo.keyType)) {
23555                                propTypes.push(info.type);
23556                            }
23557                        }
23558                        if (propTypes.length) {
23559                            inferWithPriority(getUnionType(propTypes), targetInfo.type, priority);
23560                        }
23561                    }
23562                }
23563                for (const targetInfo of indexInfos) {
23564                    const sourceInfo = getApplicableIndexInfo(source, targetInfo.keyType);
23565                    if (sourceInfo) {
23566                        inferWithPriority(sourceInfo.type, targetInfo.type, priority);
23567                    }
23568                }
23569            }
23570        }
23571
23572        function isTypeOrBaseIdenticalTo(s: Type, t: Type) {
23573            return exactOptionalPropertyTypes && t === missingType ? s === t :
23574                (isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral));
23575        }
23576
23577        function isTypeCloselyMatchedBy(s: Type, t: Type) {
23578            return !!(s.flags & TypeFlags.Object && t.flags & TypeFlags.Object && s.symbol && s.symbol === t.symbol ||
23579                s.aliasSymbol && s.aliasTypeArguments && s.aliasSymbol === t.aliasSymbol);
23580        }
23581
23582        function hasPrimitiveConstraint(type: TypeParameter): boolean {
23583            const constraint = getConstraintOfTypeParameter(type);
23584            return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping);
23585        }
23586
23587        function isObjectLiteralType(type: Type) {
23588            return !!(getObjectFlags(type) & ObjectFlags.ObjectLiteral);
23589        }
23590
23591        function isObjectOrArrayLiteralType(type: Type) {
23592            return !!(getObjectFlags(type) & (ObjectFlags.ObjectLiteral | ObjectFlags.ArrayLiteral));
23593        }
23594
23595        function unionObjectAndArrayLiteralCandidates(candidates: Type[]): Type[] {
23596            if (candidates.length > 1) {
23597                const objectLiterals = filter(candidates, isObjectOrArrayLiteralType);
23598                if (objectLiterals.length) {
23599                    const literalsType = getUnionType(objectLiterals, UnionReduction.Subtype);
23600                    return concatenate(filter(candidates, t => !isObjectOrArrayLiteralType(t)), [literalsType]);
23601                }
23602            }
23603            return candidates;
23604        }
23605
23606        function getContravariantInference(inference: InferenceInfo) {
23607            return inference.priority! & InferencePriority.PriorityImpliesCombination ? getIntersectionType(inference.contraCandidates!) : getCommonSubtype(inference.contraCandidates!);
23608        }
23609
23610        function getCovariantInference(inference: InferenceInfo, signature: Signature) {
23611            // Extract all object and array literal types and replace them with a single widened and normalized type.
23612            const candidates = unionObjectAndArrayLiteralCandidates(inference.candidates!);
23613            // We widen inferred literal types if
23614            // all inferences were made to top-level occurrences of the type parameter, and
23615            // the type parameter has no constraint or its constraint includes no primitive or literal types, and
23616            // the type parameter was fixed during inference or does not occur at top-level in the return type.
23617            const primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter);
23618            const widenLiteralTypes = !primitiveConstraint && inference.topLevel &&
23619                (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter));
23620            const baseCandidates = primitiveConstraint ? sameMap(candidates, getRegularTypeOfLiteralType) :
23621                widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) :
23622                candidates;
23623            // If all inferences were made from a position that implies a combined result, infer a union type.
23624            // Otherwise, infer a common supertype.
23625            const unwidenedType = inference.priority! & InferencePriority.PriorityImpliesCombination ?
23626                getUnionType(baseCandidates, UnionReduction.Subtype) :
23627                getCommonSupertype(baseCandidates);
23628            return getWidenedType(unwidenedType);
23629        }
23630
23631        function getInferredType(context: InferenceContext, index: number): Type {
23632            const inference = context.inferences[index];
23633            if (!inference.inferredType) {
23634                let inferredType: Type | undefined;
23635                const signature = context.signature;
23636                if (signature) {
23637                    const inferredCovariantType = inference.candidates ? getCovariantInference(inference, signature) : undefined;
23638                    if (inference.contraCandidates) {
23639                        // If we have both co- and contra-variant inferences, we prefer the contra-variant inference
23640                        // unless the co-variant inference is a subtype of some contra-variant inference and not 'never'.
23641                        inferredType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) &&
23642                            some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) ?
23643                            inferredCovariantType : getContravariantInference(inference);
23644                    }
23645                    else if (inferredCovariantType) {
23646                        inferredType = inferredCovariantType;
23647                    }
23648                    else if (context.flags & InferenceFlags.NoDefault) {
23649                        // We use silentNeverType as the wildcard that signals no inferences.
23650                        inferredType = silentNeverType;
23651                    }
23652                    else {
23653                        // Infer either the default or the empty object type when no inferences were
23654                        // made. It is important to remember that in this case, inference still
23655                        // succeeds, meaning there is no error for not having inference candidates. An
23656                        // inference error only occurs when there are *conflicting* candidates, i.e.
23657                        // candidates with no common supertype.
23658                        const defaultType = getDefaultFromTypeParameter(inference.typeParameter);
23659                        if (defaultType) {
23660                            // Instantiate the default type. Any forward reference to a type
23661                            // parameter should be instantiated to the empty object type.
23662                            inferredType = instantiateType(defaultType, mergeTypeMappers(createBackreferenceMapper(context, index), context.nonFixingMapper));
23663                        }
23664                    }
23665                }
23666                else {
23667                    inferredType = getTypeFromInference(inference);
23668                }
23669
23670                inference.inferredType = inferredType || getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault));
23671
23672                const constraint = getConstraintOfTypeParameter(inference.typeParameter);
23673                if (constraint) {
23674                    const instantiatedConstraint = instantiateType(constraint, context.nonFixingMapper);
23675                    if (!inferredType || !context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
23676                        inference.inferredType = inferredType = instantiatedConstraint;
23677                    }
23678                }
23679            }
23680
23681            return inference.inferredType;
23682        }
23683
23684        function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): Type {
23685            return isInJavaScriptFile ? anyType : unknownType;
23686        }
23687
23688        function getInferredTypes(context: InferenceContext): Type[] {
23689            const result: Type[] = [];
23690            for (let i = 0; i < context.inferences.length; i++) {
23691                result.push(getInferredType(context, i));
23692            }
23693            return result;
23694        }
23695
23696        // EXPRESSION TYPE CHECKING
23697
23698        function getCannotFindNameDiagnosticForName(node: Identifier): DiagnosticMessage {
23699            switch (node.escapedText) {
23700                case "document":
23701                case "console":
23702                    return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_include_dom;
23703                case "$":
23704                    return compilerOptions.types
23705                        ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery_and_then_add_jquery_to_the_types_field_in_your_tsconfig
23706                        : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery;
23707                case "describe":
23708                case "suite":
23709                case "it":
23710                case "test":
23711                    return compilerOptions.types
23712                        ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha_and_then_add_jest_or_mocha_to_the_types_field_in_your_tsconfig
23713                        : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha;
23714                case "process":
23715                case "require":
23716                case "Buffer":
23717                case "module":
23718                    return compilerOptions.types
23719                        ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode_and_then_add_node_to_the_types_field_in_your_tsconfig
23720                        : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode;
23721                case "Map":
23722                case "Set":
23723                case "Promise":
23724                case "Symbol":
23725                case "WeakMap":
23726                case "WeakSet":
23727                case "Iterator":
23728                case "AsyncIterator":
23729                case "SharedArrayBuffer":
23730                case "Atomics":
23731                case "AsyncIterable":
23732                case "AsyncIterableIterator":
23733                case "AsyncGenerator":
23734                case "AsyncGeneratorFunction":
23735                case "BigInt":
23736                case "Reflect":
23737                case "BigInt64Array":
23738                case "BigUint64Array":
23739                    return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_1_or_later;
23740                case "await":
23741                    if (isCallExpression(node.parent)) {
23742                        return Diagnostics.Cannot_find_name_0_Did_you_mean_to_write_this_in_an_async_function;
23743                    }
23744                    // falls through
23745                default:
23746                    if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
23747                        return Diagnostics.No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer;
23748                    }
23749                    else {
23750                        return Diagnostics.Cannot_find_name_0;
23751                    }
23752            }
23753        }
23754
23755        function getResolvedSymbol(node: Identifier): Symbol {
23756            const links = getNodeLinks(node);
23757            if (!links.resolvedSymbol) {
23758                links.resolvedSymbol = !nodeIsMissing(node) &&
23759                    resolveName(
23760                        node,
23761                        node.escapedText,
23762                        SymbolFlags.Value | SymbolFlags.ExportValue,
23763                        getCannotFindNameDiagnosticForName(node),
23764                        node,
23765                        !isWriteOnlyAccess(node),
23766                        /*excludeGlobals*/ false) || unknownSymbol;
23767            }
23768            return links.resolvedSymbol;
23769        }
23770
23771        function isInTypeQuery(node: Node): boolean {
23772            // TypeScript 1.0 spec (April 2014): 3.6.3
23773            // A type query consists of the keyword typeof followed by an expression.
23774            // The expression is restricted to a single identifier or a sequence of identifiers separated by periods
23775            return !!findAncestor(
23776                node,
23777                n => n.kind === SyntaxKind.TypeQuery ? true : n.kind === SyntaxKind.Identifier || n.kind === SyntaxKind.QualifiedName ? false : "quit");
23778        }
23779
23780        // Return the flow cache key for a "dotted name" (i.e. a sequence of identifiers
23781        // separated by dots). The key consists of the id of the symbol referenced by the
23782        // leftmost identifier followed by zero or more property names separated by dots.
23783        // The result is undefined if the reference isn't a dotted name.
23784        function getFlowCacheKey(node: Node, declaredType: Type, initialType: Type, flowContainer: Node | undefined): string | undefined {
23785            switch (node.kind) {
23786                case SyntaxKind.Identifier:
23787                    if (!isThisInTypeQuery(node)) {
23788                        const symbol = getResolvedSymbol(node as Identifier);
23789                        return symbol !== unknownSymbol ? `${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}|${getSymbolId(symbol)}` : undefined;
23790                    }
23791                    // falls through
23792                case SyntaxKind.ThisKeyword:
23793                    return `0|${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}`;
23794                case SyntaxKind.NonNullExpression:
23795                case SyntaxKind.ParenthesizedExpression:
23796                    return getFlowCacheKey((node as NonNullExpression | ParenthesizedExpression).expression, declaredType, initialType, flowContainer);
23797                case SyntaxKind.QualifiedName:
23798                    const left = getFlowCacheKey((node as QualifiedName).left, declaredType, initialType, flowContainer);
23799                    return left && left + "." + (node as QualifiedName).right.escapedText;
23800                case SyntaxKind.PropertyAccessExpression:
23801                case SyntaxKind.ElementAccessExpression:
23802                    const propName = getAccessedPropertyName(node as AccessExpression);
23803                    if (propName !== undefined) {
23804                        const key = getFlowCacheKey((node as AccessExpression).expression, declaredType, initialType, flowContainer);
23805                        return key && key + "." + propName;
23806                    }
23807                    break;
23808                case SyntaxKind.ObjectBindingPattern:
23809                case SyntaxKind.ArrayBindingPattern:
23810                case SyntaxKind.FunctionDeclaration:
23811                case SyntaxKind.FunctionExpression:
23812                case SyntaxKind.ArrowFunction:
23813                case SyntaxKind.MethodDeclaration:
23814                    // Handle pseudo-references originating in getNarrowedTypeOfSymbol.
23815                    return `${getNodeId(node)}#${getTypeId(declaredType)}`;
23816            }
23817            return undefined;
23818        }
23819
23820        function isMatchingReference(source: Node, target: Node): boolean {
23821            switch (target.kind) {
23822                case SyntaxKind.ParenthesizedExpression:
23823                case SyntaxKind.NonNullExpression:
23824                    return isMatchingReference(source, (target as NonNullExpression | ParenthesizedExpression).expression);
23825                case SyntaxKind.BinaryExpression:
23826                    return (isAssignmentExpression(target) && isMatchingReference(source, target.left)) ||
23827                        (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source, target.right));
23828            }
23829            switch (source.kind) {
23830                case SyntaxKind.MetaProperty:
23831                    return target.kind === SyntaxKind.MetaProperty
23832                        && (source as MetaProperty).keywordToken === (target as MetaProperty).keywordToken
23833                        && (source as MetaProperty).name.escapedText === (target as MetaProperty).name.escapedText;
23834                case SyntaxKind.Identifier:
23835                case SyntaxKind.PrivateIdentifier:
23836                    return isThisInTypeQuery(source) ?
23837                        target.kind === SyntaxKind.ThisKeyword :
23838                        target.kind === SyntaxKind.Identifier && getResolvedSymbol(source as Identifier) === getResolvedSymbol(target as Identifier) ||
23839                            (target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) &&
23840                            getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfNode(target);
23841                case SyntaxKind.ThisKeyword:
23842                    return target.kind === SyntaxKind.ThisKeyword;
23843                case SyntaxKind.SuperKeyword:
23844                    return target.kind === SyntaxKind.SuperKeyword;
23845                case SyntaxKind.NonNullExpression:
23846                case SyntaxKind.ParenthesizedExpression:
23847                    return isMatchingReference((source as NonNullExpression | ParenthesizedExpression).expression, target);
23848                case SyntaxKind.PropertyAccessExpression:
23849                case SyntaxKind.ElementAccessExpression:
23850                    const sourcePropertyName = getAccessedPropertyName(source as AccessExpression);
23851                    const targetPropertyName = isAccessExpression(target) ? getAccessedPropertyName(target) : undefined;
23852                    return sourcePropertyName !== undefined && targetPropertyName !== undefined && targetPropertyName === sourcePropertyName &&
23853                        isMatchingReference((source as AccessExpression).expression, (target as AccessExpression).expression);
23854                case SyntaxKind.QualifiedName:
23855                    return isAccessExpression(target) &&
23856                        (source as QualifiedName).right.escapedText === getAccessedPropertyName(target) &&
23857                        isMatchingReference((source as QualifiedName).left, target.expression);
23858                case SyntaxKind.BinaryExpression:
23859                    return (isBinaryExpression(source) && source.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source.right, target));
23860            }
23861            return false;
23862        }
23863
23864        function getAccessedPropertyName(access: AccessExpression | BindingElement | ParameterDeclaration): __String | undefined {
23865            if (isPropertyAccessExpression(access)) {
23866                return access.name.escapedText;
23867            }
23868            if (isElementAccessExpression(access)) {
23869                return tryGetElementAccessExpressionName(access);
23870            }
23871            if (isBindingElement(access)) {
23872                const name = getDestructuringPropertyName(access);
23873                return name ? escapeLeadingUnderscores(name) : undefined;
23874            }
23875            if (isParameter(access)) {
23876                return ("" + access.parent.parameters.indexOf(access)) as __String;
23877            }
23878            return undefined;
23879        }
23880
23881        function tryGetNameFromType(type: Type) {
23882            return type.flags & TypeFlags.UniqueESSymbol ? (type as UniqueESSymbolType).escapedName :
23883                type.flags & TypeFlags.StringOrNumberLiteral ? escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value) : undefined;
23884        }
23885
23886        function tryGetElementAccessExpressionName(node: ElementAccessExpression) {
23887            if (isStringOrNumericLiteralLike(node.argumentExpression)) {
23888                return escapeLeadingUnderscores(node.argumentExpression.text);
23889            }
23890            if (isEntityNameExpression(node.argumentExpression)) {
23891                const symbol = resolveEntityName(node.argumentExpression, SymbolFlags.Value, /*ignoreErrors*/ true);
23892                if (!symbol || !(isConstVariable(symbol) || (symbol.flags & SymbolFlags.EnumMember))) return undefined;
23893
23894                const declaration = symbol.valueDeclaration;
23895                if (declaration === undefined) return undefined;
23896
23897                const type = tryGetTypeFromEffectiveTypeNode(declaration);
23898                if (type) {
23899                    const name = tryGetNameFromType(type);
23900                    if (name !== undefined) {
23901                        return name;
23902                    }
23903                }
23904
23905                if (hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node.argumentExpression)) {
23906                    const initializer = getEffectiveInitializer(declaration);
23907                    if (initializer) {
23908                        return tryGetNameFromType(getTypeOfExpression(initializer));
23909                    }
23910                    if (isEnumMember(declaration)) {
23911                        return getTextOfPropertyName(declaration.name);
23912                    }
23913                }
23914            }
23915            return undefined;
23916        }
23917
23918        function containsMatchingReference(source: Node, target: Node) {
23919            while (isAccessExpression(source)) {
23920                source = source.expression;
23921                if (isMatchingReference(source, target)) {
23922                    return true;
23923                }
23924            }
23925            return false;
23926        }
23927
23928        function optionalChainContainsReference(source: Node, target: Node) {
23929            while (isOptionalChain(source)) {
23930                source = source.expression;
23931                if (isMatchingReference(source, target)) {
23932                    return true;
23933                }
23934            }
23935            return false;
23936        }
23937
23938        function isDiscriminantProperty(type: Type | undefined, name: __String) {
23939            if (type && type.flags & TypeFlags.Union) {
23940                const prop = getUnionOrIntersectionProperty(type as UnionType, name);
23941                if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) {
23942                    if ((prop as TransientSymbol).isDiscriminantProperty === undefined) {
23943                        (prop as TransientSymbol).isDiscriminantProperty =
23944                            ((prop as TransientSymbol).checkFlags & CheckFlags.Discriminant) === CheckFlags.Discriminant &&
23945                            !isGenericType(getTypeOfSymbol(prop));
23946                    }
23947                    return !!(prop as TransientSymbol).isDiscriminantProperty;
23948                }
23949            }
23950            return false;
23951        }
23952
23953        function findDiscriminantProperties(sourceProperties: Symbol[], target: Type): Symbol[] | undefined {
23954            let result: Symbol[] | undefined;
23955            for (const sourceProperty of sourceProperties) {
23956                if (isDiscriminantProperty(target, sourceProperty.escapedName)) {
23957                    if (result) {
23958                        result.push(sourceProperty);
23959                        continue;
23960                    }
23961                    result = [sourceProperty];
23962                }
23963            }
23964            return result;
23965        }
23966
23967        // Given a set of constituent types and a property name, create and return a map keyed by the literal
23968        // types of the property by that name in each constituent type. No map is returned if some key property
23969        // has a non-literal type or if less than 10 or less than 50% of the constituents have a unique key.
23970        // Entries with duplicate keys have unknownType as the value.
23971        function mapTypesByKeyProperty(types: Type[], name: __String) {
23972            const map = new Map<TypeId, Type>();
23973            let count = 0;
23974            for (const type of types) {
23975                if (type.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) {
23976                    const discriminant = getTypeOfPropertyOfType(type, name);
23977                    if (discriminant) {
23978                        if (!isLiteralType(discriminant)) {
23979                            return undefined;
23980                        }
23981                        let duplicate = false;
23982                        forEachType(discriminant, t => {
23983                            const id = getTypeId(getRegularTypeOfLiteralType(t));
23984                            const existing = map.get(id);
23985                            if (!existing) {
23986                                map.set(id, type);
23987                            }
23988                            else if (existing !== unknownType) {
23989                                map.set(id, unknownType);
23990                                duplicate = true;
23991                            }
23992                        });
23993                        if (!duplicate) count++;
23994                    }
23995                }
23996            }
23997            return count >= 10 && count * 2 >= types.length ? map : undefined;
23998        }
23999
24000        // Return the name of a discriminant property for which it was possible and feasible to construct a map of
24001        // constituent types keyed by the literal types of the property by that name in each constituent type.
24002        function getKeyPropertyName(unionType: UnionType): __String | undefined {
24003            const types = unionType.types;
24004            // We only construct maps for unions with many non-primitive constituents.
24005            if (types.length < 10 || getObjectFlags(unionType) & ObjectFlags.PrimitiveUnion ||
24006                countWhere(types, t => !!(t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive))) < 10) {
24007                return undefined;
24008            }
24009            if (unionType.keyPropertyName === undefined) {
24010                // The candidate key property name is the name of the first property with a unit type in one of the
24011                // constituent types.
24012                const keyPropertyName = forEach(types, t =>
24013                    t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ?
24014                        forEach(getPropertiesOfType(t), p => isUnitType(getTypeOfSymbol(p)) ? p.escapedName : undefined) :
24015                        undefined);
24016                const mapByKeyProperty = keyPropertyName && mapTypesByKeyProperty(types, keyPropertyName);
24017                unionType.keyPropertyName = mapByKeyProperty ? keyPropertyName : "" as __String;
24018                unionType.constituentMap = mapByKeyProperty;
24019            }
24020            return (unionType.keyPropertyName as string).length ? unionType.keyPropertyName : undefined;
24021        }
24022
24023        // Given a union type for which getKeyPropertyName returned a non-undefined result, return the constituent
24024        // that corresponds to the given key type for that property name.
24025        function getConstituentTypeForKeyType(unionType: UnionType, keyType: Type) {
24026            const result = unionType.constituentMap?.get(getTypeId(getRegularTypeOfLiteralType(keyType)));
24027            return result !== unknownType ? result : undefined;
24028        }
24029
24030        function getMatchingUnionConstituentForType(unionType: UnionType, type: Type) {
24031            const keyPropertyName = getKeyPropertyName(unionType);
24032            const propType = keyPropertyName && getTypeOfPropertyOfType(type, keyPropertyName);
24033            return propType && getConstituentTypeForKeyType(unionType, propType);
24034        }
24035
24036        function getMatchingUnionConstituentForObjectLiteral(unionType: UnionType, node: ObjectLiteralExpression) {
24037            const keyPropertyName = getKeyPropertyName(unionType);
24038            const propNode = keyPropertyName && find(node.properties, p => p.symbol && p.kind === SyntaxKind.PropertyAssignment &&
24039                p.symbol.escapedName === keyPropertyName && isPossiblyDiscriminantValue(p.initializer));
24040            const propType = propNode && getContextFreeTypeOfExpression((propNode as PropertyAssignment).initializer);
24041            return propType && getConstituentTypeForKeyType(unionType, propType);
24042        }
24043
24044        function isOrContainsMatchingReference(source: Node, target: Node) {
24045            return isMatchingReference(source, target) || containsMatchingReference(source, target);
24046        }
24047
24048        function hasMatchingArgument(expression: CallExpression | NewExpression, reference: Node) {
24049            if (expression.arguments) {
24050                for (const argument of expression.arguments) {
24051                    if (isOrContainsMatchingReference(reference, argument)) {
24052                        return true;
24053                    }
24054                }
24055            }
24056            if (expression.expression.kind === SyntaxKind.PropertyAccessExpression &&
24057                isOrContainsMatchingReference(reference, (expression.expression as PropertyAccessExpression).expression)) {
24058                return true;
24059            }
24060            return false;
24061        }
24062
24063        function getFlowNodeId(flow: FlowNode): number {
24064            if (!flow.id || flow.id < 0) {
24065                flow.id = nextFlowId;
24066                nextFlowId++;
24067            }
24068            return flow.id;
24069        }
24070
24071        function typeMaybeAssignableTo(source: Type, target: Type) {
24072            if (!(source.flags & TypeFlags.Union)) {
24073                return isTypeAssignableTo(source, target);
24074            }
24075            for (const t of (source as UnionType).types) {
24076                if (isTypeAssignableTo(t, target)) {
24077                    return true;
24078                }
24079            }
24080            return false;
24081        }
24082
24083        // Remove those constituent types of declaredType to which no constituent type of assignedType is assignable.
24084        // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean,
24085        // we remove type string.
24086        function getAssignmentReducedType(declaredType: UnionType, assignedType: Type) {
24087            if (declaredType === assignedType) {
24088                return declaredType;
24089            }
24090            if (assignedType.flags & TypeFlags.Never) {
24091                return assignedType;
24092            }
24093            const key = `A${getTypeId(declaredType)},${getTypeId(assignedType)}`;
24094            return getCachedType(key) ?? setCachedType(key, getAssignmentReducedTypeWorker(declaredType, assignedType));
24095        }
24096
24097        function getAssignmentReducedTypeWorker(declaredType: UnionType, assignedType: Type) {
24098            const filteredType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
24099            // Ensure that we narrow to fresh types if the assignment is a fresh boolean literal type.
24100            const reducedType = assignedType.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType) ? mapType(filteredType, getFreshTypeOfLiteralType) : filteredType;
24101            // Our crude heuristic produces an invalid result in some cases: see GH#26130.
24102            // For now, when that happens, we give up and don't narrow at all.  (This also
24103            // means we'll never narrow for erroneous assignments where the assigned type
24104            // is not assignable to the declared type.)
24105            return isTypeAssignableTo(assignedType, reducedType) ? reducedType : declaredType;
24106        }
24107
24108        function isFunctionObjectType(type: ObjectType): boolean {
24109            // We do a quick check for a "bind" property before performing the more expensive subtype
24110            // check. This gives us a quicker out in the common case where an object type is not a function.
24111            const resolved = resolveStructuredTypeMembers(type);
24112            return !!(resolved.callSignatures.length || resolved.constructSignatures.length ||
24113                resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType));
24114        }
24115
24116        function getTypeFacts(type: Type): TypeFacts {
24117            if (type.flags & (TypeFlags.Intersection | TypeFlags.Instantiable)) {
24118                type = getBaseConstraintOfType(type) || unknownType;
24119            }
24120            const flags = type.flags;
24121            if (flags & (TypeFlags.String | TypeFlags.StringMapping)) {
24122                return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts;
24123            }
24124            if (flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral)) {
24125                const isEmpty = flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === "";
24126                return strictNullChecks ?
24127                    isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts :
24128                    isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts;
24129            }
24130            if (flags & (TypeFlags.Number | TypeFlags.Enum)) {
24131                return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts;
24132            }
24133            if (flags & TypeFlags.NumberLiteral) {
24134                const isZero = (type as NumberLiteralType).value === 0;
24135                return strictNullChecks ?
24136                    isZero ? TypeFacts.ZeroNumberStrictFacts : TypeFacts.NonZeroNumberStrictFacts :
24137                    isZero ? TypeFacts.ZeroNumberFacts : TypeFacts.NonZeroNumberFacts;
24138            }
24139            if (flags & TypeFlags.BigInt) {
24140                return strictNullChecks ? TypeFacts.BigIntStrictFacts : TypeFacts.BigIntFacts;
24141            }
24142            if (flags & TypeFlags.BigIntLiteral) {
24143                const isZero = isZeroBigInt(type as BigIntLiteralType);
24144                return strictNullChecks ?
24145                    isZero ? TypeFacts.ZeroBigIntStrictFacts : TypeFacts.NonZeroBigIntStrictFacts :
24146                    isZero ? TypeFacts.ZeroBigIntFacts : TypeFacts.NonZeroBigIntFacts;
24147            }
24148            if (flags & TypeFlags.Boolean) {
24149                return strictNullChecks ? TypeFacts.BooleanStrictFacts : TypeFacts.BooleanFacts;
24150            }
24151            if (flags & TypeFlags.BooleanLike) {
24152                return strictNullChecks ?
24153                    (type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts :
24154                    (type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
24155            }
24156            if (flags & TypeFlags.Object) {
24157                return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) ?
24158                    strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts :
24159                    isFunctionObjectType(type as ObjectType) ?
24160                        strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts :
24161                        strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
24162            }
24163            if (flags & TypeFlags.Void) {
24164                return TypeFacts.VoidFacts;
24165            }
24166            if (flags & TypeFlags.Undefined) {
24167                return TypeFacts.UndefinedFacts;
24168            }
24169            if (flags & TypeFlags.Null) {
24170                return TypeFacts.NullFacts;
24171            }
24172            if (flags & TypeFlags.ESSymbolLike) {
24173                return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts;
24174            }
24175            if (flags & TypeFlags.NonPrimitive) {
24176                return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
24177            }
24178            if (flags & TypeFlags.Never) {
24179                return TypeFacts.None;
24180            }
24181            if (flags & TypeFlags.Union) {
24182                return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t), TypeFacts.None);
24183            }
24184            if (flags & TypeFlags.Intersection) {
24185                return getIntersectionTypeFacts(type as IntersectionType);
24186            }
24187            return TypeFacts.UnknownFacts;
24188        }
24189
24190        function getIntersectionTypeFacts(type: IntersectionType): TypeFacts {
24191            // When an intersection contains a primitive type we ignore object type constituents as they are
24192            // presumably type tags. For example, in string & { __kind__: "name" } we ignore the object type.
24193            const ignoreObjects = maybeTypeOfKind(type, TypeFlags.Primitive);
24194            // When computing the type facts of an intersection type, certain type facts are computed as `and`
24195            // and others are computed as `or`.
24196            let oredFacts = TypeFacts.None;
24197            let andedFacts = TypeFacts.All;
24198            for (const t of type.types) {
24199                if (!(ignoreObjects && t.flags & TypeFlags.Object)) {
24200                    const f = getTypeFacts(t);
24201                    oredFacts |= f;
24202                    andedFacts &= f;
24203                }
24204            }
24205            return oredFacts & TypeFacts.OrFactsMask | andedFacts & TypeFacts.AndFactsMask;
24206        }
24207
24208        function getTypeWithFacts(type: Type, include: TypeFacts) {
24209            return filterType(type, t => (getTypeFacts(t) & include) !== 0);
24210        }
24211
24212        // This function is similar to getTypeWithFacts, except that in strictNullChecks mode it replaces type
24213        // unknown with the union {} | null | undefined (and reduces that accordingly), and it intersects remaining
24214        // instantiable types with {}, {} | null, or {} | undefined in order to remove null and/or undefined.
24215        function getAdjustedTypeWithFacts(type: Type, facts: TypeFacts) {
24216            const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts));
24217            if (strictNullChecks) {
24218                switch (facts) {
24219                    case TypeFacts.NEUndefined:
24220                        return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]): t);
24221                    case TypeFacts.NENull:
24222                        return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]): t);
24223                    case TypeFacts.NEUndefinedOrNull:
24224                    case TypeFacts.Truthy:
24225                        return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t): t);
24226                }
24227            }
24228            return reduced;
24229        }
24230
24231        function recombineUnknownType(type: Type) {
24232            return type === unknownUnionType ? unknownType : type;
24233        }
24234
24235        function getTypeWithDefault(type: Type, defaultExpression: Expression) {
24236            return defaultExpression ?
24237                getUnionType([getNonUndefinedType(type), getTypeOfExpression(defaultExpression)]) :
24238                type;
24239        }
24240
24241        function getTypeOfDestructuredProperty(type: Type, name: PropertyName) {
24242            const nameType = getLiteralTypeFromPropertyName(name);
24243            if (!isTypeUsableAsPropertyName(nameType)) return errorType;
24244            const text = getPropertyNameFromType(nameType);
24245            return getTypeOfPropertyOfType(type, text) || includeUndefinedInIndexSignature(getApplicableIndexInfoForName(type, text)?.type) || errorType;
24246        }
24247
24248        function getTypeOfDestructuredArrayElement(type: Type, index: number) {
24249            return everyType(type, isTupleLikeType) && getTupleElementType(type, index) ||
24250                includeUndefinedInIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) ||
24251                errorType;
24252        }
24253
24254        function includeUndefinedInIndexSignature(type: Type | undefined): Type | undefined {
24255            if (!type) return type;
24256            return compilerOptions.noUncheckedIndexedAccess ?
24257                getUnionType([type, undefinedType]) :
24258                type;
24259        }
24260
24261        function getTypeOfDestructuredSpreadExpression(type: Type) {
24262            return createArrayType(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined) || errorType);
24263        }
24264
24265        function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type {
24266            const isDestructuringDefaultAssignment =
24267                node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) ||
24268                node.parent.kind === SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent);
24269            return isDestructuringDefaultAssignment ?
24270                getTypeWithDefault(getAssignedType(node), node.right) :
24271                getTypeOfExpression(node.right);
24272        }
24273
24274        function isDestructuringAssignmentTarget(parent: Node) {
24275            return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent ||
24276                parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent;
24277        }
24278
24279        function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type {
24280            return getTypeOfDestructuredArrayElement(getAssignedType(node), node.elements.indexOf(element));
24281        }
24282
24283        function getAssignedTypeOfSpreadExpression(node: SpreadElement): Type {
24284            return getTypeOfDestructuredSpreadExpression(getAssignedType(node.parent as ArrayLiteralExpression));
24285        }
24286
24287        function getAssignedTypeOfPropertyAssignment(node: PropertyAssignment | ShorthandPropertyAssignment): Type {
24288            return getTypeOfDestructuredProperty(getAssignedType(node.parent), node.name);
24289        }
24290
24291        function getAssignedTypeOfShorthandPropertyAssignment(node: ShorthandPropertyAssignment): Type {
24292            return getTypeWithDefault(getAssignedTypeOfPropertyAssignment(node), node.objectAssignmentInitializer!);
24293        }
24294
24295        function getAssignedType(node: Expression): Type {
24296            const { parent } = node;
24297            switch (parent.kind) {
24298                case SyntaxKind.ForInStatement:
24299                    return stringType;
24300                case SyntaxKind.ForOfStatement:
24301                    return checkRightHandSideOfForOf(parent as ForOfStatement) || errorType;
24302                case SyntaxKind.BinaryExpression:
24303                    return getAssignedTypeOfBinaryExpression(parent as BinaryExpression);
24304                case SyntaxKind.DeleteExpression:
24305                    return undefinedType;
24306                case SyntaxKind.ArrayLiteralExpression:
24307                    return getAssignedTypeOfArrayLiteralElement(parent as ArrayLiteralExpression, node);
24308                case SyntaxKind.SpreadElement:
24309                    return getAssignedTypeOfSpreadExpression(parent as SpreadElement);
24310                case SyntaxKind.PropertyAssignment:
24311                    return getAssignedTypeOfPropertyAssignment(parent as PropertyAssignment);
24312                case SyntaxKind.ShorthandPropertyAssignment:
24313                    return getAssignedTypeOfShorthandPropertyAssignment(parent as ShorthandPropertyAssignment);
24314            }
24315            return errorType;
24316        }
24317
24318        function getInitialTypeOfBindingElement(node: BindingElement): Type {
24319            const pattern = node.parent;
24320            const parentType = getInitialType(pattern.parent as VariableDeclaration | BindingElement);
24321            const type = pattern.kind === SyntaxKind.ObjectBindingPattern ?
24322                getTypeOfDestructuredProperty(parentType, node.propertyName || node.name as Identifier) :
24323                !node.dotDotDotToken ?
24324                    getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) :
24325                    getTypeOfDestructuredSpreadExpression(parentType);
24326            return getTypeWithDefault(type, node.initializer!);
24327        }
24328
24329        function getTypeOfInitializer(node: Expression) {
24330            // Return the cached type if one is available. If the type of the variable was inferred
24331            // from its initializer, we'll already have cached the type. Otherwise we compute it now
24332            // without caching such that transient types are reflected.
24333            const links = getNodeLinks(node);
24334            return links.resolvedType || getTypeOfExpression(node);
24335        }
24336
24337        function getInitialTypeOfVariableDeclaration(node: VariableDeclaration) {
24338            if (node.initializer) {
24339                return getTypeOfInitializer(node.initializer);
24340            }
24341            if (node.parent.parent.kind === SyntaxKind.ForInStatement) {
24342                return stringType;
24343            }
24344            if (node.parent.parent.kind === SyntaxKind.ForOfStatement) {
24345                return checkRightHandSideOfForOf(node.parent.parent) || errorType;
24346            }
24347            return errorType;
24348        }
24349
24350        function getInitialType(node: VariableDeclaration | BindingElement) {
24351            return node.kind === SyntaxKind.VariableDeclaration ?
24352                getInitialTypeOfVariableDeclaration(node) :
24353                getInitialTypeOfBindingElement(node);
24354        }
24355
24356        function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) {
24357            return node.kind === SyntaxKind.VariableDeclaration && (node as VariableDeclaration).initializer &&
24358                isEmptyArrayLiteral((node as VariableDeclaration).initializer!) ||
24359                node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression &&
24360                isEmptyArrayLiteral((node.parent as BinaryExpression).right);
24361        }
24362
24363        function getReferenceCandidate(node: Expression): Expression {
24364            switch (node.kind) {
24365                case SyntaxKind.ParenthesizedExpression:
24366                    return getReferenceCandidate((node as ParenthesizedExpression).expression);
24367                case SyntaxKind.BinaryExpression:
24368                    switch ((node as BinaryExpression).operatorToken.kind) {
24369                        case SyntaxKind.EqualsToken:
24370                        case SyntaxKind.BarBarEqualsToken:
24371                        case SyntaxKind.AmpersandAmpersandEqualsToken:
24372                        case SyntaxKind.QuestionQuestionEqualsToken:
24373                            return getReferenceCandidate((node as BinaryExpression).left);
24374                        case SyntaxKind.CommaToken:
24375                            return getReferenceCandidate((node as BinaryExpression).right);
24376                    }
24377            }
24378            return node;
24379        }
24380
24381        function getReferenceRoot(node: Node): Node {
24382            const { parent } = node;
24383            return parent.kind === SyntaxKind.ParenthesizedExpression ||
24384                parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken && (parent as BinaryExpression).left === node ||
24385                parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken && (parent as BinaryExpression).right === node ?
24386                getReferenceRoot(parent) : node;
24387        }
24388
24389        function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
24390            if (clause.kind === SyntaxKind.CaseClause) {
24391                return getRegularTypeOfLiteralType(getTypeOfExpression(clause.expression));
24392            }
24393            return neverType;
24394        }
24395
24396        function getSwitchClauseTypes(switchStatement: SwitchStatement): Type[] {
24397            const links = getNodeLinks(switchStatement);
24398            if (!links.switchTypes) {
24399                links.switchTypes = [];
24400                for (const clause of switchStatement.caseBlock.clauses) {
24401                    links.switchTypes.push(getTypeOfSwitchClause(clause));
24402                }
24403            }
24404            return links.switchTypes;
24405        }
24406
24407        // Get the type names from all cases in a switch on `typeof`. The default clause and/or duplicate type names are
24408        // represented as undefined. Return undefined if one or more case clause expressions are not string literals.
24409        function getSwitchClauseTypeOfWitnesses(switchStatement: SwitchStatement): (string | undefined)[] | undefined {
24410            if (some(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.CaseClause && !isStringLiteralLike(clause.expression))) {
24411                return undefined;
24412            }
24413            const witnesses: (string | undefined)[] = [];
24414            for (const clause of switchStatement.caseBlock.clauses) {
24415                const text = clause.kind === SyntaxKind.CaseClause ? (clause.expression as StringLiteralLike).text : undefined;
24416                witnesses.push(text && !contains(witnesses, text) ? text : undefined);
24417            }
24418            return witnesses;
24419        }
24420
24421        function eachTypeContainedIn(source: Type, types: Type[]) {
24422            return source.flags & TypeFlags.Union ? !forEach((source as UnionType).types, t => !contains(types, t)) : contains(types, source);
24423        }
24424
24425        function isTypeSubsetOf(source: Type, target: Type) {
24426            return source === target || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType);
24427        }
24428
24429        function isTypeSubsetOfUnion(source: Type, target: UnionType) {
24430            if (source.flags & TypeFlags.Union) {
24431                for (const t of (source as UnionType).types) {
24432                    if (!containsType(target.types, t)) {
24433                        return false;
24434                    }
24435                }
24436                return true;
24437            }
24438            if (source.flags & TypeFlags.EnumLiteral && getBaseTypeOfEnumLiteralType(source as LiteralType) === target) {
24439                return true;
24440            }
24441            return containsType(target.types, source);
24442        }
24443
24444        function forEachType<T>(type: Type, f: (t: Type) => T | undefined): T | undefined {
24445            return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type);
24446        }
24447
24448        function someType(type: Type, f: (t: Type) => boolean): boolean {
24449            return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type);
24450        }
24451
24452        function everyType(type: Type, f: (t: Type) => boolean): boolean {
24453            return type.flags & TypeFlags.Union ? every((type as UnionType).types, f) : f(type);
24454        }
24455
24456        function everyContainedType(type: Type, f: (t: Type) => boolean): boolean {
24457            return type.flags & TypeFlags.UnionOrIntersection ? every((type as UnionOrIntersectionType).types, f) : f(type);
24458        }
24459
24460        function filterType(type: Type, f: (t: Type) => boolean): Type {
24461            if (type.flags & TypeFlags.Union) {
24462                const types = (type as UnionType).types;
24463                const filtered = filter(types, f);
24464                if (filtered === types) {
24465                    return type;
24466                }
24467                const origin = (type as UnionType).origin;
24468                let newOrigin: Type | undefined;
24469                if (origin && origin.flags & TypeFlags.Union) {
24470                    // If the origin type is a (denormalized) union type, filter its non-union constituents. If that ends
24471                    // up removing a smaller number of types than in the normalized constituent set (meaning some of the
24472                    // filtered types are within nested unions in the origin), then we can't construct a new origin type.
24473                    // Otherwise, if we have exactly one type left in the origin set, return that as the filtered type.
24474                    // Otherwise, construct a new filtered origin type.
24475                    const originTypes = (origin as UnionType).types;
24476                    const originFiltered = filter(originTypes, t => !!(t.flags & TypeFlags.Union) || f(t));
24477                    if (originTypes.length - originFiltered.length === types.length - filtered.length) {
24478                        if (originFiltered.length === 1) {
24479                            return originFiltered[0];
24480                        }
24481                        newOrigin = createOriginUnionOrIntersectionType(TypeFlags.Union, originFiltered);
24482                    }
24483                }
24484                return getUnionTypeFromSortedList(filtered, (type as UnionType).objectFlags, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, newOrigin);
24485            }
24486            return type.flags & TypeFlags.Never || f(type) ? type : neverType;
24487        }
24488
24489        function removeType(type: Type, targetType: Type) {
24490            return filterType(type, t => t !== targetType);
24491        }
24492
24493        function countTypes(type: Type) {
24494            return type.flags & TypeFlags.Union ? (type as UnionType).types.length : 1;
24495        }
24496
24497        // Apply a mapping function to a type and return the resulting type. If the source type
24498        // is a union type, the mapping function is applied to each constituent type and a union
24499        // of the resulting types is returned.
24500        function mapType(type: Type, mapper: (t: Type) => Type, noReductions?: boolean): Type;
24501        function mapType(type: Type, mapper: (t: Type) => Type | undefined, noReductions?: boolean): Type | undefined;
24502        function mapType(type: Type, mapper: (t: Type) => Type | undefined, noReductions?: boolean): Type | undefined {
24503            if (type.flags & TypeFlags.Never) {
24504                return type;
24505            }
24506            if (!(type.flags & TypeFlags.Union)) {
24507                return mapper(type);
24508            }
24509            const origin = (type as UnionType).origin;
24510            const types = origin && origin.flags & TypeFlags.Union ? (origin as UnionType).types : (type as UnionType).types;
24511            let mappedTypes: Type[] | undefined;
24512            let changed = false;
24513            for (const t of types) {
24514                const mapped = t.flags & TypeFlags.Union ? mapType(t, mapper, noReductions) : mapper(t);
24515                changed ||= t !== mapped;
24516                if (mapped) {
24517                    if (!mappedTypes) {
24518                        mappedTypes = [mapped];
24519                    }
24520                    else {
24521                        mappedTypes.push(mapped);
24522                    }
24523                }
24524            }
24525            return changed ? mappedTypes && getUnionType(mappedTypes, noReductions ? UnionReduction.None : UnionReduction.Literal) : type;
24526        }
24527
24528        function mapTypeWithAlias(type: Type, mapper: (t: Type) => Type, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) {
24529            return type.flags & TypeFlags.Union && aliasSymbol ?
24530                getUnionType(map((type as UnionType).types, mapper), UnionReduction.Literal, aliasSymbol, aliasTypeArguments) :
24531                mapType(type, mapper);
24532        }
24533
24534        function extractTypesOfKind(type: Type, kind: TypeFlags) {
24535            return filterType(type, t => (t.flags & kind) !== 0);
24536        }
24537
24538        // Return a new type in which occurrences of the string, number and bigint primitives and placeholder template
24539        // literal types in typeWithPrimitives have been replaced with occurrences of compatible and more specific types
24540        // from typeWithLiterals. This is essentially a limited form of intersection between the two types. We avoid a
24541        // true intersection because it is more costly and, when applied to union types, generates a large number of
24542        // types we don't actually care about.
24543        function replacePrimitivesWithLiterals(typeWithPrimitives: Type, typeWithLiterals: Type) {
24544            if (maybeTypeOfKind(typeWithPrimitives, TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.Number | TypeFlags.BigInt) &&
24545                maybeTypeOfKind(typeWithLiterals, TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.NumberLiteral | TypeFlags.BigIntLiteral)) {
24546                return mapType(typeWithPrimitives, t =>
24547                    t.flags & TypeFlags.String ? extractTypesOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) :
24548                    isPatternLiteralType(t) && !maybeTypeOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? extractTypesOfKind(typeWithLiterals, TypeFlags.StringLiteral) :
24549                    t.flags & TypeFlags.Number ? extractTypesOfKind(typeWithLiterals, TypeFlags.Number | TypeFlags.NumberLiteral) :
24550                    t.flags & TypeFlags.BigInt ? extractTypesOfKind(typeWithLiterals, TypeFlags.BigInt | TypeFlags.BigIntLiteral) : t);
24551            }
24552            return typeWithPrimitives;
24553        }
24554
24555        function isIncomplete(flowType: FlowType) {
24556            return flowType.flags === 0;
24557        }
24558
24559        function getTypeFromFlowType(flowType: FlowType) {
24560            return flowType.flags === 0 ? (flowType as IncompleteType).type : flowType as Type;
24561        }
24562
24563        function createFlowType(type: Type, incomplete: boolean): FlowType {
24564            return incomplete ? { flags: 0, type: type.flags & TypeFlags.Never ? silentNeverType : type } : type;
24565        }
24566
24567        // An evolving array type tracks the element types that have so far been seen in an
24568        // 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving
24569        // array types are ultimately converted into manifest array types (using getFinalArrayType)
24570        // and never escape the getFlowTypeOfReference function.
24571        function createEvolvingArrayType(elementType: Type): EvolvingArrayType {
24572            const result = createObjectType(ObjectFlags.EvolvingArray) as EvolvingArrayType;
24573            result.elementType = elementType;
24574            return result;
24575        }
24576
24577        function getEvolvingArrayType(elementType: Type): EvolvingArrayType {
24578            return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType));
24579        }
24580
24581        // When adding evolving array element types we do not perform subtype reduction. Instead,
24582        // we defer subtype reduction until the evolving array type is finalized into a manifest
24583        // array type.
24584        function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType {
24585            const elementType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node)));
24586            return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType]));
24587        }
24588
24589        function createFinalArrayType(elementType: Type) {
24590            return elementType.flags & TypeFlags.Never ?
24591                autoArrayType :
24592                createArrayType(elementType.flags & TypeFlags.Union ?
24593                    getUnionType((elementType as UnionType).types, UnionReduction.Subtype) :
24594                    elementType);
24595        }
24596
24597        // We perform subtype reduction upon obtaining the final array type from an evolving array type.
24598        function getFinalArrayType(evolvingArrayType: EvolvingArrayType): Type {
24599            return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType));
24600        }
24601
24602        function finalizeEvolvingArrayType(type: Type): Type {
24603            return getObjectFlags(type) & ObjectFlags.EvolvingArray ? getFinalArrayType(type as EvolvingArrayType) : type;
24604        }
24605
24606        function getElementTypeOfEvolvingArrayType(type: Type) {
24607            return getObjectFlags(type) & ObjectFlags.EvolvingArray ? (type as EvolvingArrayType).elementType : neverType;
24608        }
24609
24610        function isEvolvingArrayTypeList(types: Type[]) {
24611            let hasEvolvingArrayType = false;
24612            for (const t of types) {
24613                if (!(t.flags & TypeFlags.Never)) {
24614                    if (!(getObjectFlags(t) & ObjectFlags.EvolvingArray)) {
24615                        return false;
24616                    }
24617                    hasEvolvingArrayType = true;
24618                }
24619            }
24620            return hasEvolvingArrayType;
24621        }
24622
24623        // Return true if the given node is 'x' in an 'x.length', x.push(value)', 'x.unshift(value)' or
24624        // 'x[n] = value' operation, where 'n' is an expression of type any, undefined, or a number-like type.
24625        function isEvolvingArrayOperationTarget(node: Node) {
24626            const root = getReferenceRoot(node);
24627            const parent = root.parent;
24628            const isLengthPushOrUnshift = isPropertyAccessExpression(parent) && (
24629                parent.name.escapedText === "length" ||
24630                parent.parent.kind === SyntaxKind.CallExpression
24631                && isIdentifier(parent.name)
24632                && isPushOrUnshiftIdentifier(parent.name));
24633            const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression &&
24634                (parent as ElementAccessExpression).expression === root &&
24635                parent.parent.kind === SyntaxKind.BinaryExpression &&
24636                (parent.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
24637                (parent.parent as BinaryExpression).left === parent &&
24638                !isAssignmentTarget(parent.parent) &&
24639                isTypeAssignableToKind(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression), TypeFlags.NumberLike);
24640            return isLengthPushOrUnshift || isElementAssignment;
24641        }
24642
24643        function isDeclarationWithExplicitTypeAnnotation(node: Declaration) {
24644            return (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isParameter(node)) &&
24645                !!(getEffectiveTypeAnnotationNode(node) ||
24646                    isInJSFile(node) && hasInitializer(node) && node.initializer && isFunctionExpressionOrArrowFunction(node.initializer) && getEffectiveReturnTypeNode(node.initializer));
24647        }
24648
24649        function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) {
24650            symbol = resolveSymbol(symbol);
24651            if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule)) {
24652                return getTypeOfSymbol(symbol);
24653            }
24654            if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
24655                if (getCheckFlags(symbol) & CheckFlags.Mapped) {
24656                    const origin = (symbol as MappedSymbol).syntheticOrigin;
24657                    if (origin && getExplicitTypeOfSymbol(origin)) {
24658                        return getTypeOfSymbol(symbol);
24659                    }
24660                }
24661                const declaration = symbol.valueDeclaration;
24662                if (declaration) {
24663                    if (isDeclarationWithExplicitTypeAnnotation(declaration)) {
24664                        return getTypeOfSymbol(symbol);
24665                    }
24666                    if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
24667                        const statement = declaration.parent.parent;
24668                        const expressionType = getTypeOfDottedName(statement.expression, /*diagnostic*/ undefined);
24669                        if (expressionType) {
24670                            const use = statement.awaitModifier ? IterationUse.ForAwaitOf : IterationUse.ForOf;
24671                            return checkIteratedTypeOrElementType(use, expressionType, undefinedType, /*errorNode*/ undefined);
24672                        }
24673                    }
24674                    if (diagnostic) {
24675                        addRelatedInfo(diagnostic, createDiagnosticForNode(declaration, Diagnostics._0_needs_an_explicit_type_annotation, symbolToString(symbol)));
24676                    }
24677                }
24678            }
24679        }
24680
24681        // We require the dotted function name in an assertion expression to be comprised of identifiers
24682        // that reference function, method, class or value module symbols; or variable, property or
24683        // parameter symbols with declarations that have explicit type annotations. Such references are
24684        // resolvable with no possibility of triggering circularities in control flow analysis.
24685        function getTypeOfDottedName(node: Expression, diagnostic: Diagnostic | undefined): Type | undefined {
24686            if (!(node.flags & NodeFlags.InWithStatement)) {
24687                switch (node.kind) {
24688                    case SyntaxKind.Identifier:
24689                        const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(node as Identifier));
24690                        return getExplicitTypeOfSymbol(symbol, diagnostic);
24691                    case SyntaxKind.ThisKeyword:
24692                        return getExplicitThisType(node);
24693                    case SyntaxKind.SuperKeyword:
24694                        return checkSuperExpression(node);
24695                    case SyntaxKind.PropertyAccessExpression: {
24696                        const type = getTypeOfDottedName((node as PropertyAccessExpression).expression, diagnostic);
24697                        if (type) {
24698                            const name = (node as PropertyAccessExpression).name;
24699                            let prop: Symbol | undefined;
24700                            if (isPrivateIdentifier(name)) {
24701                                if (!type.symbol) {
24702                                    return undefined;
24703                                }
24704                                prop = getPropertyOfType(type, getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText));
24705                            }
24706                            else {
24707                                prop = getPropertyOfType(type, name.escapedText);
24708                            }
24709                            return prop && getExplicitTypeOfSymbol(prop, diagnostic);
24710                        }
24711                        return undefined;
24712                    }
24713                    case SyntaxKind.ParenthesizedExpression:
24714                        return getTypeOfDottedName((node as ParenthesizedExpression).expression, diagnostic);
24715                }
24716            }
24717        }
24718
24719        function getEffectsSignature(node: CallExpression) {
24720            const links = getNodeLinks(node);
24721            let signature = links.effectsSignature;
24722            if (signature === undefined) {
24723                // A call expression parented by an expression statement is a potential assertion. Other call
24724                // expressions are potential type predicate function calls. In order to avoid triggering
24725                // circularities in control flow analysis, we use getTypeOfDottedName when resolving the call
24726                // target expression of an assertion.
24727                let funcType: Type | undefined;
24728                if (node.parent.kind === SyntaxKind.ExpressionStatement) {
24729                    funcType = getTypeOfDottedName(node.expression, /*diagnostic*/ undefined);
24730                }
24731                else if (node.expression.kind !== SyntaxKind.SuperKeyword) {
24732                    if (isOptionalChain(node)) {
24733                        funcType = checkNonNullType(
24734                            getOptionalExpressionType(checkExpression(node.expression), node.expression),
24735                            node.expression
24736                        );
24737                    }
24738                    else {
24739                        funcType = checkNonNullExpression(node.expression);
24740                    }
24741                }
24742                const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call);
24743                const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] :
24744                    some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) :
24745                    undefined;
24746                signature = links.effectsSignature = candidate && hasTypePredicateOrNeverReturnType(candidate) ? candidate : unknownSignature;
24747            }
24748            return signature === unknownSignature ? undefined : signature;
24749        }
24750
24751        function hasTypePredicateOrNeverReturnType(signature: Signature) {
24752            return !!(getTypePredicateOfSignature(signature) ||
24753                signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never);
24754        }
24755
24756        function getTypePredicateArgument(predicate: TypePredicate, callExpression: CallExpression) {
24757            if (predicate.kind === TypePredicateKind.Identifier || predicate.kind === TypePredicateKind.AssertsIdentifier) {
24758                return callExpression.arguments[predicate.parameterIndex];
24759            }
24760            const invokedExpression = skipParentheses(callExpression.expression);
24761            return isAccessExpression(invokedExpression) ? skipParentheses(invokedExpression.expression) : undefined;
24762        }
24763
24764        function reportFlowControlError(node: Node) {
24765            const block = findAncestor(node, isFunctionOrModuleBlock) as Block | ModuleBlock | SourceFile;
24766            const sourceFile = getSourceFileOfNode(node);
24767            const span = getSpanOfTokenAtPosition(sourceFile, block.statements.pos);
24768            diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis));
24769        }
24770
24771        function isReachableFlowNode(flow: FlowNode) {
24772            const result = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ false);
24773            lastFlowNode = flow;
24774            lastFlowNodeReachable = result;
24775            return result;
24776        }
24777
24778        function isFalseExpression(expr: Expression): boolean {
24779            const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true);
24780            return node.kind === SyntaxKind.FalseKeyword || node.kind === SyntaxKind.BinaryExpression && (
24781                (node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken && (isFalseExpression((node as BinaryExpression).left) || isFalseExpression((node as BinaryExpression).right)) ||
24782                (node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken && isFalseExpression((node as BinaryExpression).left) && isFalseExpression((node as BinaryExpression).right));
24783        }
24784
24785        function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck: boolean): boolean {
24786            while (true) {
24787                if (flow === lastFlowNode) {
24788                    return lastFlowNodeReachable;
24789                }
24790                const flags = flow.flags;
24791                if (flags & FlowFlags.Shared) {
24792                    if (!noCacheCheck) {
24793                        const id = getFlowNodeId(flow);
24794                        const reachable = flowNodeReachable[id];
24795                        return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ true));
24796                    }
24797                    noCacheCheck = false;
24798                }
24799                if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation)) {
24800                    flow = (flow as FlowAssignment | FlowCondition | FlowArrayMutation).antecedent;
24801                }
24802                else if (flags & FlowFlags.Call) {
24803                    const signature = getEffectsSignature((flow as FlowCall).node);
24804                    if (signature) {
24805                        const predicate = getTypePredicateOfSignature(signature);
24806                        if (predicate && predicate.kind === TypePredicateKind.AssertsIdentifier && !predicate.type) {
24807                            const predicateArgument = (flow as FlowCall).node.arguments[predicate.parameterIndex];
24808                            if (predicateArgument && isFalseExpression(predicateArgument)) {
24809                                return false;
24810                            }
24811                        }
24812                        if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
24813                            return false;
24814                        }
24815                    }
24816                    flow = (flow as FlowCall).antecedent;
24817                }
24818                else if (flags & FlowFlags.BranchLabel) {
24819                    // A branching point is reachable if any branch is reachable.
24820                    return some((flow as FlowLabel).antecedents, f => isReachableFlowNodeWorker(f, /*noCacheCheck*/ false));
24821                }
24822                else if (flags & FlowFlags.LoopLabel) {
24823                    const antecedents = (flow as FlowLabel).antecedents;
24824                    if (antecedents === undefined || antecedents.length === 0) {
24825                        return false;
24826                    }
24827                    // A loop is reachable if the control flow path that leads to the top is reachable.
24828                    flow = antecedents[0];
24829                }
24830                else if (flags & FlowFlags.SwitchClause) {
24831                    // The control flow path representing an unmatched value in a switch statement with
24832                    // no default clause is unreachable if the switch statement is exhaustive.
24833                    if ((flow as FlowSwitchClause).clauseStart === (flow as FlowSwitchClause).clauseEnd && isExhaustiveSwitchStatement((flow as FlowSwitchClause).switchStatement)) {
24834                        return false;
24835                    }
24836                    flow = (flow as FlowSwitchClause).antecedent;
24837                }
24838                else if (flags & FlowFlags.ReduceLabel) {
24839                    // Cache is unreliable once we start adjusting labels
24840                    lastFlowNode = undefined;
24841                    const target = (flow as FlowReduceLabel).target;
24842                    const saveAntecedents = target.antecedents;
24843                    target.antecedents = (flow as FlowReduceLabel).antecedents;
24844                    const result = isReachableFlowNodeWorker((flow as FlowReduceLabel).antecedent, /*noCacheCheck*/ false);
24845                    target.antecedents = saveAntecedents;
24846                    return result;
24847                }
24848                else {
24849                    return !(flags & FlowFlags.Unreachable);
24850                }
24851            }
24852        }
24853
24854        // Return true if the given flow node is preceded by a 'super(...)' call in every possible code path
24855        // leading to the node.
24856        function isPostSuperFlowNode(flow: FlowNode, noCacheCheck: boolean): boolean {
24857            while (true) {
24858                const flags = flow.flags;
24859                if (flags & FlowFlags.Shared) {
24860                    if (!noCacheCheck) {
24861                        const id = getFlowNodeId(flow);
24862                        const postSuper = flowNodePostSuper[id];
24863                        return postSuper !== undefined ? postSuper : (flowNodePostSuper[id] = isPostSuperFlowNode(flow, /*noCacheCheck*/ true));
24864                    }
24865                    noCacheCheck = false;
24866                }
24867                if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.SwitchClause)) {
24868                    flow = (flow as FlowAssignment | FlowCondition | FlowArrayMutation | FlowSwitchClause).antecedent;
24869                }
24870                else if (flags & FlowFlags.Call) {
24871                    if ((flow as FlowCall).node.expression.kind === SyntaxKind.SuperKeyword) {
24872                        return true;
24873                    }
24874                    flow = (flow as FlowCall).antecedent;
24875                }
24876                else if (flags & FlowFlags.BranchLabel) {
24877                    // A branching point is post-super if every branch is post-super.
24878                    return every((flow as FlowLabel).antecedents, f => isPostSuperFlowNode(f, /*noCacheCheck*/ false));
24879                }
24880                else if (flags & FlowFlags.LoopLabel) {
24881                    // A loop is post-super if the control flow path that leads to the top is post-super.
24882                    flow = (flow as FlowLabel).antecedents![0];
24883                }
24884                else if (flags & FlowFlags.ReduceLabel) {
24885                    const target = (flow as FlowReduceLabel).target;
24886                    const saveAntecedents = target.antecedents;
24887                    target.antecedents = (flow as FlowReduceLabel).antecedents;
24888                    const result = isPostSuperFlowNode((flow as FlowReduceLabel).antecedent, /*noCacheCheck*/ false);
24889                    target.antecedents = saveAntecedents;
24890                    return result;
24891                }
24892                else {
24893                    // Unreachable nodes are considered post-super to silence errors
24894                    return !!(flags & FlowFlags.Unreachable);
24895                }
24896            }
24897        }
24898
24899        function isConstantReference(node: Node): boolean {
24900            switch (node.kind) {
24901                case SyntaxKind.Identifier: {
24902                    const symbol = getResolvedSymbol(node as Identifier);
24903                    return isConstVariable(symbol) || isParameterOrCatchClauseVariable(symbol) && !isSymbolAssigned(symbol);
24904                }
24905                case SyntaxKind.PropertyAccessExpression:
24906                case SyntaxKind.ElementAccessExpression:
24907                    // The resolvedSymbol property is initialized by checkPropertyAccess or checkElementAccess before we get here.
24908                    return isConstantReference((node as AccessExpression).expression) && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol);
24909            }
24910            return false;
24911        }
24912
24913        function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, flowNode = reference.flowNode) {
24914            let key: string | undefined;
24915            let isKeySet = false;
24916            let flowDepth = 0;
24917            if (flowAnalysisDisabled) {
24918                return errorType;
24919            }
24920            if (!flowNode) {
24921                return declaredType;
24922            }
24923            flowInvocationCount++;
24924            const sharedFlowStart = sharedFlowCount;
24925            const evolvedType = getTypeFromFlowType(getTypeAtFlowNode(flowNode));
24926            sharedFlowCount = sharedFlowStart;
24927            // When the reference is 'x' in an 'x.length', 'x.push(value)', 'x.unshift(value)' or x[n] = value' operation,
24928            // we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations
24929            // on empty arrays are possible without implicit any errors and new element types can be inferred without
24930            // type mismatch errors.
24931            const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType);
24932            if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && !(resultType.flags & TypeFlags.Never) && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
24933                return declaredType;
24934            }
24935            // The non-null unknown type should never escape control flow analysis.
24936            return resultType === nonNullUnknownType ? unknownType : resultType;
24937
24938            function getOrSetCacheKey() {
24939                if (isKeySet) {
24940                    return key;
24941                }
24942                isKeySet = true;
24943                return key = getFlowCacheKey(reference, declaredType, initialType, flowContainer);
24944            }
24945
24946            function getTypeAtFlowNode(flow: FlowNode): FlowType {
24947                if (flowDepth === getMaxFlowDepth(compilerOptions)) {
24948                    // We have made the number of recursive invocations by user configuring, or default value 2000.
24949                    // To avoid overflowing the call stack we report an error
24950                    // and disable further control flow analysis in the containing function or module body.
24951                    tracing?.instant(tracing.Phase.CheckTypes, "getTypeAtFlowNode_DepthLimit", { flowId: flow.id });
24952                    flowAnalysisDisabled = true;
24953                    reportFlowControlError(reference);
24954                    return errorType;
24955                }
24956                flowDepth++;
24957                let sharedFlow: FlowNode | undefined;
24958                while (true) {
24959                    const flags = flow.flags;
24960                    if (flags & FlowFlags.Shared) {
24961                        // We cache results of flow type resolution for shared nodes that were previously visited in
24962                        // the same getFlowTypeOfReference invocation. A node is considered shared when it is the
24963                        // antecedent of more than one node.
24964                        for (let i = sharedFlowStart; i < sharedFlowCount; i++) {
24965                            if (sharedFlowNodes[i] === flow) {
24966                                flowDepth--;
24967                                return sharedFlowTypes[i];
24968                            }
24969                        }
24970                        sharedFlow = flow;
24971                    }
24972                    let type: FlowType | undefined;
24973                    if (flags & FlowFlags.Assignment) {
24974                        type = getTypeAtFlowAssignment(flow as FlowAssignment);
24975                        if (!type) {
24976                            flow = (flow as FlowAssignment).antecedent;
24977                            continue;
24978                        }
24979                    }
24980                    else if (flags & FlowFlags.Call) {
24981                        type = getTypeAtFlowCall(flow as FlowCall);
24982                        if (!type) {
24983                            flow = (flow as FlowCall).antecedent;
24984                            continue;
24985                        }
24986                    }
24987                    else if (flags & FlowFlags.Condition) {
24988                        type = getTypeAtFlowCondition(flow as FlowCondition);
24989                    }
24990                    else if (flags & FlowFlags.SwitchClause) {
24991                        type = getTypeAtSwitchClause(flow as FlowSwitchClause);
24992                    }
24993                    else if (flags & FlowFlags.Label) {
24994                        if ((flow as FlowLabel).antecedents!.length === 1) {
24995                            flow = (flow as FlowLabel).antecedents![0];
24996                            continue;
24997                        }
24998                        type = flags & FlowFlags.BranchLabel ?
24999                            getTypeAtFlowBranchLabel(flow as FlowLabel) :
25000                            getTypeAtFlowLoopLabel(flow as FlowLabel);
25001                    }
25002                    else if (flags & FlowFlags.ArrayMutation) {
25003                        type = getTypeAtFlowArrayMutation(flow as FlowArrayMutation);
25004                        if (!type) {
25005                            flow = (flow as FlowArrayMutation).antecedent;
25006                            continue;
25007                        }
25008                    }
25009                    else if (flags & FlowFlags.ReduceLabel) {
25010                        const target = (flow as FlowReduceLabel).target;
25011                        const saveAntecedents = target.antecedents;
25012                        target.antecedents = (flow as FlowReduceLabel).antecedents;
25013                        type = getTypeAtFlowNode((flow as FlowReduceLabel).antecedent);
25014                        target.antecedents = saveAntecedents;
25015                    }
25016                    else if (flags & FlowFlags.Start) {
25017                        // Check if we should continue with the control flow of the containing function.
25018                        const container = (flow as FlowStart).node;
25019                        if (container && container !== flowContainer &&
25020                            reference.kind !== SyntaxKind.PropertyAccessExpression &&
25021                            reference.kind !== SyntaxKind.ElementAccessExpression &&
25022                            reference.kind !== SyntaxKind.ThisKeyword) {
25023                            flow = container.flowNode!;
25024                            continue;
25025                        }
25026                        // At the top of the flow we have the initial type.
25027                        type = initialType;
25028                    }
25029                    else {
25030                        // Unreachable code errors are reported in the binding phase. Here we
25031                        // simply return the non-auto declared type to reduce follow-on errors.
25032                        type = convertAutoToAny(declaredType);
25033                    }
25034                    if (sharedFlow) {
25035                        // Record visited node and the associated type in the cache.
25036                        sharedFlowNodes[sharedFlowCount] = sharedFlow;
25037                        sharedFlowTypes[sharedFlowCount] = type;
25038                        sharedFlowCount++;
25039                    }
25040                    flowDepth--;
25041                    return type;
25042                }
25043            }
25044
25045            function getInitialOrAssignedType(flow: FlowAssignment) {
25046                const node = flow.node;
25047                return getNarrowableTypeForReference(node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ?
25048                    getInitialType(node as VariableDeclaration | BindingElement) :
25049                    getAssignedType(node), reference);
25050            }
25051
25052            function getTypeAtFlowAssignment(flow: FlowAssignment) {
25053                const node = flow.node;
25054                // Assignments only narrow the computed type if the declared type is a union type. Thus, we
25055                // only need to evaluate the assigned type if the declared type is a union type.
25056                if (isMatchingReference(reference, node)) {
25057                    if (!isReachableFlowNode(flow)) {
25058                        return unreachableNeverType;
25059                    }
25060                    if (getAssignmentTargetKind(node) === AssignmentKind.Compound) {
25061                        const flowType = getTypeAtFlowNode(flow.antecedent);
25062                        return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType));
25063                    }
25064                    if (declaredType === autoType || declaredType === autoArrayType) {
25065                        if (isEmptyArrayAssignment(node)) {
25066                            return getEvolvingArrayType(neverType);
25067                        }
25068                        const assignedType = getWidenedLiteralType(getInitialOrAssignedType(flow));
25069                        return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType;
25070                    }
25071                    if (declaredType.flags & TypeFlags.Union) {
25072                        return getAssignmentReducedType(declaredType as UnionType, getInitialOrAssignedType(flow));
25073                    }
25074                    return declaredType;
25075                }
25076                // We didn't have a direct match. However, if the reference is a dotted name, this
25077                // may be an assignment to a left hand part of the reference. For example, for a
25078                // reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case,
25079                // return the declared type.
25080                if (containsMatchingReference(reference, node)) {
25081                    if (!isReachableFlowNode(flow)) {
25082                        return unreachableNeverType;
25083                    }
25084                    // A matching dotted name might also be an expando property on a function *expression*,
25085                    // in which case we continue control flow analysis back to the function's declaration
25086                    if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) {
25087                        const init = getDeclaredExpandoInitializer(node);
25088                        if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) {
25089                            return getTypeAtFlowNode(flow.antecedent);
25090                        }
25091                    }
25092                    return declaredType;
25093                }
25094                // for (const _ in ref) acts as a nonnull on ref
25095                if (isVariableDeclaration(node) && node.parent.parent.kind === SyntaxKind.ForInStatement && isMatchingReference(reference, node.parent.parent.expression)) {
25096                    return getNonNullableTypeIfNeeded(finalizeEvolvingArrayType(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent))));
25097                }
25098                // Assignment doesn't affect reference
25099                return undefined;
25100            }
25101
25102            function narrowTypeByAssertion(type: Type, expr: Expression): Type {
25103                const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true);
25104                if (node.kind === SyntaxKind.FalseKeyword) {
25105                    return unreachableNeverType;
25106                }
25107                if (node.kind === SyntaxKind.BinaryExpression) {
25108                    if ((node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
25109                        return narrowTypeByAssertion(narrowTypeByAssertion(type, (node as BinaryExpression).left), (node as BinaryExpression).right);
25110                    }
25111                    if ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken) {
25112                        return getUnionType([narrowTypeByAssertion(type, (node as BinaryExpression).left), narrowTypeByAssertion(type, (node as BinaryExpression).right)]);
25113                    }
25114                }
25115                return narrowType(type, node, /*assumeTrue*/ true);
25116            }
25117
25118            function getTypeAtFlowCall(flow: FlowCall): FlowType | undefined {
25119                const signature = getEffectsSignature(flow.node);
25120                if (signature) {
25121                    const predicate = getTypePredicateOfSignature(signature);
25122                    if (predicate && (predicate.kind === TypePredicateKind.AssertsThis || predicate.kind === TypePredicateKind.AssertsIdentifier)) {
25123                        const flowType = getTypeAtFlowNode(flow.antecedent);
25124                        const type = finalizeEvolvingArrayType(getTypeFromFlowType(flowType));
25125                        const narrowedType = predicate.type ? narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) :
25126                            predicate.kind === TypePredicateKind.AssertsIdentifier && predicate.parameterIndex >= 0 && predicate.parameterIndex < flow.node.arguments.length ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) :
25127                            type;
25128                        return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType));
25129                    }
25130                    if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
25131                        return unreachableNeverType;
25132                    }
25133                }
25134                return undefined;
25135            }
25136
25137            function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined {
25138                if (declaredType === autoType || declaredType === autoArrayType) {
25139                    const node = flow.node;
25140                    const expr = node.kind === SyntaxKind.CallExpression ?
25141                        (node.expression as PropertyAccessExpression).expression :
25142                        (node.left as ElementAccessExpression).expression;
25143                    if (isMatchingReference(reference, getReferenceCandidate(expr))) {
25144                        const flowType = getTypeAtFlowNode(flow.antecedent);
25145                        const type = getTypeFromFlowType(flowType);
25146                        if (getObjectFlags(type) & ObjectFlags.EvolvingArray) {
25147                            let evolvedType = type as EvolvingArrayType;
25148                            if (node.kind === SyntaxKind.CallExpression) {
25149                                for (const arg of node.arguments) {
25150                                    evolvedType = addEvolvingArrayElementType(evolvedType, arg);
25151                                }
25152                            }
25153                            else {
25154                                // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time)
25155                                const indexType = getContextFreeTypeOfExpression((node.left as ElementAccessExpression).argumentExpression);
25156                                if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) {
25157                                    evolvedType = addEvolvingArrayElementType(evolvedType, node.right);
25158                                }
25159                            }
25160                            return evolvedType === type ? flowType : createFlowType(evolvedType, isIncomplete(flowType));
25161                        }
25162                        return flowType;
25163                    }
25164                }
25165                return undefined;
25166            }
25167
25168            function getTypeAtFlowCondition(flow: FlowCondition): FlowType {
25169                const flowType = getTypeAtFlowNode(flow.antecedent);
25170                const type = getTypeFromFlowType(flowType);
25171                if (type.flags & TypeFlags.Never) {
25172                    return flowType;
25173                }
25174                // If we have an antecedent type (meaning we're reachable in some way), we first
25175                // attempt to narrow the antecedent type. If that produces the never type, and if
25176                // the antecedent type is incomplete (i.e. a transient type in a loop), then we
25177                // take the type guard as an indication that control *could* reach here once we
25178                // have the complete type. We proceed by switching to the silent never type which
25179                // doesn't report errors when operators are applied to it. Note that this is the
25180                // *only* place a silent never type is ever generated.
25181                const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
25182                const nonEvolvingType = finalizeEvolvingArrayType(type);
25183                const narrowedType = narrowType(nonEvolvingType, flow.node, assumeTrue);
25184                if (narrowedType === nonEvolvingType) {
25185                    return flowType;
25186                }
25187                return createFlowType(narrowedType, isIncomplete(flowType));
25188            }
25189
25190            function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
25191                const expr = flow.switchStatement.expression;
25192                const flowType = getTypeAtFlowNode(flow.antecedent);
25193                let type = getTypeFromFlowType(flowType);
25194                if (isMatchingReference(reference, expr)) {
25195                    type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
25196                }
25197                else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) {
25198                    type = narrowTypeBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
25199                }
25200                else {
25201                    if (strictNullChecks) {
25202                        if (optionalChainContainsReference(expr, reference)) {
25203                            type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd,
25204                                t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never)));
25205                        }
25206                        else if (expr.kind === SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as TypeOfExpression).expression, reference)) {
25207                            type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd,
25208                                t => !(t.flags & TypeFlags.Never || t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === "undefined"));
25209                        }
25210                    }
25211                    const access = getDiscriminantPropertyAccess(expr, type);
25212                    if (access) {
25213                        type = narrowTypeBySwitchOnDiscriminantProperty(type, access, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
25214                    }
25215                }
25216                return createFlowType(type, isIncomplete(flowType));
25217            }
25218
25219            function getTypeAtFlowBranchLabel(flow: FlowLabel): FlowType {
25220                const antecedentTypes: Type[] = [];
25221                let subtypeReduction = false;
25222                let seenIncomplete = false;
25223                let bypassFlow: FlowSwitchClause | undefined;
25224                for (const antecedent of flow.antecedents!) {
25225                    if (!bypassFlow && antecedent.flags & FlowFlags.SwitchClause && (antecedent as FlowSwitchClause).clauseStart === (antecedent as FlowSwitchClause).clauseEnd) {
25226                        // The antecedent is the bypass branch of a potentially exhaustive switch statement.
25227                        bypassFlow = antecedent as FlowSwitchClause;
25228                        continue;
25229                    }
25230                    const flowType = getTypeAtFlowNode(antecedent);
25231                    const type = getTypeFromFlowType(flowType);
25232                    // If the type at a particular antecedent path is the declared type and the
25233                    // reference is known to always be assigned (i.e. when declared and initial types
25234                    // are the same), there is no reason to process more antecedents since the only
25235                    // possible outcome is subtypes that will be removed in the final union type anyway.
25236                    if (type === declaredType && declaredType === initialType) {
25237                        return type;
25238                    }
25239                    pushIfUnique(antecedentTypes, type);
25240                    // If an antecedent type is not a subset of the declared type, we need to perform
25241                    // subtype reduction. This happens when a "foreign" type is injected into the control
25242                    // flow using the instanceof operator or a user defined type predicate.
25243                    if (!isTypeSubsetOf(type, declaredType)) {
25244                        subtypeReduction = true;
25245                    }
25246                    if (isIncomplete(flowType)) {
25247                        seenIncomplete = true;
25248                    }
25249                }
25250                if (bypassFlow) {
25251                    const flowType = getTypeAtFlowNode(bypassFlow);
25252                    const type = getTypeFromFlowType(flowType);
25253                    // If the bypass flow contributes a type we haven't seen yet and the switch statement
25254                    // isn't exhaustive, process the bypass flow type. Since exhaustiveness checks increase
25255                    // the risk of circularities, we only want to perform them when they make a difference.
25256                    if (!contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) {
25257                        if (type === declaredType && declaredType === initialType) {
25258                            return type;
25259                        }
25260                        antecedentTypes.push(type);
25261                        if (!isTypeSubsetOf(type, declaredType)) {
25262                            subtypeReduction = true;
25263                        }
25264                        if (isIncomplete(flowType)) {
25265                            seenIncomplete = true;
25266                        }
25267                    }
25268                }
25269                return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal), seenIncomplete);
25270            }
25271
25272            function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType {
25273                // If we have previously computed the control flow type for the reference at
25274                // this flow loop junction, return the cached type.
25275                const id = getFlowNodeId(flow);
25276                const cache = flowLoopCaches[id] || (flowLoopCaches[id] = new Map<string, Type>());
25277                const key = getOrSetCacheKey();
25278                if (!key) {
25279                    // No cache key is generated when binding patterns are in unnarrowable situations
25280                    return declaredType;
25281                }
25282                const cached = cache.get(key);
25283                if (cached) {
25284                    return cached;
25285                }
25286                // If this flow loop junction and reference are already being processed, return
25287                // the union of the types computed for each branch so far, marked as incomplete.
25288                // It is possible to see an empty array in cases where loops are nested and the
25289                // back edge of the outer loop reaches an inner loop that is already being analyzed.
25290                // In such cases we restart the analysis of the inner loop, which will then see
25291                // a non-empty in-process array for the outer loop and eventually terminate because
25292                // the first antecedent of a loop junction is always the non-looping control flow
25293                // path that leads to the top.
25294                for (let i = flowLoopStart; i < flowLoopCount; i++) {
25295                    if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key && flowLoopTypes[i].length) {
25296                        return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], UnionReduction.Literal), /*incomplete*/ true);
25297                    }
25298                }
25299                // Add the flow loop junction and reference to the in-process stack and analyze
25300                // each antecedent code path.
25301                const antecedentTypes: Type[] = [];
25302                let subtypeReduction = false;
25303                let firstAntecedentType: FlowType | undefined;
25304                for (const antecedent of flow.antecedents!) {
25305                    let flowType;
25306                    if (!firstAntecedentType) {
25307                        // The first antecedent of a loop junction is always the non-looping control
25308                        // flow path that leads to the top.
25309                        flowType = firstAntecedentType = getTypeAtFlowNode(antecedent);
25310                    }
25311                    else {
25312                        // All but the first antecedent are the looping control flow paths that lead
25313                        // back to the loop junction. We track these on the flow loop stack.
25314                        flowLoopNodes[flowLoopCount] = flow;
25315                        flowLoopKeys[flowLoopCount] = key;
25316                        flowLoopTypes[flowLoopCount] = antecedentTypes;
25317                        flowLoopCount++;
25318                        const saveFlowTypeCache = flowTypeCache;
25319                        flowTypeCache = undefined;
25320                        flowType = getTypeAtFlowNode(antecedent);
25321                        flowTypeCache = saveFlowTypeCache;
25322                        flowLoopCount--;
25323                        // If we see a value appear in the cache it is a sign that control flow analysis
25324                        // was restarted and completed by checkExpressionCached. We can simply pick up
25325                        // the resulting type and bail out.
25326                        const cached = cache.get(key);
25327                        if (cached) {
25328                            return cached;
25329                        }
25330                    }
25331                    const type = getTypeFromFlowType(flowType);
25332                    pushIfUnique(antecedentTypes, type);
25333                    // If an antecedent type is not a subset of the declared type, we need to perform
25334                    // subtype reduction. This happens when a "foreign" type is injected into the control
25335                    // flow using the instanceof operator or a user defined type predicate.
25336                    if (!isTypeSubsetOf(type, declaredType)) {
25337                        subtypeReduction = true;
25338                    }
25339                    // If the type at a particular antecedent path is the declared type there is no
25340                    // reason to process more antecedents since the only possible outcome is subtypes
25341                    // that will be removed in the final union type anyway.
25342                    if (type === declaredType) {
25343                        break;
25344                    }
25345                }
25346                // The result is incomplete if the first antecedent (the non-looping control flow path)
25347                // is incomplete.
25348                const result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal);
25349                if (isIncomplete(firstAntecedentType!)) {
25350                    return createFlowType(result, /*incomplete*/ true);
25351                }
25352                cache.set(key, result);
25353                return result;
25354            }
25355
25356            // At flow control branch or loop junctions, if the type along every antecedent code path
25357            // is an evolving array type, we construct a combined evolving array type. Otherwise we
25358            // finalize all evolving array types.
25359            function getUnionOrEvolvingArrayType(types: Type[], subtypeReduction: UnionReduction) {
25360                if (isEvolvingArrayTypeList(types)) {
25361                    return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType)));
25362                }
25363                const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction));
25364                if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arraysEqual((result as UnionType).types, (declaredType as UnionType).types)) {
25365                    return declaredType;
25366                }
25367                return result;
25368            }
25369
25370            function getCandidateDiscriminantPropertyAccess(expr: Expression) {
25371                if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) {
25372                    // When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in
25373                    // getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or
25374                    // parameter declared in the same parameter list is a candidate.
25375                    if (isIdentifier(expr)) {
25376                        const symbol = getResolvedSymbol(expr);
25377                        const declaration = symbol.valueDeclaration;
25378                        if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) {
25379                            return declaration;
25380                        }
25381                    }
25382                }
25383                else if (isAccessExpression(expr)) {
25384                    // An access expression is a candidate if the reference matches the left hand expression.
25385                    if (isMatchingReference(reference, expr.expression)) {
25386                        return expr;
25387                    }
25388                }
25389                else if (isIdentifier(expr)) {
25390                    const symbol = getResolvedSymbol(expr);
25391                    if (isConstVariable(symbol)) {
25392                        const declaration = symbol.valueDeclaration!;
25393                        // Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind'
25394                        if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) &&
25395                            isMatchingReference(reference, declaration.initializer.expression)) {
25396                            return declaration.initializer;
25397                        }
25398                        // Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind'
25399                        if (isBindingElement(declaration) && !declaration.initializer) {
25400                            const parent = declaration.parent.parent;
25401                            if (isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) &&
25402                                isMatchingReference(reference, parent.initializer)) {
25403                                return declaration;
25404                            }
25405                        }
25406                    }
25407                }
25408                return undefined;
25409            }
25410
25411            function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
25412                const type = declaredType.flags & TypeFlags.Union ? declaredType : computedType;
25413                if (type.flags & TypeFlags.Union) {
25414                    const access = getCandidateDiscriminantPropertyAccess(expr);
25415                    if (access) {
25416                        const name = getAccessedPropertyName(access);
25417                        if (name && isDiscriminantProperty(type, name)) {
25418                            return access;
25419                        }
25420                    }
25421                }
25422                return undefined;
25423            }
25424
25425            function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowType: (t: Type) => Type): Type {
25426                const propName = getAccessedPropertyName(access);
25427                if (propName === undefined) {
25428                    return type;
25429                }
25430                const removeNullable = strictNullChecks && isOptionalChain(access) && maybeTypeOfKind(type, TypeFlags.Nullable);
25431                let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName);
25432                if (!propType) {
25433                    return type;
25434                }
25435                propType = removeNullable ? getOptionalType(propType) : propType;
25436                const narrowedPropType = narrowType(propType);
25437                return filterType(type, t => {
25438                    const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName);
25439                    return !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType);
25440                });
25441            }
25442
25443            function narrowTypeByDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, operator: SyntaxKind, value: Expression, assumeTrue: boolean) {
25444                if ((operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & TypeFlags.Union) {
25445                    const keyPropertyName = getKeyPropertyName(type as UnionType);
25446                    if (keyPropertyName && keyPropertyName === getAccessedPropertyName(access)) {
25447                        const candidate = getConstituentTypeForKeyType(type as UnionType, getTypeOfExpression(value));
25448                        if (candidate) {
25449                            return operator === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate :
25450                                isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? removeType(type, candidate) :
25451                                type;
25452                        }
25453                    }
25454                }
25455                return narrowTypeByDiscriminant(type, access, t => narrowTypeByEquality(t, operator, value, assumeTrue));
25456            }
25457
25458            function narrowTypeBySwitchOnDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
25459                if (clauseStart < clauseEnd && type.flags & TypeFlags.Union && getKeyPropertyName(type as UnionType) === getAccessedPropertyName(access)) {
25460                    const clauseTypes = getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd);
25461                    const candidate = getUnionType(map(clauseTypes, t => getConstituentTypeForKeyType(type as UnionType, t) || unknownType));
25462                    if (candidate !== unknownType) {
25463                        return candidate;
25464                    }
25465                }
25466                return narrowTypeByDiscriminant(type, access, t => narrowTypeBySwitchOnDiscriminant(t, switchStatement, clauseStart, clauseEnd));
25467            }
25468
25469            function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type {
25470                if (isMatchingReference(reference, expr)) {
25471                    return getAdjustedTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy);
25472                }
25473                if (strictNullChecks && assumeTrue && optionalChainContainsReference(expr, reference)) {
25474                    type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
25475                }
25476                const access = getDiscriminantPropertyAccess(expr, type);
25477                if (access) {
25478                    return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
25479                }
25480                return type;
25481            }
25482
25483            function isTypePresencePossible(type: Type, propName: __String, assumeTrue: boolean) {
25484                const prop = getPropertyOfType(type, propName);
25485                return prop ?
25486                    !!(prop.flags & SymbolFlags.Optional) || assumeTrue :
25487                    !!getApplicableIndexInfoForName(type, propName) || !assumeTrue;
25488            }
25489
25490            function narrowTypeByInKeyword(type: Type, nameType: StringLiteralType | NumberLiteralType | UniqueESSymbolType, assumeTrue: boolean) {
25491                const name = getPropertyNameFromType(nameType);
25492                const isKnownProperty = someType(type, t => isTypePresencePossible(t, name, /*assumeTrue*/ true));
25493                if (isKnownProperty) {
25494                    // If the check is for a known property (i.e. a property declared in some constituent of
25495                    // the target type), we filter the target type by presence of absence of the property.
25496                    return filterType(type, t => isTypePresencePossible(t, name, assumeTrue));
25497                }
25498                if (assumeTrue) {
25499                    // If the check is for an unknown property, we intersect the target type with `Record<X, unknown>`,
25500                    // where X is the name of the property.
25501                    const recordSymbol = getGlobalRecordSymbol();
25502                    if (recordSymbol) {
25503                        return getIntersectionType([type, getTypeAliasInstantiation(recordSymbol, [nameType, unknownType])]);
25504                    }
25505                }
25506                return type;
25507            }
25508
25509            function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
25510                switch (expr.operatorToken.kind) {
25511                    case SyntaxKind.EqualsToken:
25512                    case SyntaxKind.BarBarEqualsToken:
25513                    case SyntaxKind.AmpersandAmpersandEqualsToken:
25514                    case SyntaxKind.QuestionQuestionEqualsToken:
25515                        return narrowTypeByTruthiness(narrowType(type, expr.right, assumeTrue), expr.left, assumeTrue);
25516                    case SyntaxKind.EqualsEqualsToken:
25517                    case SyntaxKind.ExclamationEqualsToken:
25518                    case SyntaxKind.EqualsEqualsEqualsToken:
25519                    case SyntaxKind.ExclamationEqualsEqualsToken:
25520                        const operator = expr.operatorToken.kind;
25521                        const left = getReferenceCandidate(expr.left);
25522                        const right = getReferenceCandidate(expr.right);
25523                        if (left.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(right)) {
25524                            return narrowTypeByTypeof(type, left as TypeOfExpression, operator, right, assumeTrue);
25525                        }
25526                        if (right.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(left)) {
25527                            return narrowTypeByTypeof(type, right as TypeOfExpression, operator, left, assumeTrue);
25528                        }
25529                        if (isMatchingReference(reference, left)) {
25530                            return narrowTypeByEquality(type, operator, right, assumeTrue);
25531                        }
25532                        if (isMatchingReference(reference, right)) {
25533                            return narrowTypeByEquality(type, operator, left, assumeTrue);
25534                        }
25535                        if (strictNullChecks) {
25536                            if (optionalChainContainsReference(left, reference)) {
25537                                type = narrowTypeByOptionalChainContainment(type, operator, right, assumeTrue);
25538                            }
25539                            else if (optionalChainContainsReference(right, reference)) {
25540                                type = narrowTypeByOptionalChainContainment(type, operator, left, assumeTrue);
25541                            }
25542                        }
25543                        const leftAccess = getDiscriminantPropertyAccess(left, type);
25544                        if (leftAccess) {
25545                            return narrowTypeByDiscriminantProperty(type, leftAccess, operator, right, assumeTrue);
25546                        }
25547                        const rightAccess = getDiscriminantPropertyAccess(right, type);
25548                        if (rightAccess) {
25549                            return narrowTypeByDiscriminantProperty(type, rightAccess, operator, left, assumeTrue);
25550                        }
25551                        if (isMatchingConstructorReference(left)) {
25552                            return narrowTypeByConstructor(type, operator, right, assumeTrue);
25553                        }
25554                        if (isMatchingConstructorReference(right)) {
25555                            return narrowTypeByConstructor(type, operator, left, assumeTrue);
25556                        }
25557                        break;
25558                    case SyntaxKind.InstanceOfKeyword:
25559                        return narrowTypeByInstanceof(type, expr, assumeTrue);
25560                    case SyntaxKind.InKeyword:
25561                        if (isPrivateIdentifier(expr.left)) {
25562                            return narrowTypeByPrivateIdentifierInInExpression(type, expr, assumeTrue);
25563                        }
25564                        const target = getReferenceCandidate(expr.right);
25565                        const leftType = getTypeOfExpression(expr.left);
25566                        if (leftType.flags & TypeFlags.StringOrNumberLiteralOrUnique) {
25567                            if (containsMissingType(type) && isAccessExpression(reference) && isMatchingReference(reference.expression, target) &&
25568                                getAccessedPropertyName(reference) === getPropertyNameFromType(leftType as StringLiteralType | NumberLiteralType | UniqueESSymbolType)) {
25569                                return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined);
25570                            }
25571                            if (isMatchingReference(reference, target)) {
25572                                return narrowTypeByInKeyword(type, leftType as StringLiteralType | NumberLiteralType | UniqueESSymbolType, assumeTrue);
25573                            }
25574                        }
25575                        break;
25576                    case SyntaxKind.CommaToken:
25577                        return narrowType(type, expr.right, assumeTrue);
25578                    // Ordinarily we won't see && and || expressions in control flow analysis because the Binder breaks those
25579                    // expressions down to individual conditional control flows. However, we may encounter them when analyzing
25580                    // aliased conditional expressions.
25581                    case SyntaxKind.AmpersandAmpersandToken:
25582                        return assumeTrue ?
25583                            narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ true) :
25584                            getUnionType([narrowType(type, expr.left, /*assumeTrue*/ false), narrowType(type, expr.right, /*assumeTrue*/ false)]);
25585                    case SyntaxKind.BarBarToken:
25586                        return assumeTrue ?
25587                            getUnionType([narrowType(type, expr.left, /*assumeTrue*/ true), narrowType(type, expr.right, /*assumeTrue*/ true)]) :
25588                            narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ false);
25589                }
25590                return type;
25591            }
25592
25593            function narrowTypeByPrivateIdentifierInInExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
25594                const target = getReferenceCandidate(expr.right);
25595                if (!isMatchingReference(reference, target)) {
25596                    return type;
25597                }
25598
25599                Debug.assertNode(expr.left, isPrivateIdentifier);
25600                const symbol = getSymbolForPrivateIdentifierExpression(expr.left);
25601                if (symbol === undefined) {
25602                    return type;
25603                }
25604                const classSymbol = symbol.parent!;
25605                const targetType = hasStaticModifier(Debug.checkDefined(symbol.valueDeclaration, "should always have a declaration"))
25606                    ? getTypeOfSymbol(classSymbol) as InterfaceType
25607                    : getDeclaredTypeOfSymbol(classSymbol);
25608                return getNarrowedType(type, targetType, assumeTrue, /*checkDerived*/ true);
25609            }
25610
25611            function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
25612                // We are in a branch of obj?.foo === value (or any one of the other equality operators). We narrow obj as follows:
25613                // When operator is === and type of value excludes undefined, null and undefined is removed from type of obj in true branch.
25614                // When operator is !== and type of value excludes undefined, null and undefined is removed from type of obj in false branch.
25615                // When operator is == and type of value excludes null and undefined, null and undefined is removed from type of obj in true branch.
25616                // When operator is != and type of value excludes null and undefined, null and undefined is removed from type of obj in false branch.
25617                // When operator is === and type of value is undefined, null and undefined is removed from type of obj in false branch.
25618                // When operator is !== and type of value is undefined, null and undefined is removed from type of obj in true branch.
25619                // When operator is == and type of value is null or undefined, null and undefined is removed from type of obj in false branch.
25620                // When operator is != and type of value is null or undefined, null and undefined is removed from type of obj in true branch.
25621                const equalsOperator = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
25622                const nullableFlags = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? TypeFlags.Nullable : TypeFlags.Undefined;
25623                const valueType = getTypeOfExpression(value);
25624                // Note that we include any and unknown in the exclusion test because their domain includes null and undefined.
25625                const removeNullable = equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) ||
25626                    equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags)));
25627                return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
25628            }
25629
25630            function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
25631                if (type.flags & TypeFlags.Any) {
25632                    return type;
25633                }
25634                if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
25635                    assumeTrue = !assumeTrue;
25636                }
25637                const valueType = getTypeOfExpression(value);
25638                const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
25639                if (valueType.flags & TypeFlags.Nullable) {
25640                    if (!strictNullChecks) {
25641                        return type;
25642                    }
25643                    const facts = doubleEquals ?
25644                        assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull :
25645                        valueType.flags & TypeFlags.Null ?
25646                            assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
25647                            assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
25648                    return getAdjustedTypeWithFacts(type, facts);
25649                }
25650                if (assumeTrue) {
25651                    if (!doubleEquals && (type.flags & TypeFlags.Unknown || someType(type, isEmptyAnonymousObjectType))) {
25652                        if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || isEmptyAnonymousObjectType(valueType)) {
25653                            return valueType;
25654                        }
25655                        if (valueType.flags & TypeFlags.Object) {
25656                            return nonPrimitiveType;
25657                        }
25658                    }
25659                    const filteredType = filterType(type, t => areTypesComparable(t, valueType) || doubleEquals && isCoercibleUnderDoubleEquals(t, valueType));
25660                    return replacePrimitivesWithLiterals(filteredType, valueType);
25661                }
25662                if (isUnitType(valueType)) {
25663                    return filterType(type, t => !(isUnitLikeType(t) && areTypesComparable(t, valueType)));
25664                }
25665                return type;
25666            }
25667
25668            function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type {
25669                // We have '==', '!=', '===', or !==' operator with 'typeof xxx' and string literal operands
25670                if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
25671                    assumeTrue = !assumeTrue;
25672                }
25673                const target = getReferenceCandidate(typeOfExpr.expression);
25674                if (!isMatchingReference(reference, target)) {
25675                    const propertyAccess = getDiscriminantPropertyAccess(typeOfExpr.expression, type);
25676                    if (propertyAccess) {
25677                        return narrowTypeByDiscriminant(type, propertyAccess, t => narrowTypeByLiteralExpression(t, literal, assumeTrue));
25678                    }
25679                    if (strictNullChecks && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) {
25680                        return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
25681                    }
25682                    return type;
25683                }
25684                return narrowTypeByLiteralExpression(type, literal, assumeTrue);
25685            }
25686
25687            function narrowTypeByLiteralExpression(type: Type, literal: LiteralExpression, assumeTrue: boolean) {
25688                return assumeTrue ?
25689                    narrowTypeByTypeName(type, literal.text) :
25690                    getTypeWithFacts(type, typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject);
25691            }
25692
25693            function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) {
25694                const everyClauseChecks = clauseStart !== clauseEnd && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck);
25695                return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
25696            }
25697
25698            function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
25699                // We only narrow if all case expressions specify
25700                // values with unit types, except for the case where
25701                // `type` is unknown. In this instance we map object
25702                // types to the nonPrimitive type and narrow with that.
25703                const switchTypes = getSwitchClauseTypes(switchStatement);
25704                if (!switchTypes.length) {
25705                    return type;
25706                }
25707                const clauseTypes = switchTypes.slice(clauseStart, clauseEnd);
25708                const hasDefaultClause = clauseStart === clauseEnd || contains(clauseTypes, neverType);
25709                if ((type.flags & TypeFlags.Unknown) && !hasDefaultClause) {
25710                    let groundClauseTypes: Type[] | undefined;
25711                    for (let i = 0; i < clauseTypes.length; i += 1) {
25712                        const t = clauseTypes[i];
25713                        if (t.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) {
25714                            if (groundClauseTypes !== undefined) {
25715                                groundClauseTypes.push(t);
25716                            }
25717                        }
25718                        else if (t.flags & TypeFlags.Object) {
25719                            if (groundClauseTypes === undefined) {
25720                                groundClauseTypes = clauseTypes.slice(0, i);
25721                            }
25722                            groundClauseTypes.push(nonPrimitiveType);
25723                        }
25724                        else {
25725                            return type;
25726                        }
25727                    }
25728                    return getUnionType(groundClauseTypes === undefined ? clauseTypes : groundClauseTypes);
25729                }
25730                const discriminantType = getUnionType(clauseTypes);
25731                const caseType =
25732                    discriminantType.flags & TypeFlags.Never ? neverType :
25733                    replacePrimitivesWithLiterals(filterType(type, t => areTypesComparable(discriminantType, t)), discriminantType);
25734                if (!hasDefaultClause) {
25735                    return caseType;
25736                }
25737                const defaultType = filterType(type, t => !(isUnitLikeType(t) && contains(switchTypes, getRegularTypeOfLiteralType(extractUnitType(t)))));
25738                return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]);
25739            }
25740
25741            function narrowTypeByTypeName(type: Type, typeName: string) {
25742                switch (typeName) {
25743                    case "string": return narrowTypeByTypeFacts(type, stringType, TypeFacts.TypeofEQString);
25744                    case "number": return narrowTypeByTypeFacts(type, numberType, TypeFacts.TypeofEQNumber);
25745                    case "bigint": return narrowTypeByTypeFacts(type, bigintType, TypeFacts.TypeofEQBigInt);
25746                    case "boolean": return narrowTypeByTypeFacts(type, booleanType, TypeFacts.TypeofEQBoolean);
25747                    case "symbol": return narrowTypeByTypeFacts(type, esSymbolType, TypeFacts.TypeofEQSymbol);
25748                    case "object": return type.flags & TypeFlags.Any ? type : getUnionType([narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQObject), narrowTypeByTypeFacts(type, nullType, TypeFacts.EQNull)]);
25749                    case "function": return type.flags & TypeFlags.Any ? type : narrowTypeByTypeFacts(type, globalFunctionType, TypeFacts.TypeofEQFunction);
25750                    case "undefined": return narrowTypeByTypeFacts(type, undefinedType, TypeFacts.EQUndefined);
25751                }
25752                return narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQHostObject);
25753            }
25754
25755            function narrowTypeByTypeFacts(type: Type, impliedType: Type, facts: TypeFacts) {
25756                return mapType(type, t =>
25757                    // We first check if a constituent is a subtype of the implied type. If so, we either keep or eliminate
25758                    // the constituent based on its type facts. We use the strict subtype relation because it treats `object`
25759                    // as a subtype of `{}`, and we need the type facts check because function types are subtypes of `object`,
25760                    // but are classified as "function" according to `typeof`.
25761                    isTypeRelatedTo(t, impliedType, strictSubtypeRelation) ? getTypeFacts(t) & facts ? t : neverType :
25762                    // We next check if the consituent is a supertype of the implied type. If so, we substitute the implied
25763                    // type. This handles top types like `unknown` and `{}`, and supertypes like `{ toString(): string }`.
25764                    isTypeSubtypeOf(impliedType, t) ? impliedType :
25765                    // Neither the constituent nor the implied type is a subtype of the other, however their domains may still
25766                    // overlap. For example, an unconstrained type parameter and type `string`. If the type facts indicate
25767                    // possible overlap, we form an intersection. Otherwise, we eliminate the constituent.
25768                    getTypeFacts(t) & facts ? getIntersectionType([t, impliedType]) :
25769                    neverType);
25770            }
25771
25772            function narrowTypeBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type {
25773                const witnesses = getSwitchClauseTypeOfWitnesses(switchStatement);
25774                if (!witnesses) {
25775                    return type;
25776                }
25777                // Equal start and end denotes implicit fallthrough; undefined marks explicit default clause.
25778                const defaultIndex = findIndex(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.DefaultClause);
25779                const hasDefaultClause = clauseStart === clauseEnd || (defaultIndex >= clauseStart && defaultIndex < clauseEnd);
25780                if (hasDefaultClause) {
25781                    // In the default clause we filter constituents down to those that are not-equal to all handled cases.
25782                    const notEqualFacts = getNotEqualFactsFromTypeofSwitch(clauseStart, clauseEnd, witnesses);
25783                    return filterType(type, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts);
25784                }
25785                // In the non-default cause we create a union of the type narrowed by each of the listed cases.
25786                const clauseWitnesses = witnesses.slice(clauseStart, clauseEnd);
25787                return getUnionType(map(clauseWitnesses, text => text ? narrowTypeByTypeName(type, text) : neverType));
25788            }
25789
25790            function isMatchingConstructorReference(expr: Expression) {
25791                return (isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" ||
25792                    isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor") &&
25793                    isMatchingReference(reference, expr.expression);
25794            }
25795
25796            function narrowTypeByConstructor(type: Type, operator: SyntaxKind, identifier: Expression, assumeTrue: boolean): Type {
25797                // Do not narrow when checking inequality.
25798                if (assumeTrue ? (operator !== SyntaxKind.EqualsEqualsToken && operator !== SyntaxKind.EqualsEqualsEqualsToken) : (operator !== SyntaxKind.ExclamationEqualsToken && operator !== SyntaxKind.ExclamationEqualsEqualsToken)) {
25799                    return type;
25800                }
25801
25802                // Get the type of the constructor identifier expression, if it is not a function then do not narrow.
25803                const identifierType = getTypeOfExpression(identifier);
25804                if (!isFunctionType(identifierType) && !isConstructorType(identifierType)) {
25805                    return type;
25806                }
25807
25808                // Get the prototype property of the type identifier so we can find out its type.
25809                const prototypeProperty = getPropertyOfType(identifierType, "prototype" as __String);
25810                if (!prototypeProperty) {
25811                    return type;
25812                }
25813
25814                // Get the type of the prototype, if it is undefined, or the global `Object` or `Function` types then do not narrow.
25815                const prototypeType = getTypeOfSymbol(prototypeProperty);
25816                const candidate = !isTypeAny(prototypeType) ? prototypeType : undefined;
25817                if (!candidate || candidate === globalObjectType || candidate === globalFunctionType) {
25818                    return type;
25819                }
25820
25821                // If the type that is being narrowed is `any` then just return the `candidate` type since every type is a subtype of `any`.
25822                if (isTypeAny(type)) {
25823                    return candidate;
25824                }
25825
25826                // Filter out types that are not considered to be "constructed by" the `candidate` type.
25827                return filterType(type, t => isConstructedBy(t, candidate));
25828
25829                function isConstructedBy(source: Type, target: Type) {
25830                    // If either the source or target type are a class type then we need to check that they are the same exact type.
25831                    // This is because you may have a class `A` that defines some set of properties, and another class `B`
25832                    // that defines the same set of properties as class `A`, in that case they are structurally the same
25833                    // type, but when you do something like `instanceOfA.constructor === B` it will return false.
25834                    if (source.flags & TypeFlags.Object && getObjectFlags(source) & ObjectFlags.Class ||
25835                        target.flags & TypeFlags.Object && getObjectFlags(target) & ObjectFlags.Class) {
25836                        return source.symbol === target.symbol;
25837                    }
25838
25839                    // For all other types just check that the `source` type is a subtype of the `target` type.
25840                    return isTypeSubtypeOf(source, target);
25841                }
25842            }
25843
25844            function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
25845                const left = getReferenceCandidate(expr.left);
25846                if (!isMatchingReference(reference, left)) {
25847                    if (assumeTrue && strictNullChecks && optionalChainContainsReference(left, reference)) {
25848                        return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
25849                    }
25850                    return type;
25851                }
25852
25853                // Check that right operand is a function type with a prototype property
25854                const rightType = getTypeOfExpression(expr.right);
25855                if (!isTypeDerivedFrom(rightType, globalFunctionType)) {
25856                    return type;
25857                }
25858
25859                let targetType: Type | undefined;
25860                const prototypeProperty = getPropertyOfType(rightType, "prototype" as __String);
25861                if (prototypeProperty) {
25862                    // Target type is type of the prototype property
25863                    const prototypePropertyType = getTypeOfSymbol(prototypeProperty);
25864                    if (!isTypeAny(prototypePropertyType)) {
25865                        targetType = prototypePropertyType;
25866                    }
25867                }
25868
25869                // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function'
25870                if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) {
25871                    return type;
25872                }
25873
25874                if (!targetType) {
25875                    const constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
25876                    targetType = constructSignatures.length ?
25877                        getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))) :
25878                        emptyObjectType;
25879                }
25880
25881                // We can't narrow a union based off instanceof without negated types see #31576 for more info
25882                if (!assumeTrue && rightType.flags & TypeFlags.Union) {
25883                    const nonConstructorTypeInUnion = find((rightType as UnionType).types, (t) => !isConstructorType(t));
25884                    if (!nonConstructorTypeInUnion) return type;
25885                }
25886
25887                return getNarrowedType(type, targetType, assumeTrue, /*checkDerived*/ true);
25888            }
25889
25890            function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean) {
25891                const key = type.flags & TypeFlags.Union ? `N${getTypeId(type)},${getTypeId(candidate)},${(assumeTrue ? 1 : 0) | (checkDerived ? 2 : 0)}` : undefined;
25892                return getCachedType(key) ?? setCachedType(key, getNarrowedTypeWorker(type, candidate, assumeTrue, checkDerived));
25893            }
25894
25895            function getNarrowedTypeWorker(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean) {
25896                const isRelated = checkDerived ? isTypeDerivedFrom : isTypeSubtypeOf;
25897                if (!assumeTrue) {
25898                    return filterType(type, t => !isRelated(t, candidate));
25899                }
25900                if (type.flags & TypeFlags.AnyOrUnknown) {
25901                    return candidate;
25902                }
25903                // We first attempt to filter the current type, narrowing constituents as appropriate and removing
25904                // constituents that are unrelated to the candidate.
25905                const keyPropertyName = type.flags & TypeFlags.Union ? getKeyPropertyName(type as UnionType) : undefined;
25906                const narrowedType = mapType(candidate, c => {
25907                    // If a discriminant property is available, use that to reduce the type.
25908                    const discriminant = keyPropertyName && getTypeOfPropertyOfType(c, keyPropertyName);
25909                    const matching = discriminant && getConstituentTypeForKeyType(type as UnionType, discriminant);
25910                    // For each constituent t in the current type, if t and and c are directly related, pick the most
25911                    // specific of the two. When t and c are related in both directions, we prefer c for type predicates
25912                    // because that is the asserted type, but t for `instanceof` because generics aren't reflected in
25913                    // prototype object types.
25914                    const directlyRelated = mapType(matching || type, checkDerived ?
25915                        t => isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType :
25916                        t => isTypeSubtypeOf(c, t) ? c : isTypeSubtypeOf(t, c) ? t : neverType);
25917                    // If no constituents are directly related, create intersections for any generic constituents that
25918                    // are related by constraint.
25919                    return directlyRelated.flags & TypeFlags.Never ?
25920                        mapType(type, t => maybeTypeOfKind(t, TypeFlags.Instantiable) && isRelated(c, getBaseConstraintOfType(t) || unknownType) ? getIntersectionType([t, c]) : neverType) :
25921                        directlyRelated;
25922                });
25923                // If filtering produced a non-empty type, return that. Otherwise, pick the most specific of the two
25924                // based on assignability, or as a last resort produce an intersection.
25925                return !(narrowedType.flags & TypeFlags.Never) ? narrowedType :
25926                    isTypeSubtypeOf(candidate, type) ? candidate :
25927                    isTypeAssignableTo(type, candidate) ? type :
25928                    isTypeAssignableTo(candidate, type) ? candidate :
25929                    getIntersectionType([type, candidate]);
25930            }
25931
25932            function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
25933                if (hasMatchingArgument(callExpression, reference)) {
25934                    const signature = assumeTrue || !isCallChain(callExpression) ? getEffectsSignature(callExpression) : undefined;
25935                    const predicate = signature && getTypePredicateOfSignature(signature);
25936                    if (predicate && (predicate.kind === TypePredicateKind.This || predicate.kind === TypePredicateKind.Identifier)) {
25937                        return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue);
25938                    }
25939                }
25940                if (containsMissingType(type) && isAccessExpression(reference) && isPropertyAccessExpression(callExpression.expression)) {
25941                    const callAccess = callExpression.expression;
25942                    if (isMatchingReference(reference.expression, getReferenceCandidate(callAccess.expression)) &&
25943                        isIdentifier(callAccess.name) && callAccess.name.escapedText === "hasOwnProperty" && callExpression.arguments.length === 1) {
25944                        const argument = callExpression.arguments[0];
25945                        if (isStringLiteralLike(argument) && getAccessedPropertyName(reference) === escapeLeadingUnderscores(argument.text)) {
25946                            return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined);
25947                        }
25948                    }
25949                }
25950                return type;
25951            }
25952
25953            function narrowTypeByTypePredicate(type: Type, predicate: TypePredicate, callExpression: CallExpression, assumeTrue: boolean): Type {
25954                // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function'
25955                if (predicate.type && !(isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType))) {
25956                    const predicateArgument = getTypePredicateArgument(predicate, callExpression);
25957                    if (predicateArgument) {
25958                        if (isMatchingReference(reference, predicateArgument)) {
25959                            return getNarrowedType(type, predicate.type, assumeTrue, /*checkDerived*/ false);
25960                        }
25961                        if (strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) &&
25962                            !(getTypeFacts(predicate.type) & TypeFacts.EQUndefined)) {
25963                            type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
25964                        }
25965                        const access = getDiscriminantPropertyAccess(predicateArgument, type);
25966                        if (access) {
25967                            return narrowTypeByDiscriminant(type, access, t => getNarrowedType(t, predicate.type!, assumeTrue, /*checkDerived*/ false));
25968                        }
25969                    }
25970                }
25971                return type;
25972            }
25973
25974            // Narrow the given type based on the given expression having the assumed boolean value. The returned type
25975            // will be a subtype or the same type as the argument.
25976            function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type {
25977                // for `a?.b`, we emulate a synthetic `a !== null && a !== undefined` condition for `a`
25978                if (isExpressionOfOptionalChainRoot(expr) ||
25979                    isBinaryExpression(expr.parent) && expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken && expr.parent.left === expr) {
25980                    return narrowTypeByOptionality(type, expr, assumeTrue);
25981                }
25982                switch (expr.kind) {
25983                    case SyntaxKind.Identifier:
25984                        // When narrowing a reference to a const variable, non-assigned parameter, or readonly property, we inline
25985                        // up to five levels of aliased conditional expressions that are themselves declared as const variables.
25986                        if (!isMatchingReference(reference, expr) && inlineLevel < 5) {
25987                            const symbol = getResolvedSymbol(expr as Identifier);
25988                            if (isConstVariable(symbol)) {
25989                                const declaration = symbol.valueDeclaration;
25990                                if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isConstantReference(reference)) {
25991                                    inlineLevel++;
25992                                    const result = narrowType(type, declaration.initializer, assumeTrue);
25993                                    inlineLevel--;
25994                                    return result;
25995                                }
25996                            }
25997                        }
25998                        // falls through
25999                    case SyntaxKind.ThisKeyword:
26000                    case SyntaxKind.SuperKeyword:
26001                    case SyntaxKind.PropertyAccessExpression:
26002                    case SyntaxKind.ElementAccessExpression:
26003                        return narrowTypeByTruthiness(type, expr, assumeTrue);
26004                    case SyntaxKind.CallExpression:
26005                        return narrowTypeByCallExpression(type, expr as CallExpression, assumeTrue);
26006                    case SyntaxKind.ParenthesizedExpression:
26007                    case SyntaxKind.NonNullExpression:
26008                        return narrowType(type, (expr as ParenthesizedExpression | NonNullExpression).expression, assumeTrue);
26009                    case SyntaxKind.BinaryExpression:
26010                        return narrowTypeByBinaryExpression(type, expr as BinaryExpression, assumeTrue);
26011                    case SyntaxKind.PrefixUnaryExpression:
26012                        if ((expr as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken) {
26013                            return narrowType(type, (expr as PrefixUnaryExpression).operand, !assumeTrue);
26014                        }
26015                        break;
26016                }
26017                return type;
26018            }
26019
26020            function narrowTypeByOptionality(type: Type, expr: Expression, assumePresent: boolean): Type {
26021                if (isMatchingReference(reference, expr)) {
26022                    return getAdjustedTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull);
26023                }
26024                const access = getDiscriminantPropertyAccess(expr, type);
26025                if (access) {
26026                    return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull));
26027                }
26028                return type;
26029            }
26030        }
26031
26032        function getTypeOfSymbolAtLocation(symbol: Symbol, location: Node) {
26033            symbol = symbol.exportSymbol || symbol;
26034
26035            // If we have an identifier or a property access at the given location, if the location is
26036            // an dotted name expression, and if the location is not an assignment target, obtain the type
26037            // of the expression (which will reflect control flow analysis). If the expression indeed
26038            // resolved to the given symbol, return the narrowed type.
26039            if (location.kind === SyntaxKind.Identifier || location.kind === SyntaxKind.PrivateIdentifier) {
26040                if (isRightSideOfQualifiedNameOrPropertyAccess(location)) {
26041                    location = location.parent;
26042                }
26043                if (isExpressionNode(location) && (!isAssignmentTarget(location) || isWriteAccess(location))) {
26044                    const type = getTypeOfExpression(location as Expression);
26045                    if (getExportSymbolOfValueSymbolIfExported(getNodeLinks(location).resolvedSymbol) === symbol) {
26046                        return type;
26047                    }
26048                }
26049            }
26050            if (isDeclarationName(location) && isSetAccessor(location.parent) && getAnnotatedAccessorTypeNode(location.parent)) {
26051                return getWriteTypeOfAccessors(location.parent.symbol);
26052            }
26053            // The location isn't a reference to the given symbol, meaning we're being asked
26054            // a hypothetical question of what type the symbol would have if there was a reference
26055            // to it at the given location. Since we have no control flow information for the
26056            // hypothetical reference (control flow information is created and attached by the
26057            // binder), we simply return the declared type of the symbol.
26058            return getNonMissingTypeOfSymbol(symbol);
26059        }
26060
26061        function getControlFlowContainer(node: Node): Node {
26062            return findAncestor(node.parent, node =>
26063                isFunctionLike(node) && !getImmediatelyInvokedFunctionExpression(node) ||
26064                node.kind === SyntaxKind.ModuleBlock ||
26065                node.kind === SyntaxKind.SourceFile ||
26066                node.kind === SyntaxKind.PropertyDeclaration ||
26067                node.kind === SyntaxKind.AnnotationPropertyDeclaration)!;
26068            }
26069
26070        // Check if a parameter or catch variable is assigned anywhere
26071        function isSymbolAssigned(symbol: Symbol) {
26072            if (!symbol.valueDeclaration) {
26073                return false;
26074            }
26075            const parent = getRootDeclaration(symbol.valueDeclaration).parent;
26076            const links = getNodeLinks(parent);
26077            if (!(links.flags & NodeCheckFlags.AssignmentsMarked)) {
26078                links.flags |= NodeCheckFlags.AssignmentsMarked;
26079                if (!hasParentWithAssignmentsMarked(parent)) {
26080                    markNodeAssignments(parent);
26081                }
26082            }
26083            return symbol.isAssigned || false;
26084        }
26085
26086        function hasParentWithAssignmentsMarked(node: Node) {
26087            return !!findAncestor(node.parent, node =>
26088                (isFunctionLike(node) || isCatchClause(node)) && !!(getNodeLinks(node).flags & NodeCheckFlags.AssignmentsMarked));
26089        }
26090
26091        function markNodeAssignments(node: Node) {
26092            if (node.kind === SyntaxKind.Identifier) {
26093                if (isAssignmentTarget(node)) {
26094                    const symbol = getResolvedSymbol(node as Identifier);
26095                    if (isParameterOrCatchClauseVariable(symbol)) {
26096                        symbol.isAssigned = true;
26097                    }
26098                }
26099            }
26100            else {
26101                forEachChild(node, markNodeAssignments);
26102            }
26103        }
26104
26105        function isConstVariable(symbol: Symbol) {
26106            return symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0;
26107        }
26108
26109        /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */
26110        function removeOptionalityFromDeclaredType(declaredType: Type, declaration: VariableLikeDeclaration): Type {
26111            if (pushTypeResolution(declaration.symbol, TypeSystemPropertyName.DeclaredType)) {
26112                const annotationIncludesUndefined = strictNullChecks &&
26113                    declaration.kind === SyntaxKind.Parameter &&
26114                    declaration.initializer &&
26115                    getTypeFacts(declaredType) & TypeFacts.IsUndefined &&
26116                    !(getTypeFacts(checkExpression(declaration.initializer)) & TypeFacts.IsUndefined);
26117                popTypeResolution();
26118
26119                return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType;
26120            }
26121            else {
26122                reportCircularityError(declaration.symbol);
26123                return declaredType;
26124            }
26125        }
26126
26127        function isConstraintPosition(type: Type, node: Node) {
26128            const parent = node.parent;
26129            // In an element access obj[x], we consider obj to be in a constraint position, except when obj is of
26130            // a generic type without a nullable constraint and x is a generic type. This is because when both obj
26131            // and x are of generic types T and K, we want the resulting type to be T[K].
26132            return parent.kind === SyntaxKind.PropertyAccessExpression ||
26133                parent.kind === SyntaxKind.QualifiedName ||
26134                parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node ||
26135                parent.kind === SyntaxKind.ElementAccessExpression && (parent as ElementAccessExpression).expression === node &&
26136                    !(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression)));
26137        }
26138
26139        function isGenericTypeWithUnionConstraint(type: Type): boolean {
26140            return type.flags & TypeFlags.Intersection ?
26141                some((type as IntersectionType).types, isGenericTypeWithUnionConstraint) :
26142                !!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union));
26143        }
26144
26145        function isGenericTypeWithoutNullableConstraint(type: Type): boolean {
26146            return type.flags & TypeFlags.Intersection ?
26147                some((type as IntersectionType).types, isGenericTypeWithoutNullableConstraint) :
26148                !!(type.flags & TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable));
26149        }
26150
26151        function hasContextualTypeWithNoGenericTypes(node: Node, checkMode: CheckMode | undefined) {
26152            // Computing the contextual type for a child of a JSX element involves resolving the type of the
26153            // element's tag name, so we exclude that here to avoid circularities.
26154            // If check mode has `CheckMode.RestBindingElement`, we skip binding pattern contextual types,
26155            // as we want the type of a rest element to be generic when possible.
26156            const contextualType = (isIdentifier(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node)) &&
26157                !((isJsxOpeningElement(node.parent) || isJsxSelfClosingElement(node.parent)) && node.parent.tagName === node) &&
26158                (checkMode && checkMode & CheckMode.RestBindingElement ?
26159                    getContextualType(node, ContextFlags.SkipBindingPatterns)
26160                    : getContextualType(node, /*contextFlags*/ undefined));
26161            return contextualType && !isGenericType(contextualType);
26162        }
26163
26164        function getNarrowableTypeForReference(type: Type, reference: Node, checkMode?: CheckMode) {
26165            // When the type of a reference is or contains an instantiable type with a union type constraint, and
26166            // when the reference is in a constraint position (where it is known we'll obtain the apparent type) or
26167            // has a contextual type containing no top-level instantiables (meaning constraints will determine
26168            // assignability), we substitute constraints for all instantiables in the type of the reference to give
26169            // control flow analysis an opportunity to narrow it further. For example, for a reference of a type
26170            // parameter type 'T extends string | undefined' with a contextual type 'string', we substitute
26171            // 'string | undefined' to give control flow analysis the opportunity to narrow to type 'string'.
26172            const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) &&
26173                someType(type, isGenericTypeWithUnionConstraint) &&
26174                (isConstraintPosition(type, reference) || hasContextualTypeWithNoGenericTypes(reference, checkMode));
26175            return substituteConstraints ? mapType(type, getBaseConstraintOrType) : type;
26176        }
26177
26178        function isExportOrExportExpression(location: Node) {
26179            return !!findAncestor(location, n => {
26180                const parent = n.parent;
26181                if (parent === undefined) {
26182                    return "quit";
26183                }
26184                if (isExportAssignment(parent)) {
26185                    return parent.expression === n && isEntityNameExpression(n);
26186                }
26187                if (isExportSpecifier(parent)) {
26188                    return parent.name === n || parent.propertyName === n;
26189                }
26190                return false;
26191            });
26192        }
26193
26194        function markAliasReferenced(symbol: Symbol, location: Node) {
26195            if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) {
26196                const target = resolveAlias(symbol);
26197                if (getAllSymbolFlags(target) & (SymbolFlags.Value | SymbolFlags.ExportValue)) {
26198                    // An alias resolving to a const enum cannot be elided if (1) 'isolatedModules' is enabled
26199                    // (because the const enum value will not be inlined), or if (2) the alias is an export
26200                    // of a const enum declaration that will be preserved.
26201                    if (compilerOptions.isolatedModules ||
26202                        shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(location) ||
26203                        !isConstEnumOrConstEnumOnlyModule(getExportSymbolOfValueSymbolIfExported(target))
26204                    ) {
26205                        markAliasSymbolAsReferenced(symbol);
26206                    }
26207                    else {
26208                        markConstEnumAliasAsReferenced(symbol);
26209                    }
26210                }
26211            }
26212        }
26213
26214        function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier) {
26215            const declaration = symbol.valueDeclaration;
26216            if (declaration) {
26217                // If we have a non-rest binding element with no initializer declared as a const variable or a const-like
26218                // parameter (a parameter for which there are no assignments in the function body), and if the parent type
26219                // for the destructuring is a union type, one or more of the binding elements may represent discriminant
26220                // properties, and we want the effects of conditional checks on such discriminants to affect the types of
26221                // other binding elements from the same destructuring. Consider:
26222                //
26223                //   type Action =
26224                //       | { kind: 'A', payload: number }
26225                //       | { kind: 'B', payload: string };
26226                //
26227                //   function f({ kind, payload }: Action) {
26228                //       if (kind === 'A') {
26229                //           payload.toFixed();
26230                //       }
26231                //       if (kind === 'B') {
26232                //           payload.toUpperCase();
26233                //       }
26234                //   }
26235                //
26236                // Above, we want the conditional checks on 'kind' to affect the type of 'payload'. To facilitate this, we use
26237                // the binding pattern AST instance for '{ kind, payload }' as a pseudo-reference and narrow this reference
26238                // as if it occurred in the specified location. We then recompute the narrowed binding element type by
26239                // destructuring from the narrowed parent type.
26240                if (isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) {
26241                    const parent = declaration.parent.parent;
26242                    if (parent.kind === SyntaxKind.VariableDeclaration && getCombinedNodeFlags(declaration) & NodeFlags.Const || parent.kind === SyntaxKind.Parameter) {
26243                        const links = getNodeLinks(parent);
26244                        if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) {
26245                            links.flags |= NodeCheckFlags.InCheckIdentifier;
26246                            const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal);
26247                            const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType);
26248                            links.flags &= ~NodeCheckFlags.InCheckIdentifier;
26249                            if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) {
26250                                const pattern = declaration.parent;
26251                                const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode);
26252                                if (narrowedType.flags & TypeFlags.Never) {
26253                                    return neverType;
26254                                }
26255                                return getBindingElementTypeFromParentType(declaration, narrowedType);
26256                            }
26257                        }
26258                    }
26259                }
26260                // If we have a const-like parameter with no type annotation or initializer, and if the parameter is contextually
26261                // typed by a signature with a single rest parameter of a union of tuple types, one or more of the parameters may
26262                // represent discriminant tuple elements, and we want the effects of conditional checks on such discriminants to
26263                // affect the types of other parameters in the same parameter list. Consider:
26264                //
26265                //   type Action = [kind: 'A', payload: number] | [kind: 'B', payload: string];
26266                //
26267                //   const f: (...args: Action) => void = (kind, payload) => {
26268                //       if (kind === 'A') {
26269                //           payload.toFixed();
26270                //       }
26271                //       if (kind === 'B') {
26272                //           payload.toUpperCase();
26273                //       }
26274                //   }
26275                //
26276                // Above, we want the conditional checks on 'kind' to affect the type of 'payload'. To facilitate this, we use
26277                // the arrow function AST node for '(kind, payload) => ...' as a pseudo-reference and narrow this reference as
26278                // if it occurred in the specified location. We then recompute the narrowed parameter type by indexing into the
26279                // narrowed tuple type.
26280                if (isParameter(declaration) && !declaration.type && !declaration.initializer && !declaration.dotDotDotToken) {
26281                    const func = declaration.parent;
26282                    if (func.parameters.length >= 2 && isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
26283                        const contextualSignature = getContextualSignature(func);
26284                        if (contextualSignature && contextualSignature.parameters.length === 1 && signatureHasRestParameter(contextualSignature)) {
26285                            const restType = getReducedApparentType(getTypeOfSymbol(contextualSignature.parameters[0]));
26286                            if (restType.flags & TypeFlags.Union && everyType(restType, isTupleType) && !isSymbolAssigned(symbol)) {
26287                                const narrowedType = getFlowTypeOfReference(func, restType, restType, /*flowContainer*/ undefined, location.flowNode);
26288                                const index = func.parameters.indexOf(declaration) - (getThisParameter(func) ? 1 : 0);
26289                                return getIndexedAccessType(narrowedType, getNumberLiteralType(index));
26290                            }
26291                        }
26292                    }
26293                }
26294            }
26295            return getTypeOfSymbol(symbol);
26296        }
26297
26298        function checkIdentifier(node: Identifier, checkMode: CheckMode | undefined): Type {
26299            if (isThisInTypeQuery(node)) {
26300                return checkThisExpression(node);
26301            }
26302
26303            const symbol = getResolvedSymbol(node);
26304            if (symbol === unknownSymbol) {
26305                return errorType;
26306            }
26307
26308            // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects.
26309            // Although in down-level emit of arrow function, we emit it using function expression which means that
26310            // arguments objects will be bound to the inner object; emitting arrow function natively in ES6, arguments objects
26311            // will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior.
26312            // To avoid that we will give an error to users if they use arguments objects in arrow function so that they
26313            // can explicitly bound arguments objects
26314            if (symbol === argumentsSymbol) {
26315                if (isInPropertyInitializerOrClassStaticBlock(node)) {
26316                    error(node, Diagnostics.arguments_cannot_be_referenced_in_property_initializers);
26317                    return errorType;
26318                }
26319
26320                const container = getContainingFunction(node)!;
26321                if (languageVersion < ScriptTarget.ES2015) {
26322                    if (container.kind === SyntaxKind.ArrowFunction) {
26323                        error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
26324                    }
26325                    else if (hasSyntacticModifier(container, ModifierFlags.Async)) {
26326                        error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method);
26327                    }
26328                }
26329
26330                getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
26331                checkIdentifierJsDoc(node, symbol);
26332                return getTypeOfSymbol(symbol);
26333            }
26334
26335            if (shouldMarkIdentifierAliasReferenced(node)) {
26336                markAliasReferenced(symbol, node);
26337            }
26338
26339            const localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol);
26340            const targetSymbol = checkDeprecatedAliasedSymbol(localOrExportSymbol, node);
26341            checkIdentifierJsDoc(node, targetSymbol);
26342            if (isDeprecatedSymbol(targetSymbol) && isUncalledFunctionReference(node, targetSymbol) && targetSymbol.declarations) {
26343                addDeprecatedSuggestion(node, targetSymbol.declarations, node.escapedText as string);
26344            }
26345
26346            let declaration = localOrExportSymbol.valueDeclaration;
26347            if (declaration && localOrExportSymbol.flags & SymbolFlags.Class) {
26348                // Due to the emit for class decorators, any reference to the class from inside of the class body
26349                // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
26350                // behavior of class names in ES6.
26351                if (declaration.kind === SyntaxKind.ClassDeclaration
26352                    && nodeIsDecorated(declaration as ClassDeclaration)) {
26353                    let container = getContainingClass(node);
26354                    while (container !== undefined) {
26355                        if (container === declaration && container.name !== node) {
26356                            getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference;
26357                            getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass;
26358                            break;
26359                        }
26360
26361                        container = getContainingClass(container);
26362                    }
26363                }
26364                else if (declaration.kind === SyntaxKind.ClassExpression) {
26365                    // When we emit a class expression with static members that contain a reference
26366                    // to the constructor in the initializer, we will need to substitute that
26367                    // binding with an alias as the class name is not in scope.
26368                    let container = getThisContainer(node, /*includeArrowFunctions*/ false);
26369                    while (container.kind !== SyntaxKind.SourceFile) {
26370                        if (container.parent === declaration) {
26371                            if (isPropertyDeclaration(container) && isStatic(container) || isClassStaticBlockDeclaration(container)) {
26372                                getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference;
26373                                getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass;
26374                            }
26375                            break;
26376                        }
26377
26378                        container = getThisContainer(container, /*includeArrowFunctions*/ false);
26379                    }
26380                }
26381            }
26382
26383            checkNestedBlockScopedBinding(node, symbol);
26384
26385            let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node);
26386            const assignmentKind = getAssignmentTargetKind(node);
26387
26388            if ((localOrExportSymbol.flags & SymbolFlags.Annotation) &&
26389                !findAncestor(node, isAnnotationDeclaration) &&
26390                !findAncestor(node, isAnnotation) &&
26391                !findAncestor(node, isDecorator) &&
26392                !findAncestor(node, isImportDeclaration) &&
26393                !findAncestor(node, isExportDeclaration) &&
26394                !findAncestor(node, isExportAssignment)) {
26395                error(node, Diagnostics.Annotation_cannot_be_used_as_type_or_variable_or_function_or_method);
26396                return errorType;
26397            }
26398
26399            if (assignmentKind) {
26400                if (!(localOrExportSymbol.flags & SymbolFlags.Variable) &&
26401                    !(isInJSFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) {
26402                    const assignmentError = localOrExportSymbol.flags & SymbolFlags.Enum ? Diagnostics.Cannot_assign_to_0_because_it_is_an_enum
26403                        : localOrExportSymbol.flags & SymbolFlags.Class ? Diagnostics.Cannot_assign_to_0_because_it_is_a_class
26404                        : localOrExportSymbol.flags & SymbolFlags.Module ? Diagnostics.Cannot_assign_to_0_because_it_is_a_namespace
26405                        : localOrExportSymbol.flags & SymbolFlags.Function ? Diagnostics.Cannot_assign_to_0_because_it_is_a_function
26406                        : localOrExportSymbol.flags & SymbolFlags.Alias ? Diagnostics.Cannot_assign_to_0_because_it_is_an_import
26407                        : Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable;
26408
26409                    error(node, assignmentError, symbolToString(symbol));
26410                    return errorType;
26411                }
26412                if (isReadonlySymbol(localOrExportSymbol)) {
26413                    if (localOrExportSymbol.flags & SymbolFlags.Variable) {
26414                        error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant, symbolToString(symbol));
26415                    }
26416                    else {
26417                        error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(symbol));
26418                    }
26419                    return errorType;
26420                }
26421            }
26422
26423            const isAlias = localOrExportSymbol.flags & SymbolFlags.Alias;
26424
26425            // We only narrow variables and parameters occurring in a non-assignment position. For all other
26426            // entities we simply return the declared type.
26427            if (localOrExportSymbol.flags & SymbolFlags.Variable) {
26428                if (assignmentKind === AssignmentKind.Definite) {
26429                    return type;
26430                }
26431            }
26432            else if (isAlias) {
26433                declaration = getDeclarationOfAliasSymbol(symbol);
26434            }
26435            else {
26436                return type;
26437            }
26438
26439            if (!declaration) {
26440                return type;
26441            }
26442
26443            type = getNarrowableTypeForReference(type, node, checkMode);
26444
26445            // The declaration container is the innermost function that encloses the declaration of the variable
26446            // or parameter. The flow container is the innermost function starting with which we analyze the control
26447            // flow graph to determine the control flow based type.
26448            const isParameter = getRootDeclaration(declaration).kind === SyntaxKind.Parameter;
26449            const declarationContainer = getControlFlowContainer(declaration);
26450            let flowContainer = getControlFlowContainer(node);
26451            const isOuterVariable = flowContainer !== declarationContainer;
26452            const isSpreadDestructuringAssignmentTarget = node.parent && node.parent.parent && isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent);
26453            const isModuleExports = symbol.flags & SymbolFlags.ModuleExports;
26454            // When the control flow originates in a function expression or arrow function and we are referencing
26455            // a const variable or parameter from an outer function, we extend the origin of the control flow
26456            // analysis to include the immediately enclosing function.
26457            while (flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression ||
26458                flowContainer.kind === SyntaxKind.ArrowFunction || isObjectLiteralOrClassExpressionMethodOrAccessor(flowContainer)) &&
26459                (isConstVariable(localOrExportSymbol) && type !== autoArrayType || isParameter && !isSymbolAssigned(localOrExportSymbol))) {
26460                flowContainer = getControlFlowContainer(flowContainer);
26461            }
26462            // We only look for uninitialized variables in strict null checking mode, and only when we can analyze
26463            // the entire control flow graph from the variable's declaration (i.e. when the flow container and
26464            // declaration container are the same).
26465            const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) ||
26466                type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 ||
26467                isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) ||
26468                node.parent.kind === SyntaxKind.NonNullExpression ||
26469                declaration.kind === SyntaxKind.VariableDeclaration && (declaration as VariableDeclaration).exclamationToken ||
26470                declaration.flags & NodeFlags.Ambient;
26471            const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) :
26472                type === autoType || type === autoArrayType ? undefinedType :
26473                getOptionalType(type);
26474            const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer);
26475            // A variable is considered uninitialized when it is possible to analyze the entire control flow graph
26476            // from declaration to use, and when the variable's declared type doesn't include undefined but the
26477            // control flow based type does include undefined.
26478            if (!isEvolvingArrayOperationTarget(node) && (type === autoType || type === autoArrayType)) {
26479                if (flowType === autoType || flowType === autoArrayType) {
26480                    if (noImplicitAny) {
26481                        error(getNameOfDeclaration(declaration), Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
26482                        error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
26483                    }
26484                    return convertAutoToAny(flowType);
26485                }
26486            }
26487            else if (!assumeInitialized && !containsUndefinedType(type) && containsUndefinedType(flowType)) {
26488                error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
26489                // Return the declared type to reduce follow-on errors
26490                return type;
26491            }
26492            return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
26493        }
26494
26495        function isSameScopedBindingElement(node: Identifier, declaration: Declaration) {
26496            if (isBindingElement(declaration)) {
26497                const bindingElement = findAncestor(node, isBindingElement);
26498                return bindingElement && getRootDeclaration(bindingElement) === getRootDeclaration(declaration);
26499            }
26500        }
26501
26502        function shouldMarkIdentifierAliasReferenced(node: Identifier): boolean {
26503            const parent = node.parent;
26504            if (parent) {
26505                // A property access expression LHS? checkPropertyAccessExpression will handle that.
26506                if (isPropertyAccessExpression(parent) && parent.expression === node) {
26507                    return false;
26508                }
26509                // Next two check for an identifier inside a type only export.
26510                if (isExportSpecifier(parent) && parent.isTypeOnly) {
26511                    return false;
26512                }
26513                const greatGrandparent = parent.parent?.parent;
26514                if (greatGrandparent && isExportDeclaration(greatGrandparent) && greatGrandparent.isTypeOnly) {
26515                    return false;
26516                }
26517            }
26518            return true;
26519        }
26520
26521        function isInsideFunctionOrInstancePropertyInitializer(node: Node, threshold: Node): boolean {
26522            return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n) || (
26523                n.parent && isPropertyDeclaration(n.parent) && !hasStaticModifier(n.parent) && n.parent.initializer === n
26524            ));
26525        }
26526
26527        function getPartOfForStatementContainingNode(node: Node, container: ForStatement) {
26528            return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement);
26529        }
26530
26531        function getEnclosingIterationStatement(node: Node): Node | undefined {
26532            return findAncestor(node, n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" : isIterationStatement(n, /*lookInLabeledStatements*/ false));
26533        }
26534
26535        function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void {
26536            if (languageVersion >= ScriptTarget.ES2015 ||
26537                (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 ||
26538                !symbol.valueDeclaration ||
26539                isSourceFile(symbol.valueDeclaration) ||
26540                symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) {
26541                return;
26542            }
26543
26544            // 1. walk from the use site up to the declaration and check
26545            // if there is anything function like between declaration and use-site (is binding/class is captured in function).
26546            // 2. walk from the declaration up to the boundary of lexical environment and check
26547            // if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement)
26548
26549            const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
26550            const isCaptured = isInsideFunctionOrInstancePropertyInitializer(node, container);
26551
26552            const enclosingIterationStatement = getEnclosingIterationStatement(container);
26553            if (enclosingIterationStatement) {
26554                if (isCaptured) {
26555                    // mark iteration statement as containing block-scoped binding captured in some function
26556                    let capturesBlockScopeBindingInLoopBody = true;
26557                    if (isForStatement(container)) {
26558                        const varDeclList = getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
26559                        if (varDeclList && varDeclList.parent === container) {
26560                            const part = getPartOfForStatementContainingNode(node.parent, container);
26561                            if (part) {
26562                                const links = getNodeLinks(part);
26563                                links.flags |= NodeCheckFlags.ContainsCapturedBlockScopeBinding;
26564
26565                                const capturedBindings = links.capturedBlockScopeBindings || (links.capturedBlockScopeBindings = []);
26566                                pushIfUnique(capturedBindings, symbol);
26567
26568                                if (part === container.initializer) {
26569                                    capturesBlockScopeBindingInLoopBody = false; // Initializer is outside of loop body
26570                                }
26571                            }
26572                        }
26573                    }
26574                    if (capturesBlockScopeBindingInLoopBody) {
26575                        getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
26576                    }
26577                }
26578
26579                // mark variables that are declared in loop initializer and reassigned inside the body of ForStatement.
26580                // if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back.
26581                if (isForStatement(container)) {
26582                    const varDeclList = getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
26583                    if (varDeclList && varDeclList.parent === container && isAssignedInBodyOfForStatement(node, container)) {
26584                        getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.NeedsLoopOutParameter;
26585                    }
26586                }
26587
26588                // set 'declared inside loop' bit on the block-scoped binding
26589                getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
26590            }
26591
26592            if (isCaptured) {
26593                getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.CapturedBlockScopedBinding;
26594            }
26595        }
26596
26597        function isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement) {
26598            const links = getNodeLinks(node);
26599            return !!links && contains(links.capturedBlockScopeBindings, getSymbolOfNode(decl));
26600        }
26601
26602        function isAssignedInBodyOfForStatement(node: Identifier, container: ForStatement): boolean {
26603            // skip parenthesized nodes
26604            let current: Node = node;
26605            while (current.parent.kind === SyntaxKind.ParenthesizedExpression) {
26606                current = current.parent;
26607            }
26608
26609            // check if node is used as LHS in some assignment expression
26610            let isAssigned = false;
26611            if (isAssignmentTarget(current)) {
26612                isAssigned = true;
26613            }
26614            else if ((current.parent.kind === SyntaxKind.PrefixUnaryExpression || current.parent.kind === SyntaxKind.PostfixUnaryExpression)) {
26615                const expr = current.parent as PrefixUnaryExpression | PostfixUnaryExpression;
26616                isAssigned = expr.operator === SyntaxKind.PlusPlusToken || expr.operator === SyntaxKind.MinusMinusToken;
26617            }
26618
26619            if (!isAssigned) {
26620                return false;
26621            }
26622
26623            // at this point we know that node is the target of assignment
26624            // now check that modification happens inside the statement part of the ForStatement
26625            return !!findAncestor(current, n => n === container ? "quit" : n === container.statement);
26626        }
26627
26628        function captureLexicalThis(node: Node, container: Node): void {
26629            getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis;
26630            if (container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.Constructor) {
26631                const classNode = container.parent;
26632                getNodeLinks(classNode).flags |= NodeCheckFlags.CaptureThis;
26633            }
26634            else {
26635                getNodeLinks(container).flags |= NodeCheckFlags.CaptureThis;
26636            }
26637        }
26638
26639        function findFirstSuperCall(node: Node): SuperCall | undefined {
26640            return isSuperCall(node) ? node :
26641                isFunctionLike(node) ? undefined :
26642                forEachChild(node, findFirstSuperCall);
26643        }
26644
26645        /**
26646         * Check if the given class-declaration extends null then return true.
26647         * Otherwise, return false
26648         * @param classDecl a class declaration to check if it extends null
26649         */
26650        function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean {
26651            const classSymbol = getSymbolOfNode(classDecl);
26652            const classInstanceType = getDeclaredTypeOfSymbol(classSymbol) as InterfaceType;
26653            const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType);
26654
26655            return baseConstructorType === nullWideningType;
26656        }
26657
26658        function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) {
26659            const containingClassDecl = container.parent as ClassDeclaration;
26660            const baseTypeNode = getClassExtendsHeritageElement(containingClassDecl);
26661
26662            // If a containing class does not have extends clause or the class extends null
26663            // skip checking whether super statement is called before "this" accessing.
26664            if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
26665                if (node.flowNode && !isPostSuperFlowNode(node.flowNode, /*noCacheCheck*/ false)) {
26666                    error(node, diagnosticMessage);
26667                }
26668            }
26669        }
26670
26671        function checkThisInStaticClassFieldInitializerInDecoratedClass(thisExpression: Node, container: Node) {
26672            if (isPropertyDeclaration(container) && hasStaticModifier(container) &&
26673                container.initializer && textRangeContainsPositionInclusive(container.initializer, thisExpression.pos) && hasDecorators(container.parent)) {
26674                    error(thisExpression, Diagnostics.Cannot_use_this_in_a_static_property_initializer_of_a_decorated_class);
26675            }
26676        }
26677
26678        function checkThisExpression(node: Node): Type {
26679            const isNodeInTypeQuery = isInTypeQuery(node);
26680            // Stop at the first arrow function so that we can
26681            // tell whether 'this' needs to be captured.
26682            let container = getThisContainer(node, /* includeArrowFunctions */ true);
26683            let capturedByArrowFunction = false;
26684
26685            if (container.kind === SyntaxKind.Constructor) {
26686                checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
26687            }
26688
26689            // Now skip arrow functions to get the "real" owner of 'this'.
26690            if (container.kind === SyntaxKind.ArrowFunction) {
26691                container = getThisContainer(container, /* includeArrowFunctions */ false);
26692                capturedByArrowFunction = true;
26693            }
26694
26695            checkThisInStaticClassFieldInitializerInDecoratedClass(node, container);
26696            switch (container.kind) {
26697                case SyntaxKind.ModuleDeclaration:
26698                    error(node, Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body);
26699                    // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
26700                    break;
26701                case SyntaxKind.EnumDeclaration:
26702                    error(node, Diagnostics.this_cannot_be_referenced_in_current_location);
26703                    // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
26704                    break;
26705                case SyntaxKind.Constructor:
26706                    if (isInConstructorArgumentInitializer(node, container)) {
26707                        error(node, Diagnostics.this_cannot_be_referenced_in_constructor_arguments);
26708                        // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
26709                    }
26710                    break;
26711                case SyntaxKind.ComputedPropertyName:
26712                    error(node, Diagnostics.this_cannot_be_referenced_in_a_computed_property_name);
26713                    break;
26714            }
26715
26716            // When targeting es6, mark that we'll need to capture `this` in its lexically bound scope.
26717            if (!isNodeInTypeQuery && capturedByArrowFunction && languageVersion < ScriptTarget.ES2015) {
26718                captureLexicalThis(node, container);
26719            }
26720
26721            const type = tryGetThisTypeAt(node, /*includeGlobalThis*/ true, container);
26722            if (noImplicitThis) {
26723                const globalThisType = getTypeOfSymbol(globalThisSymbol);
26724                if (type === globalThisType && capturedByArrowFunction) {
26725                    error(node, Diagnostics.The_containing_arrow_function_captures_the_global_value_of_this);
26726                }
26727                else if (!type) {
26728                    // With noImplicitThis, functions may not reference 'this' if it has type 'any'
26729                    const diag = error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
26730                    if (!isSourceFile(container)) {
26731                        const outsideThis = tryGetThisTypeAt(container);
26732                        if (outsideThis && outsideThis !== globalThisType) {
26733                            addRelatedInfo(diag, createDiagnosticForNode(container, Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container));
26734                        }
26735                    }
26736                }
26737            }
26738            return type || anyType;
26739        }
26740
26741        function tryGetThisTypeAt(node: Node, includeGlobalThis = true, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined {
26742            const isInJS = isInJSFile(node);
26743            if (isFunctionLike(container) &&
26744                (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) {
26745                let thisType = getThisTypeOfDeclaration(container) || isInJS && getTypeForThisExpressionFromJSDoc(container);
26746                // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated.
26747                // If this is a function in a JS file, it might be a class method.
26748                if (!thisType) {
26749                    const className = getClassNameFromPrototypeMethod(container);
26750                    if (isInJS && className) {
26751                        const classSymbol = checkExpression(className).symbol;
26752                        if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
26753                            thisType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType;
26754                        }
26755                    }
26756                    else if (isJSConstructor(container)) {
26757                        thisType = (getDeclaredTypeOfSymbol(getMergedSymbol(container.symbol)) as InterfaceType).thisType;
26758                    }
26759                    thisType ||= getContextualThisParameterType(container);
26760                }
26761
26762                if (thisType) {
26763                    return getFlowTypeOfReference(node, thisType);
26764                }
26765            }
26766
26767            if (isClassLike(container.parent)) {
26768                const symbol = getSymbolOfNode(container.parent);
26769                const type = isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!;
26770                return getFlowTypeOfReference(node, type);
26771            }
26772
26773            if (isSourceFile(container)) {
26774                // look up in the source file's locals or exports
26775                if (container.commonJsModuleIndicator) {
26776                    const fileSymbol = getSymbolOfNode(container);
26777                    return fileSymbol && getTypeOfSymbol(fileSymbol);
26778                }
26779                else if (container.externalModuleIndicator) {
26780                    // TODO: Maybe issue a better error than 'object is possibly undefined'
26781                    return undefinedType;
26782                }
26783                else if (includeGlobalThis) {
26784                    return getTypeOfSymbol(globalThisSymbol);
26785                }
26786            }
26787        }
26788
26789        function getExplicitThisType(node: Expression) {
26790            const container = getThisContainer(node, /*includeArrowFunctions*/ false);
26791            if (isFunctionLike(container)) {
26792                const signature = getSignatureFromDeclaration(container);
26793                if (signature.thisParameter) {
26794                    return getExplicitTypeOfSymbol(signature.thisParameter);
26795                }
26796            }
26797            if (isClassLike(container.parent)) {
26798                const symbol = getSymbolOfNode(container.parent);
26799                return isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!;
26800            }
26801        }
26802
26803        function getClassNameFromPrototypeMethod(container: Node) {
26804            // Check if it's the RHS of a x.prototype.y = function [name]() { .... }
26805            if (container.kind === SyntaxKind.FunctionExpression &&
26806                isBinaryExpression(container.parent) &&
26807                getAssignmentDeclarationKind(container.parent) === AssignmentDeclarationKind.PrototypeProperty) {
26808                // Get the 'x' of 'x.prototype.y = container'
26809                return ((container.parent   // x.prototype.y = container
26810                    .left as PropertyAccessExpression)       // x.prototype.y
26811                    .expression as PropertyAccessExpression) // x.prototype
26812                    .expression;                             // x
26813            }
26814            // x.prototype = { method() { } }
26815            else if (container.kind === SyntaxKind.MethodDeclaration &&
26816                container.parent.kind === SyntaxKind.ObjectLiteralExpression &&
26817                isBinaryExpression(container.parent.parent) &&
26818                getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.Prototype) {
26819                return (container.parent.parent.left as PropertyAccessExpression).expression;
26820            }
26821            // x.prototype = { method: function() { } }
26822            else if (container.kind === SyntaxKind.FunctionExpression &&
26823                container.parent.kind === SyntaxKind.PropertyAssignment &&
26824                container.parent.parent.kind === SyntaxKind.ObjectLiteralExpression &&
26825                isBinaryExpression(container.parent.parent.parent) &&
26826                getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.Prototype) {
26827                return (container.parent.parent.parent.left as PropertyAccessExpression).expression;
26828            }
26829            // Object.defineProperty(x, "method", { value: function() { } });
26830            // Object.defineProperty(x, "method", { set: (x: () => void) => void });
26831            // Object.defineProperty(x, "method", { get: () => function() { }) });
26832            else if (container.kind === SyntaxKind.FunctionExpression &&
26833                isPropertyAssignment(container.parent) &&
26834                isIdentifier(container.parent.name) &&
26835                (container.parent.name.escapedText === "value" || container.parent.name.escapedText === "get" || container.parent.name.escapedText === "set") &&
26836                isObjectLiteralExpression(container.parent.parent) &&
26837                isCallExpression(container.parent.parent.parent) &&
26838                container.parent.parent.parent.arguments[2] === container.parent.parent &&
26839                getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.ObjectDefinePrototypeProperty) {
26840                return (container.parent.parent.parent.arguments[0] as PropertyAccessExpression).expression;
26841            }
26842            // Object.defineProperty(x, "method", { value() { } });
26843            // Object.defineProperty(x, "method", { set(x: () => void) {} });
26844            // Object.defineProperty(x, "method", { get() { return () => {} } });
26845            else if (isMethodDeclaration(container) &&
26846                isIdentifier(container.name) &&
26847                (container.name.escapedText === "value" || container.name.escapedText === "get" || container.name.escapedText === "set") &&
26848                isObjectLiteralExpression(container.parent) &&
26849                isCallExpression(container.parent.parent) &&
26850                container.parent.parent.arguments[2] === container.parent &&
26851                getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.ObjectDefinePrototypeProperty) {
26852                return (container.parent.parent.arguments[0] as PropertyAccessExpression).expression;
26853            }
26854        }
26855
26856        function getTypeForThisExpressionFromJSDoc(node: Node) {
26857            const jsdocType = getJSDocType(node);
26858            if (jsdocType && jsdocType.kind === SyntaxKind.JSDocFunctionType) {
26859                const jsDocFunctionType = jsdocType as JSDocFunctionType;
26860                if (jsDocFunctionType.parameters.length > 0 &&
26861                    jsDocFunctionType.parameters[0].name &&
26862                    (jsDocFunctionType.parameters[0].name as Identifier).escapedText === InternalSymbolName.This) {
26863                    return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type!);
26864                }
26865            }
26866            const thisTag = getJSDocThisTag(node);
26867            if (thisTag && thisTag.typeExpression) {
26868                return getTypeFromTypeNode(thisTag.typeExpression);
26869            }
26870        }
26871
26872        function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean {
26873            return !!findAncestor(node, n => isFunctionLikeDeclaration(n) ? "quit" : n.kind === SyntaxKind.Parameter && n.parent === constructorDecl);
26874        }
26875
26876        function checkSuperExpression(node: Node): Type {
26877            const isCallExpression = node.parent.kind === SyntaxKind.CallExpression && (node.parent as CallExpression).expression === node;
26878
26879            const immediateContainer = getSuperContainer(node, /*stopOnFunctions*/ true);
26880            let container = immediateContainer;
26881            let needToCaptureLexicalThis = false;
26882            let inAsyncFunction = false;
26883
26884            // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting
26885            if (!isCallExpression) {
26886                while (container && container.kind === SyntaxKind.ArrowFunction) {
26887                    if (hasSyntacticModifier(container, ModifierFlags.Async)) inAsyncFunction = true;
26888                    container = getSuperContainer(container, /*stopOnFunctions*/ true);
26889                    needToCaptureLexicalThis = languageVersion < ScriptTarget.ES2015;
26890                }
26891                if (container && hasSyntacticModifier(container, ModifierFlags.Async)) inAsyncFunction = true;
26892            }
26893
26894            const canUseSuperExpression = isLegalUsageOfSuperExpression(container);
26895            let nodeCheckFlag: NodeCheckFlags = 0;
26896
26897            if (!canUseSuperExpression) {
26898                // issue more specific error if super is used in computed property name
26899                // class A { foo() { return "1" }}
26900                // class B {
26901                //     [super.foo()]() {}
26902                // }
26903                const current = findAncestor(node, n => n === container ? "quit" : n.kind === SyntaxKind.ComputedPropertyName);
26904                if (current && current.kind === SyntaxKind.ComputedPropertyName) {
26905                    error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name);
26906                }
26907                else if (isCallExpression) {
26908                    error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors);
26909                }
26910                else if (!container || !container.parent || !(isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression)) {
26911                    error(node, Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions);
26912                }
26913                else {
26914                    error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class);
26915                }
26916                return errorType;
26917            }
26918
26919            if (!isCallExpression && immediateContainer.kind === SyntaxKind.Constructor) {
26920                checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class);
26921            }
26922
26923            if (isStatic(container) || isCallExpression) {
26924                nodeCheckFlag = NodeCheckFlags.SuperStatic;
26925                if (!isCallExpression &&
26926                    languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 &&
26927                    (isPropertyDeclaration(container) || isClassStaticBlockDeclaration(container))) {
26928                    // for `super.x` or `super[x]` in a static initializer, mark all enclosing
26929                    // block scope containers so that we can report potential collisions with
26930                    // `Reflect`.
26931                    forEachEnclosingBlockScopeContainer(node.parent, current => {
26932                        if (!isSourceFile(current) || isExternalOrCommonJsModule(current)) {
26933                            getNodeLinks(current).flags |= NodeCheckFlags.ContainsSuperPropertyInStaticInitializer;
26934                        }
26935                    });
26936                }
26937            }
26938            else {
26939                nodeCheckFlag = NodeCheckFlags.SuperInstance;
26940            }
26941
26942            getNodeLinks(node).flags |= nodeCheckFlag;
26943
26944            // Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference.
26945            // This is due to the fact that we emit the body of an async function inside of a generator function. As generator
26946            // functions cannot reference `super`, we emit a helper inside of the method body, but outside of the generator. This helper
26947            // uses an arrow function, which is permitted to reference `super`.
26948            //
26949            // There are two primary ways we can access `super` from within an async method. The first is getting the value of a property
26950            // or indexed access on super, either as part of a right-hand-side expression or call expression. The second is when setting the value
26951            // of a property or indexed access, either as part of an assignment expression or destructuring assignment.
26952            //
26953            // The simplest case is reading a value, in which case we will emit something like the following:
26954            //
26955            //  // ts
26956            //  ...
26957            //  async asyncMethod() {
26958            //    let x = await super.asyncMethod();
26959            //    return x;
26960            //  }
26961            //  ...
26962            //
26963            //  // js
26964            //  ...
26965            //  asyncMethod() {
26966            //      const _super = Object.create(null, {
26967            //        asyncMethod: { get: () => super.asyncMethod },
26968            //      });
26969            //      return __awaiter(this, arguments, Promise, function *() {
26970            //          let x = yield _super.asyncMethod.call(this);
26971            //          return x;
26972            //      });
26973            //  }
26974            //  ...
26975            //
26976            // The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases
26977            // are legal in ES6, but also likely less frequent, we only emit setters if there is an assignment:
26978            //
26979            //  // ts
26980            //  ...
26981            //  async asyncMethod(ar: Promise<any[]>) {
26982            //      [super.a, super.b] = await ar;
26983            //  }
26984            //  ...
26985            //
26986            //  // js
26987            //  ...
26988            //  asyncMethod(ar) {
26989            //      const _super = Object.create(null, {
26990            //        a: { get: () => super.a, set: (v) => super.a = v },
26991            //        b: { get: () => super.b, set: (v) => super.b = v }
26992            //      };
26993            //      return __awaiter(this, arguments, Promise, function *() {
26994            //          [_super.a, _super.b] = yield ar;
26995            //      });
26996            //  }
26997            //  ...
26998            //
26999            // Creating an object that has getter and setters instead of just an accessor function is required for destructuring assignments
27000            // as a call expression cannot be used as the target of a destructuring assignment while a property access can.
27001            //
27002            // For element access expressions (`super[x]`), we emit a generic helper that forwards the element access in both situations.
27003            if (container.kind === SyntaxKind.MethodDeclaration && inAsyncFunction) {
27004                if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) {
27005                    getNodeLinks(container).flags |= NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync;
27006                }
27007                else {
27008                    getNodeLinks(container).flags |= NodeCheckFlags.MethodWithSuperPropertyAccessInAsync;
27009                }
27010            }
27011
27012            if (needToCaptureLexicalThis) {
27013                // call expressions are allowed only in constructors so they should always capture correct 'this'
27014                // super property access expressions can also appear in arrow functions -
27015                // in this case they should also use correct lexical this
27016                captureLexicalThis(node.parent, container);
27017            }
27018
27019            if (container.parent.kind === SyntaxKind.ObjectLiteralExpression) {
27020                if (languageVersion < ScriptTarget.ES2015) {
27021                    error(node, Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher);
27022                    return errorType;
27023                }
27024                else {
27025                    // for object literal assume that type of 'super' is 'any'
27026                    return anyType;
27027                }
27028            }
27029
27030            // at this point the only legal case for parent is ClassLikeDeclaration
27031            const classLikeDeclaration = container.parent as ClassLikeDeclaration;
27032            if (!getClassExtendsHeritageElement(classLikeDeclaration)) {
27033                error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class);
27034                return errorType;
27035            }
27036
27037            const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)) as InterfaceType;
27038            const baseClassType = classType && getBaseTypes(classType)[0];
27039            if (!baseClassType) {
27040                return errorType;
27041            }
27042
27043            if (container.kind === SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) {
27044                // issue custom error message for super property access in constructor arguments (to be aligned with old compiler)
27045                error(node, Diagnostics.super_cannot_be_referenced_in_constructor_arguments);
27046                return errorType;
27047            }
27048
27049            return nodeCheckFlag === NodeCheckFlags.SuperStatic
27050                ? getBaseConstructorTypeOfClass(classType)
27051                : getTypeWithThisArgument(baseClassType, classType.thisType);
27052
27053            function isLegalUsageOfSuperExpression(container: Node): boolean {
27054                if (!container) {
27055                    return false;
27056                }
27057
27058                if (isCallExpression) {
27059                    // TS 1.0 SPEC (April 2014): 4.8.1
27060                    // Super calls are only permitted in constructors of derived classes
27061                    return container.kind === SyntaxKind.Constructor;
27062                }
27063                else {
27064                    // TS 1.0 SPEC (April 2014)
27065                    // 'super' property access is allowed
27066                    // - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance
27067                    // - In a static member function or static member accessor
27068
27069                    // topmost container must be something that is directly nested in the class declaration\object literal expression
27070                    if (isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) {
27071                        if (isStatic(container)) {
27072                            return container.kind === SyntaxKind.MethodDeclaration ||
27073                                container.kind === SyntaxKind.MethodSignature ||
27074                                container.kind === SyntaxKind.GetAccessor ||
27075                                container.kind === SyntaxKind.SetAccessor ||
27076                                container.kind === SyntaxKind.PropertyDeclaration ||
27077                                container.kind === SyntaxKind.ClassStaticBlockDeclaration;
27078                        }
27079                        else {
27080                            return container.kind === SyntaxKind.MethodDeclaration ||
27081                                container.kind === SyntaxKind.MethodSignature ||
27082                                container.kind === SyntaxKind.GetAccessor ||
27083                                container.kind === SyntaxKind.SetAccessor ||
27084                                container.kind === SyntaxKind.PropertyDeclaration ||
27085                                container.kind === SyntaxKind.PropertySignature ||
27086                                container.kind === SyntaxKind.Constructor;
27087                        }
27088                    }
27089                }
27090
27091                return false;
27092            }
27093        }
27094
27095        function getContainingObjectLiteral(func: SignatureDeclaration): ObjectLiteralExpression | undefined {
27096            return (func.kind === SyntaxKind.MethodDeclaration ||
27097                func.kind === SyntaxKind.GetAccessor ||
27098                func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent :
27099                func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? func.parent.parent as ObjectLiteralExpression :
27100                undefined;
27101        }
27102
27103        function getThisTypeArgument(type: Type): Type | undefined {
27104            return getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target === globalThisType ? getTypeArguments(type as TypeReference)[0] : undefined;
27105        }
27106
27107        function getThisTypeFromContextualType(type: Type): Type | undefined {
27108            return mapType(type, t => {
27109                return t.flags & TypeFlags.Intersection ? forEach((t as IntersectionType).types, getThisTypeArgument) : getThisTypeArgument(t);
27110            });
27111        }
27112
27113        function getContextualThisParameterType(func: SignatureDeclaration): Type | undefined {
27114            if (func.kind === SyntaxKind.ArrowFunction) {
27115                return undefined;
27116            }
27117            if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
27118                const contextualSignature = getContextualSignature(func);
27119                if (contextualSignature) {
27120                    const thisParameter = contextualSignature.thisParameter;
27121                    if (thisParameter) {
27122                        return getTypeOfSymbol(thisParameter);
27123                    }
27124                }
27125            }
27126            const inJs = isInJSFile(func);
27127            if (noImplicitThis || inJs) {
27128                const containingLiteral = getContainingObjectLiteral(func);
27129                if (containingLiteral) {
27130                    // We have an object literal method. Check if the containing object literal has a contextual type
27131                    // that includes a ThisType<T>. If so, T is the contextual type for 'this'. We continue looking in
27132                    // any directly enclosing object literals.
27133                    const contextualType = getApparentTypeOfContextualType(containingLiteral, /*contextFlags*/ undefined);
27134                    let literal = containingLiteral;
27135                    let type = contextualType;
27136                    while (type) {
27137                        const thisType = getThisTypeFromContextualType(type);
27138                        if (thisType) {
27139                            return instantiateType(thisType, getMapperFromContext(getInferenceContext(containingLiteral)));
27140                        }
27141                        if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
27142                            break;
27143                        }
27144                        literal = literal.parent.parent as ObjectLiteralExpression;
27145                        type = getApparentTypeOfContextualType(literal, /*contextFlags*/ undefined);
27146                    }
27147                    // There was no contextual ThisType<T> for the containing object literal, so the contextual type
27148                    // for 'this' is the non-null form of the contextual type for the containing object literal or
27149                    // the type of the object literal itself.
27150                    return getWidenedType(contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral));
27151                }
27152                // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the
27153                // contextual type for 'this' is 'obj'.
27154                const parent = walkUpParenthesizedExpressions(func.parent);
27155                if (parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
27156                    const target = (parent as BinaryExpression).left;
27157                    if (isAccessExpression(target)) {
27158                        const { expression } = target;
27159                        // Don't contextually type `this` as `exports` in `exports.Point = function(x, y) { this.x = x; this.y = y; }`
27160                        if (inJs && isIdentifier(expression)) {
27161                            const sourceFile = getSourceFileOfNode(parent);
27162                            if (sourceFile.commonJsModuleIndicator && getResolvedSymbol(expression) === sourceFile.symbol) {
27163                                return undefined;
27164                            }
27165                        }
27166
27167                        return getWidenedType(checkExpressionCached(expression));
27168                    }
27169                }
27170            }
27171            return undefined;
27172        }
27173
27174        // Return contextual type of parameter or undefined if no contextual type is available
27175        function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type | undefined {
27176            const func = parameter.parent;
27177            if (!isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
27178                return undefined;
27179            }
27180            const iife = getImmediatelyInvokedFunctionExpression(func);
27181            if (iife && iife.arguments) {
27182                const args = getEffectiveCallArguments(iife);
27183                const indexOfParameter = func.parameters.indexOf(parameter);
27184                if (parameter.dotDotDotToken) {
27185                    return getSpreadArgumentType(args, indexOfParameter, args.length, anyType, /*context*/ undefined, CheckMode.Normal);
27186                }
27187                const links = getNodeLinks(iife);
27188                const cached = links.resolvedSignature;
27189                links.resolvedSignature = anySignature;
27190                const type = indexOfParameter < args.length ?
27191                    getWidenedLiteralType(checkExpression(args[indexOfParameter])) :
27192                    parameter.initializer ? undefined : undefinedWideningType;
27193                links.resolvedSignature = cached;
27194                return type;
27195            }
27196            const contextualSignature = getContextualSignature(func);
27197            if (contextualSignature) {
27198                const index = func.parameters.indexOf(parameter) - (getThisParameter(func) ? 1 : 0);
27199                return parameter.dotDotDotToken && lastOrUndefined(func.parameters) === parameter ?
27200                    getRestTypeAtPosition(contextualSignature, index) :
27201                    tryGetTypeAtPosition(contextualSignature, index);
27202            }
27203        }
27204
27205        function getContextualTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, contextFlags: ContextFlags | undefined): Type | undefined {
27206            const typeNode = getEffectiveTypeAnnotationNode(declaration);
27207            if (typeNode) {
27208                return getTypeFromTypeNode(typeNode);
27209            }
27210            switch (declaration.kind) {
27211                case SyntaxKind.Parameter:
27212                    return getContextuallyTypedParameterType(declaration);
27213                case SyntaxKind.BindingElement:
27214                    return getContextualTypeForBindingElement(declaration, contextFlags);
27215                case SyntaxKind.PropertyDeclaration:
27216                    if (isStatic(declaration)) {
27217                        return getContextualTypeForStaticPropertyDeclaration(declaration, contextFlags);
27218                    }
27219                // By default, do nothing and return undefined - only the above cases have context implied by a parent
27220            }
27221        }
27222
27223        function getContextualTypeForBindingElement(declaration: BindingElement, contextFlags: ContextFlags | undefined): Type | undefined {
27224            const parent = declaration.parent.parent;
27225            const name = declaration.propertyName || declaration.name;
27226            const parentType = getContextualTypeForVariableLikeDeclaration(parent, contextFlags) ||
27227                parent.kind !== SyntaxKind.BindingElement && parent.initializer && checkDeclarationInitializer(parent, declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal);
27228            if (!parentType || isBindingPattern(name) || isComputedNonLiteralName(name)) return undefined;
27229            if (parent.name.kind === SyntaxKind.ArrayBindingPattern) {
27230                const index = indexOfNode(declaration.parent.elements, declaration);
27231                if (index < 0) return undefined;
27232                return getContextualTypeForElementExpression(parentType, index);
27233            }
27234            const nameType = getLiteralTypeFromPropertyName(name);
27235            if (isTypeUsableAsPropertyName(nameType)) {
27236                const text = getPropertyNameFromType(nameType);
27237                return getTypeOfPropertyOfType(parentType, text);
27238            }
27239        }
27240
27241        function getContextualTypeForStaticPropertyDeclaration(declaration: PropertyDeclaration, contextFlags: ContextFlags | undefined): Type | undefined {
27242            const parentType = isExpression(declaration.parent) && getContextualType(declaration.parent, contextFlags);
27243            if (!parentType) return undefined;
27244            return getTypeOfPropertyOfContextualType(parentType, getSymbolOfNode(declaration).escapedName);
27245        }
27246
27247        // In a variable, parameter or property declaration with a type annotation,
27248        //   the contextual type of an initializer expression is the type of the variable, parameter or property.
27249        // Otherwise, in a parameter declaration of a contextually typed function expression,
27250        //   the contextual type of an initializer expression is the contextual type of the parameter.
27251        // Otherwise, in a variable or parameter declaration with a binding pattern name,
27252        //   the contextual type of an initializer expression is the type implied by the binding pattern.
27253        // Otherwise, in a binding pattern inside a variable or parameter declaration,
27254        //   the contextual type of an initializer expression is the type annotation of the containing declaration, if present.
27255        function getContextualTypeForInitializerExpression(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined {
27256            const declaration = node.parent as VariableLikeDeclaration;
27257            if (hasInitializer(declaration) && node === declaration.initializer) {
27258                const result = getContextualTypeForVariableLikeDeclaration(declaration, contextFlags);
27259                if (result) {
27260                    return result;
27261                }
27262                if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name) && declaration.name.elements.length > 0) {
27263                    return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false);
27264                }
27265            }
27266            return undefined;
27267        }
27268
27269        function getContextualTypeForReturnExpression(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined {
27270            const func = getContainingFunction(node);
27271            if (func) {
27272                let contextualReturnType = getContextualReturnType(func, contextFlags);
27273                if (contextualReturnType) {
27274                    const functionFlags = getFunctionFlags(func);
27275                    if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function
27276                        const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0;
27277                        if (contextualReturnType.flags & TypeFlags.Union) {
27278                            contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator));
27279                        }
27280                        const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0);
27281                        if (!iterationReturnType) {
27282                            return undefined;
27283                        }
27284                        contextualReturnType = iterationReturnType;
27285                        // falls through to unwrap Promise for AsyncGenerators
27286                    }
27287
27288                    if (functionFlags & FunctionFlags.Async) { // Async function or AsyncGenerator function
27289                        // Get the awaited type without the `Awaited<T>` alias
27290                        const contextualAwaitedType = mapType(contextualReturnType, getAwaitedTypeNoAlias);
27291                        return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
27292                    }
27293
27294                    return contextualReturnType; // Regular function or Generator function
27295                }
27296            }
27297            return undefined;
27298        }
27299
27300        function getContextualTypeForAwaitOperand(node: AwaitExpression, contextFlags: ContextFlags | undefined): Type | undefined {
27301            const contextualType = getContextualType(node, contextFlags);
27302            if (contextualType) {
27303                const contextualAwaitedType = getAwaitedTypeNoAlias(contextualType);
27304                return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
27305            }
27306            return undefined;
27307        }
27308
27309        function getContextualTypeForYieldOperand(node: YieldExpression, contextFlags: ContextFlags | undefined): Type | undefined {
27310            const func = getContainingFunction(node);
27311            if (func) {
27312                const functionFlags = getFunctionFlags(func);
27313                let contextualReturnType = getContextualReturnType(func, contextFlags);
27314                if (contextualReturnType) {
27315                    const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0;
27316                    if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) {
27317                        contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator));
27318                    }
27319                    return node.asteriskToken
27320                        ? contextualReturnType
27321                        : getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator);
27322                }
27323            }
27324
27325            return undefined;
27326        }
27327
27328        function isInParameterInitializerBeforeContainingFunction(node: Node) {
27329            let inBindingInitializer = false;
27330            while (node.parent && !isFunctionLike(node.parent)) {
27331                if (isParameter(node.parent) && (inBindingInitializer || node.parent.initializer === node)) {
27332                    return true;
27333                }
27334                if (isBindingElement(node.parent) && node.parent.initializer === node) {
27335                    inBindingInitializer = true;
27336                }
27337
27338                node = node.parent;
27339            }
27340
27341            return false;
27342        }
27343
27344        function getContextualIterationType(kind: IterationTypeKind, functionDecl: SignatureDeclaration): Type | undefined {
27345            const isAsync = !!(getFunctionFlags(functionDecl) & FunctionFlags.Async);
27346            const contextualReturnType = getContextualReturnType(functionDecl, /*contextFlags*/ undefined);
27347            if (contextualReturnType) {
27348                return getIterationTypeOfGeneratorFunctionReturnType(kind, contextualReturnType, isAsync)
27349                    || undefined;
27350            }
27351
27352            return undefined;
27353        }
27354
27355        function getContextualReturnType(functionDecl: SignatureDeclaration, contextFlags: ContextFlags | undefined): Type | undefined {
27356            // If the containing function has a return type annotation, is a constructor, or is a get accessor whose
27357            // corresponding set accessor has a type annotation, return statements in the function are contextually typed
27358            const returnType = getReturnTypeFromAnnotation(functionDecl);
27359            if (returnType) {
27360                return returnType;
27361            }
27362            // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
27363            // and that call signature is non-generic, return statements are contextually typed by the return type of the signature
27364            const signature = getContextualSignatureForFunctionLikeDeclaration(functionDecl as FunctionExpression);
27365            if (signature && !isResolvingReturnTypeOfSignature(signature)) {
27366                return getReturnTypeOfSignature(signature);
27367            }
27368            const iife = getImmediatelyInvokedFunctionExpression(functionDecl);
27369            if (iife) {
27370                return getContextualType(iife, contextFlags);
27371            }
27372            return undefined;
27373        }
27374
27375        // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter.
27376        function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type | undefined {
27377            const args = getEffectiveCallArguments(callTarget);
27378            const argIndex = args.indexOf(arg); // -1 for e.g. the expression of a CallExpression, or the tag of a TaggedTemplateExpression
27379            return argIndex === -1 ? undefined : getContextualTypeForArgumentAtIndex(callTarget, argIndex);
27380        }
27381
27382        function getContextualTypeForArgumentAtIndex(callTarget: CallLikeExpression, argIndex: number): Type {
27383            if (isImportCall(callTarget)) {
27384                return argIndex === 0 ? stringType :
27385                    argIndex === 1 ? getGlobalImportCallOptionsType(/*reportErrors*/ false) :
27386                    anyType;
27387            }
27388
27389            // If we're already in the process of resolving the given signature, don't resolve again as
27390            // that could cause infinite recursion. Instead, return anySignature.
27391            const signature = getNodeLinks(callTarget).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(callTarget);
27392
27393            if (isJsxOpeningLikeElement(callTarget) && argIndex === 0) {
27394                return getEffectiveFirstArgumentForJsxSignature(signature, callTarget);
27395            }
27396            const restIndex = signature.parameters.length - 1;
27397            return signatureHasRestParameter(signature) && argIndex >= restIndex ?
27398                getIndexedAccessType(getTypeOfSymbol(signature.parameters[restIndex]), getNumberLiteralType(argIndex - restIndex), AccessFlags.Contextual) :
27399                getTypeAtPosition(signature, argIndex);
27400        }
27401
27402        function getContextualTypeForSubstitutionExpression(template: TemplateExpression, substitutionExpression: Expression) {
27403            if (template.parent.kind === SyntaxKind.TaggedTemplateExpression) {
27404                return getContextualTypeForArgument(template.parent as TaggedTemplateExpression, substitutionExpression);
27405            }
27406
27407            return undefined;
27408        }
27409
27410        function getContextualTypeForBinaryOperand(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined {
27411            const binaryExpression = node.parent as BinaryExpression;
27412            const { left, operatorToken, right } = binaryExpression;
27413            switch (operatorToken.kind) {
27414                case SyntaxKind.EqualsToken:
27415                case SyntaxKind.AmpersandAmpersandEqualsToken:
27416                case SyntaxKind.BarBarEqualsToken:
27417                case SyntaxKind.QuestionQuestionEqualsToken:
27418                    return node === right ? getContextualTypeForAssignmentDeclaration(binaryExpression) : undefined;
27419                case SyntaxKind.BarBarToken:
27420                case SyntaxKind.QuestionQuestionToken:
27421                    // When an || expression has a contextual type, the operands are contextually typed by that type, except
27422                    // when that type originates in a binding pattern, the right operand is contextually typed by the type of
27423                    // the left operand. When an || expression has no contextual type, the right operand is contextually typed
27424                    // by the type of the left operand, except for the special case of Javascript declarations of the form
27425                    // `namespace.prop = namespace.prop || {}`.
27426                    const type = getContextualType(binaryExpression, contextFlags);
27427                    return node === right && (type && type.pattern || !type && !isDefaultedExpandoInitializer(binaryExpression)) ?
27428                        getTypeOfExpression(left) : type;
27429                case SyntaxKind.AmpersandAmpersandToken:
27430                case SyntaxKind.CommaToken:
27431                    return node === right ? getContextualType(binaryExpression, contextFlags) : undefined;
27432                default:
27433                    return undefined;
27434            }
27435        }
27436
27437        /**
27438         * Try to find a resolved symbol for an expression without also resolving its type, as
27439         * getSymbolAtLocation would (as that could be reentrant into contextual typing)
27440         */
27441         function getSymbolForExpression(e: Expression) {
27442            if (e.symbol) {
27443                return e.symbol;
27444            }
27445            if (isIdentifier(e)) {
27446                return getResolvedSymbol(e);
27447            }
27448            if (isPropertyAccessExpression(e)) {
27449                const lhsType = getTypeOfExpression(e.expression);
27450                return isPrivateIdentifier(e.name) ? tryGetPrivateIdentifierPropertyOfType(lhsType, e.name) : getPropertyOfType(lhsType, e.name.escapedText);
27451            }
27452            if (isElementAccessExpression(e)) {
27453                const propType = checkExpressionCached(e.argumentExpression);
27454                if (!isTypeUsableAsPropertyName(propType)) {
27455                    return undefined;
27456                }
27457                const lhsType = getTypeOfExpression(e.expression);
27458                return getPropertyOfType(lhsType, getPropertyNameFromType(propType));
27459            }
27460            return undefined;
27461
27462            function tryGetPrivateIdentifierPropertyOfType(type: Type, id: PrivateIdentifier) {
27463                const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(id.escapedText, id);
27464                return lexicallyScopedSymbol && getPrivateIdentifierPropertyOfType(type, lexicallyScopedSymbol);
27465            }
27466        }
27467
27468        // In an assignment expression, the right operand is contextually typed by the type of the left operand.
27469        // Don't do this for assignment declarations unless there is a type tag on the assignment, to avoid circularity from checking the right operand.
27470        function getContextualTypeForAssignmentDeclaration(binaryExpression: BinaryExpression): Type | undefined {
27471            const kind = getAssignmentDeclarationKind(binaryExpression);
27472            switch (kind) {
27473                case AssignmentDeclarationKind.None:
27474                case AssignmentDeclarationKind.ThisProperty:
27475                    const lhsSymbol = getSymbolForExpression(binaryExpression.left);
27476                    const decl = lhsSymbol && lhsSymbol.valueDeclaration;
27477                    // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor.
27478                    // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case.
27479                    if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl))) {
27480                        const overallAnnotation = getEffectiveTypeAnnotationNode(decl);
27481                        return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) ||
27482                            (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined);
27483                    }
27484                    if (kind === AssignmentDeclarationKind.None) {
27485                        return getTypeOfExpression(binaryExpression.left);
27486                    }
27487                    return getContextualTypeForThisPropertyAssignment(binaryExpression);
27488                case AssignmentDeclarationKind.Property:
27489                    if (isPossiblyAliasedThisProperty(binaryExpression, kind)) {
27490                        return getContextualTypeForThisPropertyAssignment(binaryExpression);
27491                    }
27492                    // If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration.
27493                    // See `bindStaticPropertyAssignment` in `binder.ts`.
27494                    else if (!binaryExpression.left.symbol) {
27495                        return getTypeOfExpression(binaryExpression.left);
27496                    }
27497                    else {
27498                        const decl = binaryExpression.left.symbol.valueDeclaration;
27499                        if (!decl) {
27500                            return undefined;
27501                        }
27502                        const lhs = cast(binaryExpression.left, isAccessExpression);
27503                        const overallAnnotation = getEffectiveTypeAnnotationNode(decl);
27504                        if (overallAnnotation) {
27505                            return getTypeFromTypeNode(overallAnnotation);
27506                        }
27507                        else if (isIdentifier(lhs.expression)) {
27508                            const id = lhs.expression;
27509                            const parentSymbol = resolveName(id, id.escapedText, SymbolFlags.Value, undefined, id.escapedText, /*isUse*/ true);
27510                            if (parentSymbol) {
27511                                const annotated = parentSymbol.valueDeclaration && getEffectiveTypeAnnotationNode(parentSymbol.valueDeclaration);
27512                                if (annotated) {
27513                                    const nameStr = getElementOrPropertyAccessName(lhs);
27514                                    if (nameStr !== undefined) {
27515                                        return getTypeOfPropertyOfContextualType(getTypeFromTypeNode(annotated), nameStr);
27516                                    }
27517                                }
27518                                return undefined;
27519                            }
27520                        }
27521                        return isInJSFile(decl) ? undefined : getTypeOfExpression(binaryExpression.left);
27522                    }
27523                case AssignmentDeclarationKind.ExportsProperty:
27524                case AssignmentDeclarationKind.Prototype:
27525                case AssignmentDeclarationKind.PrototypeProperty:
27526                case AssignmentDeclarationKind.ModuleExports:
27527                    let valueDeclaration: Declaration | undefined;
27528                    if (kind !== AssignmentDeclarationKind.ModuleExports) {
27529                        valueDeclaration = binaryExpression.left.symbol?.valueDeclaration;
27530                    }
27531                    valueDeclaration ||= binaryExpression.symbol?.valueDeclaration;
27532                    const annotated = valueDeclaration && getEffectiveTypeAnnotationNode(valueDeclaration);
27533                    return annotated ? getTypeFromTypeNode(annotated) : undefined;
27534                case AssignmentDeclarationKind.ObjectDefinePropertyValue:
27535                case AssignmentDeclarationKind.ObjectDefinePropertyExports:
27536                case AssignmentDeclarationKind.ObjectDefinePrototypeProperty:
27537                    return Debug.fail("Does not apply");
27538                default:
27539                    return Debug.assertNever(kind);
27540            }
27541        }
27542
27543        function isPossiblyAliasedThisProperty(declaration: BinaryExpression, kind = getAssignmentDeclarationKind(declaration)) {
27544            if (kind === AssignmentDeclarationKind.ThisProperty) {
27545                return true;
27546            }
27547            if (!isInJSFile(declaration) || kind !== AssignmentDeclarationKind.Property || !isIdentifier((declaration.left as AccessExpression).expression)) {
27548                return false;
27549            }
27550            const name = ((declaration.left as AccessExpression).expression as Identifier).escapedText;
27551            const symbol = resolveName(declaration.left, name, SymbolFlags.Value, undefined, undefined, /*isUse*/ true, /*excludeGlobals*/ true);
27552            return isThisInitializedDeclaration(symbol?.valueDeclaration);
27553        }
27554
27555        function getContextualTypeForThisPropertyAssignment(binaryExpression: BinaryExpression): Type | undefined {
27556            if (!binaryExpression.symbol) return getTypeOfExpression(binaryExpression.left);
27557            if (binaryExpression.symbol.valueDeclaration) {
27558                const annotated = getEffectiveTypeAnnotationNode(binaryExpression.symbol.valueDeclaration);
27559                if (annotated) {
27560                    const type = getTypeFromTypeNode(annotated);
27561                    if (type) {
27562                        return type;
27563                    }
27564                }
27565            }
27566            const thisAccess = cast(binaryExpression.left, isAccessExpression);
27567            if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false))) {
27568                return undefined;
27569            }
27570            const thisType = checkThisExpression(thisAccess.expression);
27571            const nameStr = getElementOrPropertyAccessName(thisAccess);
27572            return nameStr !== undefined && getTypeOfPropertyOfContextualType(thisType, nameStr) || undefined;
27573
27574        }
27575
27576        function isCircularMappedProperty(symbol: Symbol) {
27577            return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0);
27578        }
27579
27580        function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) {
27581            return mapType(type, t => {
27582                if (isGenericMappedType(t) && !t.declaration.nameType) {
27583                    const constraint = getConstraintTypeFromMappedType(t);
27584                    const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint;
27585                    const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name));
27586                    if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) {
27587                        return substituteIndexedMappedType(t, propertyNameType);
27588                    }
27589                }
27590                else if (t.flags & TypeFlags.StructuredType) {
27591                    const prop = getPropertyOfType(t, name);
27592                    if (prop) {
27593                        return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop);
27594                    }
27595                    if (isTupleType(t)) {
27596                        const restType = getRestTypeOfTupleType(t);
27597                        if (restType && isNumericLiteralName(name) && +name >= 0) {
27598                            return restType;
27599                        }
27600                    }
27601                    return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type;
27602                }
27603                return undefined;
27604            }, /*noReductions*/ true);
27605        }
27606
27607        // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of
27608        // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one
27609        // exists. Otherwise, it is the type of the string index signature in T, if one exists.
27610        function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined {
27611            Debug.assert(isObjectLiteralMethod(node));
27612            if (node.flags & NodeFlags.InWithStatement) {
27613                // We cannot answer semantic questions within a with block, do not proceed any further
27614                return undefined;
27615            }
27616            return getContextualTypeForObjectLiteralElement(node, contextFlags);
27617        }
27618
27619        function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike, contextFlags: ContextFlags | undefined) {
27620            const objectLiteral = element.parent as ObjectLiteralExpression;
27621            const propertyAssignmentType = isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element, contextFlags);
27622            if (propertyAssignmentType) {
27623                return propertyAssignmentType;
27624            }
27625            const type = getApparentTypeOfContextualType(objectLiteral, contextFlags);
27626            if (type) {
27627                if (hasBindableName(element)) {
27628                    // For a (non-symbol) computed property, there is no reason to look up the name
27629                    // in the type. It will just be "__computed", which does not appear in any
27630                    // SymbolTable.
27631                    const symbol = getSymbolOfNode(element);
27632                    return getTypeOfPropertyOfContextualType(type, symbol.escapedName, getSymbolLinks(symbol).nameType);
27633                }
27634                if (element.name) {
27635                    const nameType = getLiteralTypeFromPropertyName(element.name);
27636                    // We avoid calling getApplicableIndexInfo here because it performs potentially expensive intersection reduction.
27637                    return mapType(type, t => findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType)?.type, /*noReductions*/ true);
27638                }
27639            }
27640            return undefined;
27641        }
27642
27643        // In an array literal contextually typed by a type T, the contextual type of an element expression at index N is
27644        // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature,
27645        // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated
27646        // type of T.
27647        function getContextualTypeForElementExpression(arrayContextualType: Type | undefined, index: number): Type | undefined {
27648            return arrayContextualType && (
27649                getTypeOfPropertyOfContextualType(arrayContextualType, "" + index as __String)
27650                || mapType(
27651                    arrayContextualType,
27652                    t => getIteratedTypeOrElementType(IterationUse.Element, t, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false),
27653                    /*noReductions*/ true));
27654        }
27655
27656        // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type.
27657        function getContextualTypeForConditionalOperand(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined {
27658            const conditional = node.parent as ConditionalExpression;
27659            return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional, contextFlags) : undefined;
27660        }
27661
27662        function getContextualTypeForChildJsxExpression(node: JsxElement, child: JsxChild, contextFlags: ContextFlags | undefined) {
27663            const attributesType = getApparentTypeOfContextualType(node.openingElement.tagName, contextFlags);
27664            // JSX expression is in children of JSX Element, we will look for an "children" attribute (we get the name from JSX.ElementAttributesProperty)
27665            const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node));
27666            if (!(attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "")) {
27667                return undefined;
27668            }
27669            const realChildren = getSemanticJsxChildren(node.children);
27670            const childIndex = realChildren.indexOf(child);
27671            const childFieldType = getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName);
27672            return childFieldType && (realChildren.length === 1 ? childFieldType : mapType(childFieldType, t => {
27673                if (isArrayLikeType(t)) {
27674                    return getIndexedAccessType(t, getNumberLiteralType(childIndex));
27675                }
27676                else {
27677                    return t;
27678                }
27679            }, /*noReductions*/ true));
27680        }
27681
27682        function getContextualTypeForJsxExpression(node: JsxExpression, contextFlags: ContextFlags | undefined): Type | undefined {
27683            const exprParent = node.parent;
27684            return isJsxAttributeLike(exprParent)
27685                ? getContextualType(node, contextFlags)
27686                : isJsxElement(exprParent)
27687                    ? getContextualTypeForChildJsxExpression(exprParent, node, contextFlags)
27688                    : undefined;
27689        }
27690
27691        function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute, contextFlags: ContextFlags | undefined): Type | undefined {
27692            // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type
27693            // which is a type of the parameter of the signature we are trying out.
27694            // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName
27695            if (isJsxAttribute(attribute)) {
27696                const attributesType = getApparentTypeOfContextualType(attribute.parent, contextFlags);
27697                if (!attributesType || isTypeAny(attributesType)) {
27698                    return undefined;
27699                }
27700                return getTypeOfPropertyOfContextualType(attributesType, attribute.name.escapedText);
27701            }
27702            else {
27703                return getContextualType(attribute.parent, contextFlags);
27704            }
27705        }
27706
27707        // Return true if the given expression is possibly a discriminant value. We limit the kinds of
27708        // expressions we check to those that don't depend on their contextual type in order not to cause
27709        // recursive (and possibly infinite) invocations of getContextualType.
27710        function isPossiblyDiscriminantValue(node: Expression): boolean {
27711            switch (node.kind) {
27712                case SyntaxKind.StringLiteral:
27713                case SyntaxKind.NumericLiteral:
27714                case SyntaxKind.BigIntLiteral:
27715                case SyntaxKind.NoSubstitutionTemplateLiteral:
27716                case SyntaxKind.TrueKeyword:
27717                case SyntaxKind.FalseKeyword:
27718                case SyntaxKind.NullKeyword:
27719                case SyntaxKind.Identifier:
27720                case SyntaxKind.UndefinedKeyword:
27721                    return true;
27722                case SyntaxKind.PropertyAccessExpression:
27723                case SyntaxKind.ParenthesizedExpression:
27724                    return isPossiblyDiscriminantValue((node as PropertyAccessExpression | ParenthesizedExpression).expression);
27725                case SyntaxKind.JsxExpression:
27726                    return !(node as JsxExpression).expression || isPossiblyDiscriminantValue((node as JsxExpression).expression!);
27727            }
27728            return false;
27729        }
27730
27731        function discriminateContextualTypeByObjectMembers(node: ObjectLiteralExpression, contextualType: UnionType) {
27732            return getMatchingUnionConstituentForObjectLiteral(contextualType, node) || discriminateTypeByDiscriminableItems(contextualType,
27733                concatenate(
27734                    map(
27735                        filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.PropertyAssignment && isPossiblyDiscriminantValue(p.initializer) && isDiscriminantProperty(contextualType, p.symbol.escapedName)),
27736                        prop => ([() => getContextFreeTypeOfExpression((prop as PropertyAssignment).initializer), prop.symbol.escapedName] as [() => Type, __String])
27737                    ),
27738                    map(
27739                        filter(getPropertiesOfType(contextualType), s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)),
27740                        s => [() => undefinedType, s.escapedName] as [() => Type, __String]
27741                    )
27742                ),
27743                isTypeAssignableTo,
27744                contextualType
27745            );
27746        }
27747
27748        function discriminateContextualTypeByJSXAttributes(node: JsxAttributes, contextualType: UnionType) {
27749            return discriminateTypeByDiscriminableItems(contextualType,
27750                concatenate(
27751                    map(
27752                        filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.JsxAttribute && isDiscriminantProperty(contextualType, p.symbol.escapedName) && (!p.initializer || isPossiblyDiscriminantValue(p.initializer))),
27753                        prop => ([!(prop as JsxAttribute).initializer ? (() => trueType) : (() => getContextFreeTypeOfExpression((prop as JsxAttribute).initializer!)), prop.symbol.escapedName] as [() => Type, __String])
27754                    ),
27755                    map(
27756                        filter(getPropertiesOfType(contextualType), s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)),
27757                        s => [() => undefinedType, s.escapedName] as [() => Type, __String]
27758                    )
27759                ),
27760                isTypeAssignableTo,
27761                contextualType
27762            );
27763        }
27764
27765        // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
27766        // be "pushed" onto a node using the contextualType property.
27767        function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined {
27768            const contextualType = isObjectLiteralMethod(node) ?
27769                getContextualTypeForObjectLiteralMethod(node, contextFlags) :
27770                getContextualType(node, contextFlags);
27771            const instantiatedType = instantiateContextualType(contextualType, node, contextFlags);
27772            if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) {
27773                const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true);
27774                return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) :
27775                    apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) :
27776                    apparentType;
27777            }
27778        }
27779
27780        // If the given contextual type contains instantiable types and if a mapper representing
27781        // return type inferences is available, instantiate those types using that mapper.
27782        function instantiateContextualType(contextualType: Type | undefined, node: Node, contextFlags: ContextFlags | undefined): Type | undefined {
27783            if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) {
27784                const inferenceContext = getInferenceContext(node);
27785                // If no inferences have been made, and none of the type parameters for which we are inferring
27786                // specify default types, nothing is gained from instantiating as type parameters would just be
27787                // replaced with their constraints similar to the apparent type.
27788                if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidatesOrDefault)) {
27789                    // For contextual signatures we incorporate all inferences made so far, e.g. from return
27790                    // types as well as arguments to the left in a function call.
27791                    return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper);
27792                }
27793                if (inferenceContext?.returnMapper) {
27794                    // For other purposes (e.g. determining whether to produce literal types) we only
27795                    // incorporate inferences made from the return type in a function call. We remove
27796                    // the 'boolean' type from the contextual type such that contextually typed boolean
27797                    // literals actually end up widening to 'boolean' (see #48363).
27798                    const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper);
27799                    return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ?
27800                        filterType(type, t => t !== regularFalseType && t !== regularTrueType) :
27801                        type;
27802                }
27803            }
27804            return contextualType;
27805        }
27806
27807        // This function is similar to instantiateType, except that (a) it only instantiates types that
27808        // are classified as instantiable (i.e. it doesn't instantiate object types), and (b) it performs
27809        // no reductions on instantiated union types.
27810        function instantiateInstantiableTypes(type: Type, mapper: TypeMapper): Type {
27811            if (type.flags & TypeFlags.Instantiable) {
27812                return instantiateType(type, mapper);
27813            }
27814            if (type.flags & TypeFlags.Union) {
27815                return getUnionType(map((type as UnionType).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None);
27816            }
27817            if (type.flags & TypeFlags.Intersection) {
27818                return getIntersectionType(map((type as IntersectionType).types, t => instantiateInstantiableTypes(t, mapper)));
27819            }
27820            return type;
27821        }
27822
27823        /**
27824         * Whoa! Do you really want to use this function?
27825         *
27826         * Unless you're trying to get the *non-apparent* type for a
27827         * value-literal type or you're authoring relevant portions of this algorithm,
27828         * you probably meant to use 'getApparentTypeOfContextualType'.
27829         * Otherwise this may not be very useful.
27830         *
27831         * In cases where you *are* working on this function, you should understand
27832         * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContextualType'.
27833         *
27834         *   - Use 'getContextualType' when you are simply going to propagate the result to the expression.
27835         *   - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type.
27836         *
27837         * @param node the expression whose contextual type will be returned.
27838         * @returns the contextual type of an expression.
27839         */
27840        function getContextualType(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined {
27841            if (node.flags & NodeFlags.InWithStatement) {
27842                // We cannot answer semantic questions within a with block, do not proceed any further
27843                return undefined;
27844            }
27845            if (node.contextualType) {
27846                return node.contextualType;
27847            }
27848            const { parent } = node;
27849            switch (parent.kind) {
27850                case SyntaxKind.VariableDeclaration:
27851                case SyntaxKind.Parameter:
27852                case SyntaxKind.PropertyDeclaration:
27853                case SyntaxKind.PropertySignature:
27854                case SyntaxKind.BindingElement:
27855                    return getContextualTypeForInitializerExpression(node, contextFlags);
27856                case SyntaxKind.ArrowFunction:
27857                case SyntaxKind.ReturnStatement:
27858                    return getContextualTypeForReturnExpression(node, contextFlags);
27859                case SyntaxKind.YieldExpression:
27860                    return getContextualTypeForYieldOperand(parent as YieldExpression, contextFlags);
27861                case SyntaxKind.AwaitExpression:
27862                    return getContextualTypeForAwaitOperand(parent as AwaitExpression, contextFlags);
27863                case SyntaxKind.CallExpression:
27864                case SyntaxKind.EtsComponentExpression:
27865                    if (isInEtsFile(parent) && (<CallExpression | EtsComponentExpression>parent).expression.kind === SyntaxKind.ImportKeyword) {
27866                        return stringType;
27867                    }
27868                    /* falls through */
27869                case SyntaxKind.NewExpression:
27870                    return getContextualTypeForArgument(parent as CallExpression | NewExpression | EtsComponentExpression, node);
27871                case SyntaxKind.TypeAssertionExpression:
27872                case SyntaxKind.AsExpression:
27873                    return isConstTypeReference((parent as AssertionExpression).type) ? tryFindWhenConstTypeReference(parent as AssertionExpression) : getTypeFromTypeNode((parent as AssertionExpression).type);
27874                case SyntaxKind.BinaryExpression:
27875                    return getContextualTypeForBinaryOperand(node, contextFlags);
27876                case SyntaxKind.PropertyAssignment:
27877                case SyntaxKind.ShorthandPropertyAssignment:
27878                    return getContextualTypeForObjectLiteralElement(parent as PropertyAssignment | ShorthandPropertyAssignment, contextFlags);
27879                case SyntaxKind.SpreadAssignment:
27880                    return getContextualType(parent.parent as ObjectLiteralExpression, contextFlags);
27881                case SyntaxKind.ArrayLiteralExpression: {
27882                    const arrayLiteral = parent as ArrayLiteralExpression;
27883                    const type = getApparentTypeOfContextualType(arrayLiteral, contextFlags);
27884                    return getContextualTypeForElementExpression(type, indexOfNode(arrayLiteral.elements, node));
27885                }
27886                case SyntaxKind.ConditionalExpression:
27887                    return getContextualTypeForConditionalOperand(node, contextFlags);
27888                case SyntaxKind.TemplateSpan:
27889                    Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression);
27890                    return getContextualTypeForSubstitutionExpression(parent.parent as TemplateExpression, node);
27891                case SyntaxKind.ParenthesizedExpression: {
27892                    // Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast.
27893                    const tag = isInJSFile(parent) ? getJSDocTypeTag(parent) : undefined;
27894                    return !tag ? getContextualType(parent as ParenthesizedExpression, contextFlags) :
27895                        isJSDocTypeTag(tag) && isConstTypeReference(tag.typeExpression.type) ? tryFindWhenConstTypeReference(parent as ParenthesizedExpression) :
27896                        getTypeFromTypeNode(tag.typeExpression.type);
27897                }
27898                case SyntaxKind.NonNullExpression:
27899                    return getContextualType(parent as NonNullExpression, contextFlags);
27900                case SyntaxKind.SatisfiesExpression:
27901                    return getTypeFromTypeNode((parent as SatisfiesExpression).type);
27902                case SyntaxKind.ExportAssignment:
27903                    return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment);
27904                case SyntaxKind.JsxExpression:
27905                    return getContextualTypeForJsxExpression(parent as JsxExpression, contextFlags);
27906                case SyntaxKind.JsxAttribute:
27907                case SyntaxKind.JsxSpreadAttribute:
27908                    return getContextualTypeForJsxAttribute(parent as JsxAttribute | JsxSpreadAttribute, contextFlags);
27909                case SyntaxKind.JsxOpeningElement:
27910                case SyntaxKind.JsxSelfClosingElement:
27911                    return getContextualJsxElementAttributesType(parent as JsxOpeningLikeElement, contextFlags);
27912            }
27913            return undefined;
27914
27915            function tryFindWhenConstTypeReference(node: Expression) {
27916                return getContextualType(node, contextFlags);
27917            }
27918        }
27919
27920        function getInferenceContext(node: Node) {
27921            const ancestor = findAncestor(node, n => !!n.inferenceContext);
27922            return ancestor && ancestor.inferenceContext!;
27923        }
27924
27925        function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) {
27926            if (isJsxOpeningElement(node) && node.parent.contextualType && contextFlags !== ContextFlags.Completions) {
27927                // Contextually applied type is moved from attributes up to the outer jsx attributes so when walking up from the children they get hit
27928                // _However_ to hit them from the _attributes_ we must look for them here; otherwise we'll used the declared type
27929                // (as below) instead!
27930                return node.parent.contextualType;
27931            }
27932            return getContextualTypeForArgumentAtIndex(node, 0);
27933        }
27934
27935        function getEffectiveFirstArgumentForJsxSignature(signature: Signature, node: JsxOpeningLikeElement) {
27936            return getJsxReferenceKind(node) !== JsxReferenceKind.Component
27937                ? getJsxPropsTypeFromCallSignature(signature, node)
27938                : getJsxPropsTypeFromClassType(signature, node);
27939        }
27940
27941        function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) {
27942            let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType);
27943            propsType = getJsxManagedAttributesFromLocatedAttributes(context, getJsxNamespaceAt(context), propsType);
27944            const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
27945            if (!isErrorType(intrinsicAttribs)) {
27946                propsType = intersectTypes(intrinsicAttribs, propsType);
27947            }
27948            return propsType;
27949        }
27950
27951        function getJsxPropsTypeForSignatureFromMember(sig: Signature, forcedLookupLocation: __String) {
27952            if (sig.compositeSignatures) {
27953                // JSX Elements using the legacy `props`-field based lookup (eg, react class components) need to treat the `props` member as an input
27954                // instead of an output position when resolving the signature. We need to go back to the input signatures of the composite signature,
27955                // get the type of `props` on each return type individually, and then _intersect them_, rather than union them (as would normally occur
27956                // for a union signature). It's an unfortunate quirk of looking in the output of the signature for the type we want to use for the input.
27957                // The default behavior of `getTypeOfFirstParameterOfSignatureWithFallback` when no `props` member name is defined is much more sane.
27958                const results: Type[] = [];
27959                for (const signature of sig.compositeSignatures) {
27960                    const instance = getReturnTypeOfSignature(signature);
27961                    if (isTypeAny(instance)) {
27962                        return instance;
27963                    }
27964                    const propType = getTypeOfPropertyOfType(instance, forcedLookupLocation);
27965                    if (!propType) {
27966                        return;
27967                    }
27968                    results.push(propType);
27969                }
27970                return getIntersectionType(results); // Same result for both union and intersection signatures
27971            }
27972            const instanceType = getReturnTypeOfSignature(sig);
27973            return isTypeAny(instanceType) ? instanceType : getTypeOfPropertyOfType(instanceType, forcedLookupLocation);
27974        }
27975
27976        function getStaticTypeOfReferencedJsxConstructor(context: JsxOpeningLikeElement) {
27977            if (isJsxIntrinsicIdentifier(context.tagName)) {
27978                const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(context);
27979                const fakeSignature = createSignatureForJSXIntrinsic(context, result);
27980                return getOrCreateTypeFromSignature(fakeSignature);
27981            }
27982            const tagType = checkExpressionCached(context.tagName);
27983            if (tagType.flags & TypeFlags.StringLiteral) {
27984                const result = getIntrinsicAttributesTypeFromStringLiteralType(tagType as StringLiteralType, context);
27985                if (!result) {
27986                    return errorType;
27987                }
27988                const fakeSignature = createSignatureForJSXIntrinsic(context, result);
27989                return getOrCreateTypeFromSignature(fakeSignature);
27990            }
27991            return tagType;
27992        }
27993
27994        function getJsxManagedAttributesFromLocatedAttributes(context: JsxOpeningLikeElement, ns: Symbol, attributesType: Type) {
27995            const managedSym = getJsxLibraryManagedAttributes(ns);
27996            if (managedSym) {
27997                const declaredManagedType = getDeclaredTypeOfSymbol(managedSym); // fetches interface type, or initializes symbol links type parmaeters
27998                const ctorType = getStaticTypeOfReferencedJsxConstructor(context);
27999                if (managedSym.flags & SymbolFlags.TypeAlias) {
28000                    const params = getSymbolLinks(managedSym).typeParameters;
28001                    if (length(params) >= 2) {
28002                        const args = fillMissingTypeArguments([ctorType, attributesType], params, 2, isInJSFile(context));
28003                        return getTypeAliasInstantiation(managedSym, args);
28004                    }
28005                }
28006                if (length((declaredManagedType as GenericType).typeParameters) >= 2) {
28007                    const args = fillMissingTypeArguments([ctorType, attributesType], (declaredManagedType as GenericType).typeParameters, 2, isInJSFile(context));
28008                    return createTypeReference((declaredManagedType as GenericType), args);
28009                }
28010            }
28011            return attributesType;
28012        }
28013
28014        function getJsxPropsTypeFromClassType(sig: Signature, context: JsxOpeningLikeElement) {
28015            const ns = getJsxNamespaceAt(context);
28016            const forcedLookupLocation = getJsxElementPropertiesName(ns);
28017            let attributesType = forcedLookupLocation === undefined
28018                // If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type
28019                ? getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType)
28020                : forcedLookupLocation === ""
28021                    // If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead
28022                    ? getReturnTypeOfSignature(sig)
28023                    // Otherwise get the type of the property on the signature return type
28024                    : getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation);
28025
28026            if (!attributesType) {
28027                // There is no property named 'props' on this instance type
28028                if (!!forcedLookupLocation && !!length(context.attributes.properties)) {
28029                    error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation));
28030                }
28031                return unknownType;
28032            }
28033
28034            attributesType = getJsxManagedAttributesFromLocatedAttributes(context, ns, attributesType);
28035
28036            if (isTypeAny(attributesType)) {
28037                // Props is of type 'any' or unknown
28038                return attributesType;
28039            }
28040            else {
28041                // Normal case -- add in IntrinsicClassElements<T> and IntrinsicElements
28042                let apparentAttributesType = attributesType;
28043                const intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes, context);
28044                if (!isErrorType(intrinsicClassAttribs)) {
28045                    const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol);
28046                    const hostClassType = getReturnTypeOfSignature(sig);
28047                    let libraryManagedAttributeType: Type;
28048                    if (typeParams) {
28049                        // apply JSX.IntrinsicClassElements<hostClassType, ...>
28050                        const inferredArgs = fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isInJSFile(context));
28051                        libraryManagedAttributeType = instantiateType(intrinsicClassAttribs, createTypeMapper(typeParams, inferredArgs));
28052                    }
28053                    // or JSX.IntrinsicClassElements has no generics.
28054                    else libraryManagedAttributeType = intrinsicClassAttribs;
28055                    apparentAttributesType = intersectTypes(libraryManagedAttributeType, apparentAttributesType);
28056                }
28057
28058                const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context);
28059                if (!isErrorType(intrinsicAttribs)) {
28060                    apparentAttributesType = intersectTypes(intrinsicAttribs, apparentAttributesType);
28061                }
28062
28063                return apparentAttributesType;
28064            }
28065        }
28066
28067        function getIntersectedSignatures(signatures: readonly Signature[]) {
28068            return getStrictOptionValue(compilerOptions, "noImplicitAny")
28069                ? reduceLeft(
28070                    signatures,
28071                    (left, right) =>
28072                        left === right || !left ? left
28073                        : compareTypeParametersIdentical(left.typeParameters, right.typeParameters) ? combineSignaturesOfIntersectionMembers(left, right)
28074                        : undefined)
28075                : undefined;
28076        }
28077
28078        function combineIntersectionThisParam(left: Symbol | undefined, right: Symbol | undefined, mapper: TypeMapper | undefined): Symbol | undefined {
28079            if (!left || !right) {
28080                return left || right;
28081            }
28082            // A signature `this` type might be a read or a write position... It's very possible that it should be invariant
28083            // and we should refuse to merge signatures if there are `this` types and they do not match. However, so as to be
28084            // pessimistic when contextual typing, for now, we'll union the `this` types.
28085            const thisType = getUnionType([getTypeOfSymbol(left), instantiateType(getTypeOfSymbol(right), mapper)]);
28086            return createSymbolWithType(left, thisType);
28087        }
28088
28089        function combineIntersectionParameters(left: Signature, right: Signature, mapper: TypeMapper | undefined) {
28090            const leftCount = getParameterCount(left);
28091            const rightCount = getParameterCount(right);
28092            const longest = leftCount >= rightCount ? left : right;
28093            const shorter = longest === left ? right : left;
28094            const longestCount = longest === left ? leftCount : rightCount;
28095            const eitherHasEffectiveRest = (hasEffectiveRestParameter(left) || hasEffectiveRestParameter(right));
28096            const needsExtraRestElement = eitherHasEffectiveRest && !hasEffectiveRestParameter(longest);
28097            const params = new Array<Symbol>(longestCount + (needsExtraRestElement ? 1 : 0));
28098            for (let i = 0; i < longestCount; i++) {
28099                let longestParamType = tryGetTypeAtPosition(longest, i)!;
28100                if (longest === right) {
28101                    longestParamType = instantiateType(longestParamType, mapper);
28102                }
28103                let shorterParamType = tryGetTypeAtPosition(shorter, i) || unknownType;
28104                if (shorter === right) {
28105                    shorterParamType = instantiateType(shorterParamType, mapper);
28106                }
28107                const unionParamType = getUnionType([longestParamType, shorterParamType]);
28108                const isRestParam = eitherHasEffectiveRest && !needsExtraRestElement && i === (longestCount - 1);
28109                const isOptional = i >= getMinArgumentCount(longest) && i >= getMinArgumentCount(shorter);
28110                const leftName = i >= leftCount ? undefined : getParameterNameAtPosition(left, i);
28111                const rightName = i >= rightCount ? undefined : getParameterNameAtPosition(right, i);
28112
28113                const paramName = leftName === rightName ? leftName :
28114                    !leftName ? rightName :
28115                    !rightName ? leftName :
28116                    undefined;
28117                const paramSymbol = createSymbol(
28118                    SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0),
28119                    paramName || `arg${i}` as __String
28120                );
28121                paramSymbol.type = isRestParam ? createArrayType(unionParamType) : unionParamType;
28122                params[i] = paramSymbol;
28123            }
28124            if (needsExtraRestElement) {
28125                const restParamSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "args" as __String);
28126                restParamSymbol.type = createArrayType(getTypeAtPosition(shorter, longestCount));
28127                if (shorter === right) {
28128                    restParamSymbol.type = instantiateType(restParamSymbol.type, mapper);
28129                }
28130                params[longestCount] = restParamSymbol;
28131            }
28132            return params;
28133        }
28134
28135        function combineSignaturesOfIntersectionMembers(left: Signature, right: Signature): Signature {
28136            const typeParams = left.typeParameters || right.typeParameters;
28137            let paramMapper: TypeMapper | undefined;
28138            if (left.typeParameters && right.typeParameters) {
28139                paramMapper = createTypeMapper(right.typeParameters, left.typeParameters);
28140                // We just use the type parameter defaults from the first signature
28141            }
28142            const declaration = left.declaration;
28143            const params = combineIntersectionParameters(left, right, paramMapper);
28144            const thisParam = combineIntersectionThisParam(left.thisParameter, right.thisParameter, paramMapper);
28145            const minArgCount = Math.max(left.minArgumentCount, right.minArgumentCount);
28146            const result = createSignature(
28147                declaration,
28148                typeParams,
28149                thisParam,
28150                params,
28151                /*resolvedReturnType*/ undefined,
28152                /*resolvedTypePredicate*/ undefined,
28153                minArgCount,
28154                (left.flags | right.flags) & SignatureFlags.PropagatingFlags
28155            );
28156            result.compositeKind = TypeFlags.Intersection;
28157            result.compositeSignatures = concatenate(left.compositeKind === TypeFlags.Intersection && left.compositeSignatures || [left], [right]);
28158            if (paramMapper) {
28159                result.mapper = left.compositeKind === TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper;
28160            }
28161            return result;
28162        }
28163
28164        // If the given type is an object or union type with a single signature, and if that signature has at
28165        // least as many parameters as the given function, return the signature. Otherwise return undefined.
28166        function getContextualCallSignature(type: Type, node: SignatureDeclaration): Signature | undefined {
28167            const signatures = getSignaturesOfType(type, SignatureKind.Call);
28168            const applicableByArity = filter(signatures, s => !isAritySmaller(s, node));
28169            return applicableByArity.length === 1 ? applicableByArity[0] : getIntersectedSignatures(applicableByArity);
28170        }
28171
28172        /** If the contextual signature has fewer parameters than the function expression, do not use it */
28173        function isAritySmaller(signature: Signature, target: SignatureDeclaration) {
28174            let targetParameterCount = 0;
28175            for (; targetParameterCount < target.parameters.length; targetParameterCount++) {
28176                const param = target.parameters[targetParameterCount];
28177                if (param.initializer || param.questionToken || param.dotDotDotToken || isJSDocOptionalParameter(param)) {
28178                    break;
28179                }
28180            }
28181            if (target.parameters.length && parameterIsThisKeyword(target.parameters[0])) {
28182                targetParameterCount--;
28183            }
28184            return !hasEffectiveRestParameter(signature) && getParameterCount(signature) < targetParameterCount;
28185        }
28186
28187        function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature | undefined {
28188            // Only function expressions, arrow functions, and object literal methods are contextually typed.
28189            return isFunctionExpressionOrArrowFunction(node) || isObjectLiteralMethod(node)
28190                ? getContextualSignature(node as FunctionExpression)
28191                : undefined;
28192        }
28193
28194        // Return the contextual signature for a given expression node. A contextual type provides a
28195        // contextual signature if it has a single call signature and if that call signature is non-generic.
28196        // If the contextual type is a union type, get the signature from each type possible and if they are
28197        // all identical ignoring their return type, the result is same signature but with return type as
28198        // union type of return types from these signatures
28199        function getContextualSignature(node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature | undefined {
28200            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
28201            const typeTagSignature = getSignatureOfTypeTag(node);
28202            if (typeTagSignature) {
28203                return typeTagSignature;
28204            }
28205            const type = getApparentTypeOfContextualType(node, ContextFlags.Signature);
28206            if (!type) {
28207                return undefined;
28208            }
28209            if (!(type.flags & TypeFlags.Union)) {
28210                return getContextualCallSignature(type, node);
28211            }
28212            let signatureList: Signature[] | undefined;
28213            const types = (type as UnionType).types;
28214            for (const current of types) {
28215                const signature = getContextualCallSignature(current, node);
28216                if (signature) {
28217                    if (!signatureList) {
28218                        // This signature will contribute to contextual union signature
28219                        signatureList = [signature];
28220                    }
28221                    else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) {
28222                        // Signatures aren't identical, do not use
28223                        return undefined;
28224                    }
28225                    else {
28226                        // Use this signature for contextual union signature
28227                        signatureList.push(signature);
28228                    }
28229                }
28230            }
28231            // Result is union of signatures collected (return type is union of return types of this signature set)
28232            if (signatureList) {
28233                return signatureList.length === 1 ? signatureList[0] : createUnionSignature(signatureList[0], signatureList);
28234            }
28235        }
28236
28237        function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type {
28238            if (languageVersion < ScriptTarget.ES2015) {
28239                checkExternalEmitHelpers(node, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray);
28240            }
28241
28242            const arrayOrIterableType = checkExpression(node.expression, checkMode);
28243            return checkIteratedTypeOrElementType(IterationUse.Spread, arrayOrIterableType, undefinedType, node.expression);
28244        }
28245
28246        function checkSyntheticExpression(node: SyntheticExpression): Type {
28247            return node.isSpread ? getIndexedAccessType(node.type, numberType) : node.type;
28248        }
28249
28250        function hasDefaultValue(node: BindingElement | Expression): boolean {
28251            return (node.kind === SyntaxKind.BindingElement && !!(node as BindingElement).initializer) ||
28252                (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken);
28253        }
28254
28255        function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): Type {
28256            const elements = node.elements;
28257            const elementCount = elements.length;
28258            const elementTypes: Type[] = [];
28259            const elementFlags: ElementFlags[] = [];
28260            const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined);
28261            const inDestructuringPattern = isAssignmentTarget(node);
28262            const inConstContext = isConstContext(node);
28263            let hasOmittedExpression = false;
28264            for (let i = 0; i < elementCount; i++) {
28265                const e = elements[i];
28266                if (e.kind === SyntaxKind.SpreadElement) {
28267                    if (languageVersion < ScriptTarget.ES2015) {
28268                        checkExternalEmitHelpers(e, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray);
28269                    }
28270                    const spreadType = checkExpression((e as SpreadElement).expression, checkMode, forceTuple);
28271                    if (isArrayLikeType(spreadType)) {
28272                        elementTypes.push(spreadType);
28273                        elementFlags.push(ElementFlags.Variadic);
28274                    }
28275                    else if (inDestructuringPattern) {
28276                        // Given the following situation:
28277                        //    var c: {};
28278                        //    [...c] = ["", 0];
28279                        //
28280                        // c is represented in the tree as a spread element in an array literal.
28281                        // But c really functions as a rest element, and its purpose is to provide
28282                        // a contextual type for the right hand side of the assignment. Therefore,
28283                        // instead of calling checkExpression on "...c", which will give an error
28284                        // if c is not iterable/array-like, we need to act as if we are trying to
28285                        // get the contextual element type from it. So we do something similar to
28286                        // getContextualTypeForElementExpression, which will crucially not error
28287                        // if there is no index type / iterated type.
28288                        const restElementType = getIndexTypeOfType(spreadType, numberType) ||
28289                            getIteratedTypeOrElementType(IterationUse.Destructuring, spreadType, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false) ||
28290                            unknownType;
28291                        elementTypes.push(restElementType);
28292                        elementFlags.push(ElementFlags.Rest);
28293                    }
28294                    else {
28295                        elementTypes.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, (e as SpreadElement).expression));
28296                        elementFlags.push(ElementFlags.Rest);
28297                    }
28298                }
28299                else if (exactOptionalPropertyTypes && e.kind === SyntaxKind.OmittedExpression) {
28300                    hasOmittedExpression = true;
28301                    elementTypes.push(missingType);
28302                    elementFlags.push(ElementFlags.Optional);
28303                }
28304                else {
28305                    const elementContextualType = getContextualTypeForElementExpression(contextualType, elementTypes.length);
28306                    const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple);
28307                    elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
28308                    elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required);
28309                    if (contextualType && someType(contextualType, isTupleLikeType) && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) {
28310                        const inferenceContext = getInferenceContext(node);
28311                        Debug.assert(inferenceContext);  // In CheckMode.Inferential we should always have an inference context
28312                        addIntraExpressionInferenceSite(inferenceContext, e, type);
28313                    }
28314                }
28315            }
28316            if (inDestructuringPattern) {
28317                return createTupleType(elementTypes, elementFlags);
28318            }
28319            if (forceTuple || inConstContext || contextualType && someType(contextualType, isTupleLikeType)) {
28320                return createArrayLiteralType(createTupleType(elementTypes, elementFlags, /*readonly*/ inConstContext));
28321            }
28322            return createArrayLiteralType(createArrayType(elementTypes.length ?
28323                getUnionType(sameMap(elementTypes, (t, i) => elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), UnionReduction.Subtype) :
28324                strictNullChecks ? implicitNeverType : undefinedWideningType, inConstContext));
28325        }
28326
28327        function createArrayLiteralType(type: Type) {
28328            if (!(getObjectFlags(type) & ObjectFlags.Reference)) {
28329                return type;
28330            }
28331            let literalType = (type as TypeReference).literalType;
28332            if (!literalType) {
28333                literalType = (type as TypeReference).literalType = cloneTypeReference(type as TypeReference);
28334                literalType.objectFlags |= ObjectFlags.ArrayLiteral | ObjectFlags.ContainsObjectOrArrayLiteral;
28335            }
28336            return literalType;
28337        }
28338
28339        function isNumericName(name: DeclarationName): boolean {
28340            switch (name.kind) {
28341                case SyntaxKind.ComputedPropertyName:
28342                    return isNumericComputedName(name);
28343                case SyntaxKind.Identifier:
28344                    return isNumericLiteralName(name.escapedText);
28345                case SyntaxKind.NumericLiteral:
28346                case SyntaxKind.StringLiteral:
28347                    return isNumericLiteralName(name.text);
28348                default:
28349                    return false;
28350            }
28351        }
28352
28353        function isNumericComputedName(name: ComputedPropertyName): boolean {
28354            // It seems odd to consider an expression of type Any to result in a numeric name,
28355            // but this behavior is consistent with checkIndexedAccess
28356            return isTypeAssignableToKind(checkComputedPropertyName(name), TypeFlags.NumberLike);
28357        }
28358
28359        function checkComputedPropertyName(node: ComputedPropertyName): Type {
28360            const links = getNodeLinks(node.expression);
28361            if (!links.resolvedType) {
28362                if ((isTypeLiteralNode(node.parent.parent) || isClassLike(node.parent.parent) || isInterfaceDeclaration(node.parent.parent))
28363                    && isBinaryExpression(node.expression) && node.expression.operatorToken.kind === SyntaxKind.InKeyword
28364                    && node.parent.kind !== SyntaxKind.GetAccessor && node.parent.kind !== SyntaxKind.SetAccessor) {
28365                    return links.resolvedType = errorType;
28366                }
28367                links.resolvedType = checkExpression(node.expression);
28368                // The computed property name of a non-static class field within a loop must be stored in a block-scoped binding.
28369                // (It needs to be bound at class evaluation time.)
28370                if (isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) && isClassExpression(node.parent.parent)) {
28371                    const container = getEnclosingBlockScopeContainer(node.parent.parent);
28372                    const enclosingIterationStatement = getEnclosingIterationStatement(container);
28373                    if (enclosingIterationStatement) {
28374                        // The computed field name will use a block scoped binding which can be unique for each iteration of the loop.
28375                        getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
28376                        // The generated variable which stores the computed field name must be block-scoped.
28377                        getNodeLinks(node).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
28378                        // The generated variable which stores the class must be block-scoped.
28379                        getNodeLinks(node.parent.parent).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
28380                    }
28381                }
28382                // This will allow types number, string, symbol or any. It will also allow enums, the unknown
28383                // type, and any union of these types (like string | number).
28384                if (links.resolvedType.flags & TypeFlags.Nullable ||
28385                    !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) &&
28386                    !isTypeAssignableTo(links.resolvedType, stringNumberSymbolType)) {
28387                    error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
28388                }
28389            }
28390
28391            return links.resolvedType;
28392        }
28393
28394        function isSymbolWithNumericName(symbol: Symbol) {
28395            const firstDecl = symbol.declarations?.[0];
28396            return isNumericLiteralName(symbol.escapedName) || (firstDecl && isNamedDeclaration(firstDecl) && isNumericName(firstDecl.name));
28397        }
28398
28399        function isSymbolWithSymbolName(symbol: Symbol) {
28400            const firstDecl = symbol.declarations?.[0];
28401            return isKnownSymbol(symbol) || (firstDecl && isNamedDeclaration(firstDecl) && isComputedPropertyName(firstDecl.name) &&
28402                isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol));
28403        }
28404
28405        function getObjectLiteralIndexInfo(node: ObjectLiteralExpression, offset: number, properties: Symbol[], keyType: Type): IndexInfo {
28406            const propTypes: Type[] = [];
28407            for (let i = offset; i < properties.length; i++) {
28408                const prop = properties[i];
28409                if (keyType === stringType && !isSymbolWithSymbolName(prop) ||
28410                    keyType === numberType && isSymbolWithNumericName(prop) ||
28411                    keyType === esSymbolType && isSymbolWithSymbolName(prop)) {
28412                    propTypes.push(getTypeOfSymbol(properties[i]));
28413                }
28414            }
28415            const unionType = propTypes.length ? getUnionType(propTypes, UnionReduction.Subtype) : undefinedType;
28416            return createIndexInfo(keyType, unionType, isConstContext(node));
28417        }
28418
28419        function getImmediateAliasedSymbol(symbol: Symbol): Symbol | undefined {
28420            Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here.");
28421            const links = getSymbolLinks(symbol);
28422            if (!links.immediateTarget) {
28423                const node = getDeclarationOfAliasSymbol(symbol);
28424                if (!node) return Debug.fail();
28425                links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true);
28426            }
28427
28428            return links.immediateTarget;
28429        }
28430
28431        function checkObjectLiteral(node: ObjectLiteralExpression, checkMode?: CheckMode): Type {
28432            const inDestructuringPattern = isAssignmentTarget(node);
28433            // Grammar checking
28434            checkGrammarObjectLiteralExpression(node, inDestructuringPattern);
28435
28436            const allPropertiesTable = strictNullChecks ? createSymbolTable() : undefined;
28437            let propertiesTable = createSymbolTable();
28438            let propertiesArray: Symbol[] = [];
28439            let spread: Type = emptyObjectType;
28440
28441            const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined);
28442            const contextualTypeHasPattern = contextualType && contextualType.pattern &&
28443                (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
28444            const inConstContext = isConstContext(node);
28445            const checkFlags = inConstContext ? CheckFlags.Readonly : 0;
28446            const isInJavascript = isInJSFile(node) && !isInJsonFile(node);
28447            const enumTag = getJSDocEnumTag(node);
28448            const isJSObjectLiteral = !contextualType && isInJavascript && !enumTag;
28449            let objectFlags: ObjectFlags = freshObjectLiteralFlag;
28450            let patternWithComputedProperties = false;
28451            let hasComputedStringProperty = false;
28452            let hasComputedNumberProperty = false;
28453            let hasComputedSymbolProperty = false;
28454
28455            // Spreads may cause an early bail; ensure computed names are always checked (this is cached)
28456            // As otherwise they may not be checked until exports for the type at this position are retrieved,
28457            // which may never occur.
28458            for (const elem of node.properties) {
28459                if (elem.name && isComputedPropertyName(elem.name)) {
28460                    checkComputedPropertyName(elem.name);
28461                }
28462            }
28463
28464            let offset = 0;
28465            for (const memberDecl of node.properties) {
28466                let member = getSymbolOfNode(memberDecl);
28467                const computedNameType = memberDecl.name && memberDecl.name.kind === SyntaxKind.ComputedPropertyName ?
28468                    checkComputedPropertyName(memberDecl.name) : undefined;
28469                if (memberDecl.kind === SyntaxKind.PropertyAssignment ||
28470                    memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ||
28471                    isObjectLiteralMethod(memberDecl)) {
28472                    let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) :
28473                        // avoid resolving the left side of the ShorthandPropertyAssignment outside of the destructuring
28474                        // for error recovery purposes. For example, if a user wrote `{ a = 100 }` instead of `{ a: 100 }`.
28475                        // we don't want to say "could not find 'a'".
28476                        memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) :
28477                        checkObjectLiteralMethod(memberDecl, checkMode);
28478                    if (isInJavascript) {
28479                        const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl);
28480                        if (jsDocType) {
28481                            checkTypeAssignableTo(type, jsDocType, memberDecl);
28482                            type = jsDocType;
28483                        }
28484                        else if (enumTag && enumTag.typeExpression) {
28485                            checkTypeAssignableTo(type, getTypeFromTypeNode(enumTag.typeExpression), memberDecl);
28486                        }
28487                    }
28488                    objectFlags |= getObjectFlags(type) & ObjectFlags.PropagatingFlags;
28489                    const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined;
28490                    const prop = nameType ?
28491                        createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), checkFlags | CheckFlags.Late) :
28492                        createSymbol(SymbolFlags.Property | member.flags, member.escapedName, checkFlags);
28493                    if (nameType) {
28494                        prop.nameType = nameType;
28495                    }
28496
28497                    if (inDestructuringPattern) {
28498                        // If object literal is an assignment pattern and if the assignment pattern specifies a default value
28499                        // for the property, make the property optional.
28500                        const isOptional =
28501                            (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) ||
28502                            (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment && memberDecl.objectAssignmentInitializer);
28503                        if (isOptional) {
28504                            prop.flags |= SymbolFlags.Optional;
28505                        }
28506                    }
28507                    else if (contextualTypeHasPattern && !(getObjectFlags(contextualType) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) {
28508                        // If object literal is contextually typed by the implied type of a binding pattern, and if the
28509                        // binding pattern specifies a default value for the property, make the property optional.
28510                        const impliedProp = getPropertyOfType(contextualType, member.escapedName);
28511                        if (impliedProp) {
28512                            prop.flags |= impliedProp.flags & SymbolFlags.Optional;
28513                        }
28514
28515                        else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, stringType)) {
28516                            error(memberDecl.name, Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
28517                                symbolToString(member), typeToString(contextualType));
28518                        }
28519                    }
28520
28521                    prop.declarations = member.declarations;
28522                    prop.parent = member.parent;
28523                    if (member.valueDeclaration) {
28524                        prop.valueDeclaration = member.valueDeclaration;
28525                    }
28526
28527                    prop.type = type;
28528                    prop.target = member;
28529                    member = prop;
28530                    allPropertiesTable?.set(prop.escapedName, prop);
28531
28532                    if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
28533                        (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) {
28534                        const inferenceContext = getInferenceContext(node);
28535                        Debug.assert(inferenceContext);  // In CheckMode.Inferential we should always have an inference context
28536                        const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl;
28537                        addIntraExpressionInferenceSite(inferenceContext, inferenceNode, type);
28538                    }
28539                    if (type.symbol && (type.symbol.flags & SymbolFlags.Annotation)) {
28540                        error(memberDecl, Diagnostics.Annotation_cannot_be_used_as_a_value);
28541                    }
28542                }
28543                else if (memberDecl.kind === SyntaxKind.SpreadAssignment) {
28544                    if (languageVersion < ScriptTarget.ES2015) {
28545                        checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign);
28546                    }
28547                    if (propertiesArray.length > 0) {
28548                        spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
28549                        propertiesArray = [];
28550                        propertiesTable = createSymbolTable();
28551                        hasComputedStringProperty = false;
28552                        hasComputedNumberProperty = false;
28553                        hasComputedSymbolProperty = false;
28554                    }
28555                    const type = getReducedType(checkExpression(memberDecl.expression));
28556                    if (isValidSpreadType(type)) {
28557                        const mergedType = tryMergeUnionOfObjectTypeAndEmptyObject(type, inConstContext);
28558                        if (allPropertiesTable) {
28559                            checkSpreadPropOverrides(mergedType, allPropertiesTable, memberDecl);
28560                        }
28561                        offset = propertiesArray.length;
28562                        if (isErrorType(spread)) {
28563                            continue;
28564                        }
28565                        spread = getSpreadType(spread, mergedType, node.symbol, objectFlags, inConstContext);
28566                    }
28567                    else {
28568                        error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
28569                        spread = errorType;
28570                    }
28571                    continue;
28572                }
28573                else {
28574                    // TypeScript 1.0 spec (April 2014)
28575                    // A get accessor declaration is processed in the same manner as
28576                    // an ordinary function declaration(section 6.1) with no parameters.
28577                    // A set accessor declaration is processed in the same manner
28578                    // as an ordinary function declaration with a single parameter and a Void return type.
28579                    Debug.assert(memberDecl.kind === SyntaxKind.GetAccessor || memberDecl.kind === SyntaxKind.SetAccessor);
28580                    checkNodeDeferred(memberDecl);
28581                }
28582
28583                if (computedNameType && !(computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique)) {
28584                    if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) {
28585                        if (isTypeAssignableTo(computedNameType, numberType)) {
28586                            hasComputedNumberProperty = true;
28587                        }
28588                        else if (isTypeAssignableTo(computedNameType, esSymbolType)) {
28589                            hasComputedSymbolProperty = true;
28590                        }
28591                        else {
28592                            hasComputedStringProperty = true;
28593                        }
28594                        if (inDestructuringPattern) {
28595                            patternWithComputedProperties = true;
28596                        }
28597                    }
28598                }
28599                else {
28600                    propertiesTable.set(member.escapedName, member);
28601                }
28602                propertiesArray.push(member);
28603            }
28604
28605            // If object literal is contextually typed by the implied type of a binding pattern, augment the result
28606            // type with those properties for which the binding pattern specifies a default value.
28607            // If the object literal is spread into another object literal, skip this step and let the top-level object
28608            // literal handle it instead. Note that this might require full traversal to the root pattern's parent
28609            // as it's the guaranteed to be the common ancestor of the pattern node and the current object node.
28610            // It's not possible to check if the immediate parent node is a spread assignment
28611            // since the type flows in non-obvious ways through conditional expressions, IIFEs and more.
28612            if (contextualTypeHasPattern) {
28613                const rootPatternParent = findAncestor(contextualType.pattern!.parent, n =>
28614                    n.kind === SyntaxKind.VariableDeclaration ||
28615                    n.kind === SyntaxKind.BinaryExpression ||
28616                    n.kind === SyntaxKind.Parameter
28617                );
28618                const spreadOrOutsideRootObject = findAncestor(node, n =>
28619                    n === rootPatternParent ||
28620                    n.kind === SyntaxKind.SpreadAssignment
28621                )!;
28622
28623                if (spreadOrOutsideRootObject.kind !== SyntaxKind.SpreadAssignment) {
28624                    for (const prop of getPropertiesOfType(contextualType)) {
28625                        if (!propertiesTable.get(prop.escapedName) && !getPropertyOfType(spread, prop.escapedName)) {
28626                            if (!(prop.flags & SymbolFlags.Optional)) {
28627                                error(prop.valueDeclaration || (prop as TransientSymbol).bindingElement,
28628                                    Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value);
28629                            }
28630                            propertiesTable.set(prop.escapedName, prop);
28631                            propertiesArray.push(prop);
28632                        }
28633                    }
28634                }
28635            }
28636
28637            if (isErrorType(spread)) {
28638                return errorType;
28639            }
28640
28641            if (spread !== emptyObjectType) {
28642                if (propertiesArray.length > 0) {
28643                    spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
28644                    propertiesArray = [];
28645                    propertiesTable = createSymbolTable();
28646                    hasComputedStringProperty = false;
28647                    hasComputedNumberProperty = false;
28648                }
28649                // remap the raw emptyObjectType fed in at the top into a fresh empty object literal type, unique to this use site
28650                return mapType(spread, t => t === emptyObjectType ? createObjectLiteralType() : t);
28651            }
28652
28653            return createObjectLiteralType();
28654
28655            function createObjectLiteralType() {
28656                const indexInfos = [];
28657                if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, stringType));
28658                if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, numberType));
28659                if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, esSymbolType));
28660                const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos);
28661                result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral;
28662                if (isJSObjectLiteral) {
28663                    result.objectFlags |= ObjectFlags.JSLiteral;
28664                }
28665                if (patternWithComputedProperties) {
28666                    result.objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
28667                }
28668                if (inDestructuringPattern) {
28669                    result.pattern = node;
28670                }
28671                return result;
28672            }
28673        }
28674
28675        function isValidSpreadType(type: Type): boolean {
28676            const t = removeDefinitelyFalsyTypes(mapType(type, getBaseConstraintOrType));
28677            return !!(t.flags & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ||
28678                t.flags & TypeFlags.UnionOrIntersection && every((t as UnionOrIntersectionType).types, isValidSpreadType));
28679        }
28680
28681        function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) {
28682            checkJsxOpeningLikeElementOrOpeningFragment(node);
28683        }
28684
28685        function checkJsxSelfClosingElement(node: JsxSelfClosingElement, _checkMode: CheckMode | undefined): Type {
28686            checkNodeDeferred(node);
28687            return getJsxElementTypeAt(node) || anyType;
28688        }
28689
28690        function checkJsxElementDeferred(node: JsxElement) {
28691            // Check attributes
28692            checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement);
28693
28694            // Perform resolution on the closing tag so that rename/go to definition/etc work
28695            if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) {
28696                getIntrinsicTagSymbol(node.closingElement);
28697            }
28698            else {
28699                checkExpression(node.closingElement.tagName);
28700            }
28701
28702            checkJsxChildren(node);
28703        }
28704
28705        function checkJsxElement(node: JsxElement, _checkMode: CheckMode | undefined): Type {
28706            checkNodeDeferred(node);
28707
28708            return getJsxElementTypeAt(node) || anyType;
28709        }
28710
28711        function checkJsxFragment(node: JsxFragment): Type {
28712            checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment);
28713
28714            // by default, jsx:'react' will use jsxFactory = React.createElement and jsxFragmentFactory = React.Fragment
28715            // if jsxFactory compiler option is provided, ensure jsxFragmentFactory compiler option or @jsxFrag pragma is provided too
28716            const nodeSourceFile = getSourceFileOfNode(node);
28717            if (getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx"))
28718                && !compilerOptions.jsxFragmentFactory && !nodeSourceFile.pragmas.has("jsxfrag")) {
28719                error(node, compilerOptions.jsxFactory
28720                    ? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option
28721                    : Diagnostics.An_jsxFrag_pragma_is_required_when_using_an_jsx_pragma_with_JSX_fragments);
28722            }
28723
28724            checkJsxChildren(node);
28725            return getJsxElementTypeAt(node) || anyType;
28726        }
28727
28728        function isHyphenatedJsxName(name: string | __String) {
28729            return stringContains(name as string, "-");
28730        }
28731
28732        /**
28733         * Returns true iff React would emit this tag name as a string rather than an identifier or qualified name
28734         */
28735        function isJsxIntrinsicIdentifier(tagName: JsxTagNameExpression): boolean {
28736            return tagName.kind === SyntaxKind.Identifier && isIntrinsicJsxName(tagName.escapedText);
28737        }
28738
28739        function checkJsxAttribute(node: JsxAttribute, checkMode?: CheckMode) {
28740            return node.initializer
28741                ? checkExpressionForMutableLocation(node.initializer, checkMode)
28742                : trueType;  // <Elem attr /> is sugar for <Elem attr={true} />
28743        }
28744
28745        /**
28746         * Get attributes type of the JSX opening-like element. The result is from resolving "attributes" property of the opening-like element.
28747         *
28748         * @param openingLikeElement a JSX opening-like element
28749         * @param filter a function to remove attributes that will not participate in checking whether attributes are assignable
28750         * @return an anonymous type (similar to the one returned by checkObjectLiteral) in which its properties are attributes property.
28751         * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral,
28752         * which also calls getSpreadType.
28753         */
28754        function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) {
28755            const attributes = openingLikeElement.attributes;
28756            const attributesType = getContextualType(attributes, ContextFlags.None);
28757            const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined;
28758            let attributesTable = createSymbolTable();
28759            let spread: Type = emptyJsxObjectType;
28760            let hasSpreadAnyType = false;
28761            let typeToIntersect: Type | undefined;
28762            let explicitlySpecifyChildrenAttribute = false;
28763            let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes;
28764            const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement));
28765
28766            for (const attributeDecl of attributes.properties) {
28767                const member = attributeDecl.symbol;
28768                if (isJsxAttribute(attributeDecl)) {
28769                    const exprType = checkJsxAttribute(attributeDecl, checkMode);
28770                    objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags;
28771
28772                    const attributeSymbol = createSymbol(SymbolFlags.Property | member.flags, member.escapedName);
28773                    attributeSymbol.declarations = member.declarations;
28774                    attributeSymbol.parent = member.parent;
28775                    if (member.valueDeclaration) {
28776                        attributeSymbol.valueDeclaration = member.valueDeclaration;
28777                    }
28778                    attributeSymbol.type = exprType;
28779                    attributeSymbol.target = member;
28780                    attributesTable.set(attributeSymbol.escapedName, attributeSymbol);
28781                    allAttributesTable?.set(attributeSymbol.escapedName, attributeSymbol);
28782                    if (attributeDecl.name.escapedText === jsxChildrenPropertyName) {
28783                        explicitlySpecifyChildrenAttribute = true;
28784                    }
28785                    if (attributesType) {
28786                        const prop = getPropertyOfType(attributesType, member.escapedName);
28787                        if (prop && prop.declarations && isDeprecatedSymbol(prop)) {
28788                            addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string);
28789                        }
28790                    }
28791                }
28792                else {
28793                    Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute);
28794                    if (attributesTable.size > 0) {
28795                        spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false);
28796                        attributesTable = createSymbolTable();
28797                    }
28798                    const exprType = getReducedType(checkExpressionCached(attributeDecl.expression, checkMode));
28799                    if (isTypeAny(exprType)) {
28800                        hasSpreadAnyType = true;
28801                    }
28802                    if (isValidSpreadType(exprType)) {
28803                        spread = getSpreadType(spread, exprType, attributes.symbol, objectFlags, /*readonly*/ false);
28804                        if (allAttributesTable) {
28805                            checkSpreadPropOverrides(exprType, allAttributesTable, attributeDecl);
28806                        }
28807                    }
28808                    else {
28809                        error(attributeDecl.expression, Diagnostics.Spread_types_may_only_be_created_from_object_types);
28810                        typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType;
28811                    }
28812                }
28813            }
28814
28815            if (!hasSpreadAnyType) {
28816                if (attributesTable.size > 0) {
28817                    spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false);
28818                }
28819            }
28820
28821            // Handle children attribute
28822            const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? openingLikeElement.parent as JsxElement : undefined;
28823            // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement
28824            if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) {
28825                const childrenTypes: Type[] = checkJsxChildren(parent, checkMode);
28826
28827                if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
28828                    // Error if there is a attribute named "children" explicitly specified and children element.
28829                    // This is because children element will overwrite the value from attributes.
28830                    // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread.
28831                    if (explicitlySpecifyChildrenAttribute) {
28832                        error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName));
28833                    }
28834
28835                    const contextualType = getApparentTypeOfContextualType(openingLikeElement.attributes, /*contextFlags*/ undefined);
28836                    const childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName);
28837                    // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process
28838                    const childrenPropSymbol = createSymbol(SymbolFlags.Property, jsxChildrenPropertyName);
28839                    childrenPropSymbol.type = childrenTypes.length === 1 ? childrenTypes[0] :
28840                        childrenContextualType && someType(childrenContextualType, isTupleLikeType) ? createTupleType(childrenTypes) :
28841                        createArrayType(getUnionType(childrenTypes));
28842                    // Fake up a property declaration for the children
28843                    childrenPropSymbol.valueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined);
28844                    setParent(childrenPropSymbol.valueDeclaration, attributes);
28845                    childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol;
28846                    const childPropMap = createSymbolTable();
28847                    childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol);
28848                    spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, emptyArray),
28849                        attributes.symbol, objectFlags, /*readonly*/ false);
28850
28851                }
28852            }
28853
28854            if (hasSpreadAnyType) {
28855                return anyType;
28856            }
28857            if (typeToIntersect && spread !== emptyJsxObjectType) {
28858                return getIntersectionType([typeToIntersect, spread]);
28859            }
28860            return typeToIntersect || (spread === emptyJsxObjectType ? createJsxAttributesType() : spread);
28861
28862            /**
28863             * Create anonymous type from given attributes symbol table.
28864             * @param symbol a symbol of JsxAttributes containing attributes corresponding to attributesTable
28865             * @param attributesTable a symbol table of attributes property
28866             */
28867            function createJsxAttributesType() {
28868                objectFlags |= freshObjectLiteralFlag;
28869                const result = createAnonymousType(attributes.symbol, attributesTable, emptyArray, emptyArray, emptyArray);
28870                result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral;
28871                return result;
28872            }
28873        }
28874
28875        function checkJsxChildren(node: JsxElement | JsxFragment, checkMode?: CheckMode) {
28876            const childrenTypes: Type[] = [];
28877            for (const child of node.children) {
28878                // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that
28879                // because then type of children property will have constituent of string type.
28880                if (child.kind === SyntaxKind.JsxText) {
28881                    if (!child.containsOnlyTriviaWhiteSpaces) {
28882                        childrenTypes.push(stringType);
28883                    }
28884                }
28885                else if (child.kind === SyntaxKind.JsxExpression && !child.expression) {
28886                    continue; // empty jsx expressions don't *really* count as present children
28887                }
28888                else {
28889                    childrenTypes.push(checkExpressionForMutableLocation(child, checkMode));
28890                }
28891            }
28892            return childrenTypes;
28893        }
28894
28895        function checkSpreadPropOverrides(type: Type, props: SymbolTable, spread: SpreadAssignment | JsxSpreadAttribute) {
28896            for (const right of getPropertiesOfType(type)) {
28897                if (!(right.flags & SymbolFlags.Optional)) {
28898                    const left = props.get(right.escapedName);
28899                    if (left) {
28900                        const diagnostic = error(left.valueDeclaration, Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, unescapeLeadingUnderscores(left.escapedName));
28901                        addRelatedInfo(diagnostic, createDiagnosticForNode(spread, Diagnostics.This_spread_always_overwrites_this_property));
28902                    }
28903                }
28904            }
28905        }
28906
28907        /**
28908         * Check attributes property of opening-like element. This function is called during chooseOverload to get call signature of a JSX opening-like element.
28909         * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used)
28910         * @param node a JSXAttributes to be resolved of its type
28911         */
28912        function checkJsxAttributes(node: JsxAttributes, checkMode: CheckMode | undefined) {
28913            return createJsxAttributesTypeFromAttributesProperty(node.parent, checkMode);
28914        }
28915
28916        function getJsxType(name: __String, location: Node | undefined) {
28917            const namespace = getJsxNamespaceAt(location);
28918            const exports = namespace && getExportsOfSymbol(namespace);
28919            const typeSymbol = exports && getSymbol(exports, name, SymbolFlags.Type);
28920            return typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType;
28921        }
28922
28923        /**
28924         * Looks up an intrinsic tag name and returns a symbol that either points to an intrinsic
28925         * property (in which case nodeLinks.jsxFlags will be IntrinsicNamedElement) or an intrinsic
28926         * string index signature (in which case nodeLinks.jsxFlags will be IntrinsicIndexedElement).
28927         * May also return unknownSymbol if both of these lookups fail.
28928         */
28929        function getIntrinsicTagSymbol(node: JsxOpeningLikeElement | JsxClosingElement): Symbol {
28930            const links = getNodeLinks(node);
28931            if (!links.resolvedSymbol) {
28932                const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, node);
28933                if (!isErrorType(intrinsicElementsType)) {
28934                    // Property case
28935                    if (!isIdentifier(node.tagName)) return Debug.fail();
28936                    const intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText);
28937                    if (intrinsicProp) {
28938                        links.jsxFlags |= JsxFlags.IntrinsicNamedElement;
28939                        return links.resolvedSymbol = intrinsicProp;
28940                    }
28941
28942                    // Intrinsic string indexer case
28943                    const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, stringType);
28944                    if (indexSignatureType) {
28945                        links.jsxFlags |= JsxFlags.IntrinsicIndexedElement;
28946                        return links.resolvedSymbol = intrinsicElementsType.symbol;
28947                    }
28948
28949                    // Wasn't found
28950                    error(node, Diagnostics.Property_0_does_not_exist_on_type_1, idText(node.tagName), "JSX." + JsxNames.IntrinsicElements);
28951                    return links.resolvedSymbol = unknownSymbol;
28952                }
28953                else {
28954                    if (noImplicitAny) {
28955                        error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeLeadingUnderscores(JsxNames.IntrinsicElements));
28956                    }
28957                    return links.resolvedSymbol = unknownSymbol;
28958                }
28959            }
28960            return links.resolvedSymbol;
28961        }
28962
28963        function getJsxNamespaceContainerForImplicitImport(location: Node | undefined): Symbol | undefined {
28964            const file = location && getSourceFileOfNode(location);
28965            const links = file && getNodeLinks(file);
28966            if (links && links.jsxImplicitImportContainer === false) {
28967                return undefined;
28968            }
28969            if (links && links.jsxImplicitImportContainer) {
28970                return links.jsxImplicitImportContainer;
28971            }
28972            const runtimeImportSpecifier = getJSXRuntimeImport(getJSXImplicitImportBase(compilerOptions, file), compilerOptions);
28973            if (!runtimeImportSpecifier) {
28974                return undefined;
28975            }
28976            const isClassic = getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic;
28977            const errorMessage = isClassic
28978                                    ? Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option
28979                                    : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations;
28980            const mod = resolveExternalModule(location!, runtimeImportSpecifier, errorMessage, location!);
28981            const result = mod && mod !== unknownSymbol ? getMergedSymbol(resolveSymbol(mod)) : undefined;
28982            if (links) {
28983                links.jsxImplicitImportContainer = result || false;
28984            }
28985            return result;
28986        }
28987
28988        function getJsxNamespaceAt(location: Node | undefined): Symbol {
28989            const links = location && getNodeLinks(location);
28990            if (links && links.jsxNamespace) {
28991                return links.jsxNamespace;
28992            }
28993            if (!links || links.jsxNamespace !== false) {
28994                let resolvedNamespace = getJsxNamespaceContainerForImplicitImport(location);
28995
28996                if (!resolvedNamespace || resolvedNamespace === unknownSymbol) {
28997                    const namespaceName = getJsxNamespace(location);
28998                    resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false);
28999                }
29000
29001                if (resolvedNamespace) {
29002                    const candidate = resolveSymbol(getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, SymbolFlags.Namespace));
29003                    if (candidate && candidate !== unknownSymbol) {
29004                        if (links) {
29005                            links.jsxNamespace = candidate;
29006                        }
29007                        return candidate;
29008                    }
29009                }
29010                if (links) {
29011                    links.jsxNamespace = false;
29012                }
29013            }
29014            // JSX global fallback
29015            const s = resolveSymbol(getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined));
29016            if (s === unknownSymbol) {
29017                return undefined!; // TODO: GH#18217
29018            }
29019            return s!; // TODO: GH#18217
29020        }
29021
29022        /**
29023         * Look into JSX namespace and then look for container with matching name as nameOfAttribPropContainer.
29024         * Get a single property from that container if existed. Report an error if there are more than one property.
29025         *
29026         * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer
29027         *          if other string is given or the container doesn't exist, return undefined.
29028         */
29029        function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String, jsxNamespace: Symbol): __String | undefined {
29030            // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol]
29031            const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports!, nameOfAttribPropContainer, SymbolFlags.Type);
29032            // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type]
29033            const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym);
29034            // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute
29035            const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType);
29036            if (propertiesOfJsxElementAttribPropInterface) {
29037                // Element Attributes has zero properties, so the element attributes type will be the class instance type
29038                if (propertiesOfJsxElementAttribPropInterface.length === 0) {
29039                    return "" as __String;
29040                }
29041                // Element Attributes has one property, so the element attributes type will be the type of the corresponding
29042                // property of the class instance type
29043                else if (propertiesOfJsxElementAttribPropInterface.length === 1) {
29044                    return propertiesOfJsxElementAttribPropInterface[0].escapedName;
29045                }
29046                else if (propertiesOfJsxElementAttribPropInterface.length > 1 && jsxElementAttribPropInterfaceSym.declarations) {
29047                    // More than one property on ElementAttributesProperty is an error
29048                    error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer));
29049                }
29050            }
29051            return undefined;
29052        }
29053
29054        function getJsxLibraryManagedAttributes(jsxNamespace: Symbol) {
29055            // JSX.LibraryManagedAttributes [symbol]
29056            return jsxNamespace && getSymbol(jsxNamespace.exports!, JsxNames.LibraryManagedAttributes, SymbolFlags.Type);
29057        }
29058
29059        /// e.g. "props" for React.d.ts,
29060        /// or 'undefined' if ElementAttributesProperty doesn't exist (which means all
29061        ///     non-intrinsic elements' attributes type is 'any'),
29062        /// or '' if it has 0 properties (which means every
29063        ///     non-intrinsic elements' attributes type is the element instance type)
29064        function getJsxElementPropertiesName(jsxNamespace: Symbol) {
29065            return getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer, jsxNamespace);
29066        }
29067
29068        function getJsxElementChildrenPropertyName(jsxNamespace: Symbol): __String | undefined {
29069            return getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace);
29070        }
29071
29072        function getUninstantiatedJsxSignaturesOfType(elementType: Type, caller: JsxOpeningLikeElement): readonly Signature[] {
29073            if (elementType.flags & TypeFlags.String) {
29074                return [anySignature];
29075            }
29076            else if (elementType.flags & TypeFlags.StringLiteral) {
29077                const intrinsicType = getIntrinsicAttributesTypeFromStringLiteralType(elementType as StringLiteralType, caller);
29078                if (!intrinsicType) {
29079                    error(caller, Diagnostics.Property_0_does_not_exist_on_type_1, (elementType as StringLiteralType).value, "JSX." + JsxNames.IntrinsicElements);
29080                    return emptyArray;
29081                }
29082                else {
29083                    const fakeSignature = createSignatureForJSXIntrinsic(caller, intrinsicType);
29084                    return [fakeSignature];
29085                }
29086            }
29087            const apparentElemType = getApparentType(elementType);
29088            // Resolve the signatures, preferring constructor
29089            let signatures = getSignaturesOfType(apparentElemType, SignatureKind.Construct);
29090            if (signatures.length === 0) {
29091                // No construct signatures, try call signatures
29092                signatures = getSignaturesOfType(apparentElemType, SignatureKind.Call);
29093            }
29094            if (signatures.length === 0 && apparentElemType.flags & TypeFlags.Union) {
29095                // If each member has some combination of new/call signatures; make a union signature list for those
29096                signatures = getUnionSignatures(map((apparentElemType as UnionType).types, t => getUninstantiatedJsxSignaturesOfType(t, caller)));
29097            }
29098            return signatures;
29099        }
29100
29101        function getIntrinsicAttributesTypeFromStringLiteralType(type: StringLiteralType, location: Node): Type | undefined {
29102            // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type
29103            // For example:
29104            //      var CustomTag: "h1" = "h1";
29105            //      <CustomTag> Hello World </CustomTag>
29106            const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, location);
29107            if (!isErrorType(intrinsicElementsType)) {
29108                const stringLiteralTypeName = type.value;
29109                const intrinsicProp = getPropertyOfType(intrinsicElementsType, escapeLeadingUnderscores(stringLiteralTypeName));
29110                if (intrinsicProp) {
29111                    return getTypeOfSymbol(intrinsicProp);
29112                }
29113                const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, stringType);
29114                if (indexSignatureType) {
29115                    return indexSignatureType;
29116                }
29117                return undefined;
29118            }
29119            // If we need to report an error, we already done so here. So just return any to prevent any more error downstream
29120            return anyType;
29121        }
29122
29123        function checkJsxReturnAssignableToAppropriateBound(refKind: JsxReferenceKind, elemInstanceType: Type, openingLikeElement: JsxOpeningLikeElement) {
29124            if (refKind === JsxReferenceKind.Function) {
29125                const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement);
29126                if (sfcReturnConstraint) {
29127                    checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_return_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain);
29128                }
29129            }
29130            else if (refKind === JsxReferenceKind.Component) {
29131                const classConstraint = getJsxElementClassTypeAt(openingLikeElement);
29132                if (classConstraint) {
29133                    // Issue an error if this return type isn't assignable to JSX.ElementClass, failing that
29134                    checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_instance_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain);
29135                }
29136            }
29137            else { // Mixed
29138                const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement);
29139                const classConstraint = getJsxElementClassTypeAt(openingLikeElement);
29140                if (!sfcReturnConstraint || !classConstraint) {
29141                    return;
29142                }
29143                const combined = getUnionType([sfcReturnConstraint, classConstraint]);
29144                checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain);
29145            }
29146
29147            function generateInitialErrorChain(): DiagnosticMessageChain {
29148                const componentName = getTextOfNode(openingLikeElement.tagName);
29149                return chainDiagnosticMessages(/* details */ undefined, Diagnostics._0_cannot_be_used_as_a_JSX_component, componentName);
29150            }
29151        }
29152
29153        /**
29154         * Get attributes type of the given intrinsic opening-like Jsx element by resolving the tag name.
29155         * The function is intended to be called from a function which has checked that the opening element is an intrinsic element.
29156         * @param node an intrinsic JSX opening-like element
29157         */
29158        function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node: JsxOpeningLikeElement): Type {
29159            Debug.assert(isJsxIntrinsicIdentifier(node.tagName));
29160            const links = getNodeLinks(node);
29161            if (!links.resolvedJsxElementAttributesType) {
29162                const symbol = getIntrinsicTagSymbol(node);
29163                if (links.jsxFlags & JsxFlags.IntrinsicNamedElement) {
29164                    return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol) || errorType;
29165                }
29166                else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) {
29167                    return links.resolvedJsxElementAttributesType =
29168                        getIndexTypeOfType(getJsxType(JsxNames.IntrinsicElements, node), stringType) || errorType;
29169                }
29170                else {
29171                    return links.resolvedJsxElementAttributesType = errorType;
29172                }
29173            }
29174            return links.resolvedJsxElementAttributesType;
29175        }
29176
29177        function getJsxElementClassTypeAt(location: Node): Type | undefined {
29178            const type = getJsxType(JsxNames.ElementClass, location);
29179            if (isErrorType(type)) return undefined;
29180            return type;
29181        }
29182
29183        function getJsxElementTypeAt(location: Node): Type {
29184            return getJsxType(JsxNames.Element, location);
29185        }
29186
29187        function getJsxStatelessElementTypeAt(location: Node): Type | undefined {
29188            const jsxElementType = getJsxElementTypeAt(location);
29189            if (jsxElementType) {
29190                return getUnionType([jsxElementType, nullType]);
29191            }
29192        }
29193
29194        /**
29195         * Returns all the properties of the Jsx.IntrinsicElements interface
29196         */
29197        function getJsxIntrinsicTagNamesAt(location: Node): Symbol[] {
29198            const intrinsics = getJsxType(JsxNames.IntrinsicElements, location);
29199            return intrinsics ? getPropertiesOfType(intrinsics) : emptyArray;
29200        }
29201
29202        function checkJsxPreconditions(errorNode: Node) {
29203            // Preconditions for using JSX
29204            if ((compilerOptions.jsx || JsxEmit.None) === JsxEmit.None) {
29205                error(errorNode, Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided);
29206            }
29207
29208            if (getJsxElementTypeAt(errorNode) === undefined) {
29209                if (noImplicitAny) {
29210                    error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist);
29211                }
29212            }
29213        }
29214
29215        function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment) {
29216            const isNodeOpeningLikeElement = isJsxOpeningLikeElement(node);
29217
29218            if (isNodeOpeningLikeElement) {
29219                checkGrammarJsxElement(node);
29220            }
29221
29222            checkJsxPreconditions(node);
29223
29224            if (!getJsxNamespaceContainerForImplicitImport(node)) {
29225                // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import.
29226                // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error.
29227                const jsxFactoryRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
29228                const jsxFactoryNamespace = getJsxNamespace(node);
29229                const jsxFactoryLocation = isNodeOpeningLikeElement ? node.tagName : node;
29230
29231                // allow null as jsxFragmentFactory
29232                let jsxFactorySym: Symbol | undefined;
29233                if (!(isJsxOpeningFragment(node) && jsxFactoryNamespace === "null")) {
29234                    jsxFactorySym = resolveName(jsxFactoryLocation, jsxFactoryNamespace, SymbolFlags.Value, jsxFactoryRefErr, jsxFactoryNamespace, /*isUse*/ true);
29235                }
29236
29237                if (jsxFactorySym) {
29238                    // Mark local symbol as referenced here because it might not have been marked
29239                    // if jsx emit was not jsxFactory as there wont be error being emitted
29240                    jsxFactorySym.isReferenced = SymbolFlags.All;
29241
29242                    // If react/jsxFactory symbol is alias, mark it as refereced
29243                    if (jsxFactorySym.flags & SymbolFlags.Alias && !getTypeOnlyAliasDeclaration(jsxFactorySym)) {
29244                        markAliasSymbolAsReferenced(jsxFactorySym);
29245                    }
29246                }
29247
29248                // For JsxFragment, mark jsx pragma as referenced via resolveName
29249                if (isJsxOpeningFragment(node)) {
29250                    const file = getSourceFileOfNode(node);
29251                    const localJsxNamespace = getLocalJsxNamespace(file);
29252                    if (localJsxNamespace) {
29253                        resolveName(jsxFactoryLocation, localJsxNamespace, SymbolFlags.Value, jsxFactoryRefErr, localJsxNamespace, /*isUse*/ true);
29254                    }
29255                }
29256            }
29257
29258            if (isNodeOpeningLikeElement) {
29259                const jsxOpeningLikeNode = node ;
29260                const sig = getResolvedSignature(jsxOpeningLikeNode);
29261                checkDeprecatedSignature(sig, node);
29262                checkJsxReturnAssignableToAppropriateBound(getJsxReferenceKind(jsxOpeningLikeNode), getReturnTypeOfSignature(sig), jsxOpeningLikeNode);
29263            }
29264        }
29265
29266        /**
29267         * Check if a property with the given name is known anywhere in the given type. In an object type, a property
29268         * is considered known if
29269         * 1. the object type is empty and the check is for assignability, or
29270         * 2. if the object type has index signatures, or
29271         * 3. if the property is actually declared in the object type
29272         *    (this means that 'toString', for example, is not usually a known property).
29273         * 4. In a union or intersection type,
29274         *    a property is considered known if it is known in any constituent type.
29275         * @param targetType a type to search a given name in
29276         * @param name a property name to search
29277         * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType
29278         */
29279        function isKnownProperty(targetType: Type, name: __String, isComparingJsxAttributes: boolean): boolean {
29280            if (targetType.flags & TypeFlags.Object) {
29281                // For backwards compatibility a symbol-named property is satisfied by a string index signature. This
29282                // is incorrect and inconsistent with element access expressions, where it is an error, so eventually
29283                // we should remove this exception.
29284                if (getPropertyOfObjectType(targetType, name) ||
29285                    getApplicableIndexInfoForName(targetType, name) ||
29286                    isLateBoundName(name) && getIndexInfoOfType(targetType, stringType) ||
29287                    isComparingJsxAttributes && isHyphenatedJsxName(name)) {
29288                    // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
29289                    return true;
29290                }
29291            }
29292            else if (targetType.flags & TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) {
29293                for (const t of (targetType as UnionOrIntersectionType).types) {
29294                    if (isKnownProperty(t, name, isComparingJsxAttributes)) {
29295                        return true;
29296                    }
29297                }
29298            }
29299            return false;
29300        }
29301
29302        function isExcessPropertyCheckTarget(type: Type): boolean {
29303            return !!(type.flags & TypeFlags.Object && !(getObjectFlags(type) & ObjectFlags.ObjectLiteralPatternWithComputedProperties) ||
29304                type.flags & TypeFlags.NonPrimitive ||
29305                type.flags & TypeFlags.Union && some((type as UnionType).types, isExcessPropertyCheckTarget) ||
29306                type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isExcessPropertyCheckTarget));
29307        }
29308
29309        function checkJsxExpression(node: JsxExpression, checkMode?: CheckMode) {
29310            checkGrammarJsxExpression(node);
29311            if (node.expression) {
29312                const type = checkExpression(node.expression, checkMode);
29313                if (node.dotDotDotToken && type !== anyType && !isArrayType(type)) {
29314                    error(node, Diagnostics.JSX_spread_child_must_be_an_array_type);
29315                }
29316                return type;
29317            }
29318            else {
29319                return errorType;
29320            }
29321        }
29322
29323        function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags {
29324            return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0;
29325        }
29326
29327        /**
29328         * Return whether this symbol is a member of a prototype somewhere
29329         * Note that this is not tracked well within the compiler, so the answer may be incorrect.
29330         */
29331        function isPrototypeProperty(symbol: Symbol) {
29332            if (symbol.flags & SymbolFlags.Method || getCheckFlags(symbol) & CheckFlags.SyntheticMethod) {
29333                return true;
29334            }
29335            if (isInJSFile(symbol.valueDeclaration)) {
29336                const parent = symbol.valueDeclaration!.parent;
29337                return parent && isBinaryExpression(parent) &&
29338                    getAssignmentDeclarationKind(parent) === AssignmentDeclarationKind.PrototypeProperty;
29339            }
29340        }
29341
29342        /**
29343         * Check whether the requested property access is valid.
29344         * Returns true if node is a valid property access, and false otherwise.
29345         * @param node The node to be checked.
29346         * @param isSuper True if the access is from `super.`.
29347         * @param type The type of the object whose property is being accessed. (Not the type of the property.)
29348         * @param prop The symbol for the property being accessed.
29349         */
29350        function checkPropertyAccessibility(
29351            node: PropertyAccessExpression | QualifiedName | PropertyAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement,
29352            isSuper: boolean, writing: boolean, type: Type, prop: Symbol, reportError = true): boolean {
29353
29354            const errorNode = !reportError ? undefined :
29355                node.kind === SyntaxKind.QualifiedName ? node.right :
29356                node.kind === SyntaxKind.ImportType ? node :
29357                node.kind === SyntaxKind.BindingElement && node.propertyName ? node.propertyName : node.name;
29358
29359            return checkPropertyAccessibilityAtLocation(node, isSuper, writing, type, prop, errorNode);
29360        }
29361
29362        /**
29363         * Check whether the requested property can be accessed at the requested location.
29364         * Returns true if node is a valid property access, and false otherwise.
29365         * @param location The location node where we want to check if the property is accessible.
29366         * @param isSuper True if the access is from `super.`.
29367         * @param writing True if this is a write property access, false if it is a read property access.
29368         * @param containingType The type of the object whose property is being accessed. (Not the type of the property.)
29369         * @param prop The symbol for the property being accessed.
29370         * @param errorNode The node where we should report an invalid property access error, or undefined if we should not report errors.
29371         */
29372        function checkPropertyAccessibilityAtLocation(location: Node,
29373            isSuper: boolean, writing: boolean,
29374            containingType: Type, prop: Symbol, errorNode?: Node): boolean {
29375
29376            const flags = getDeclarationModifierFlagsFromSymbol(prop, writing);
29377
29378            if (isSuper) {
29379                // TS 1.0 spec (April 2014): 4.8.2
29380                // - In a constructor, instance member function, instance member accessor, or
29381                //   instance member variable initializer where this references a derived class instance,
29382                //   a super property access is permitted and must specify a public instance member function of the base class.
29383                // - In a static member function or static member accessor
29384                //   where this references the constructor function object of a derived class,
29385                //   a super property access is permitted and must specify a public static member function of the base class.
29386                if (languageVersion < ScriptTarget.ES2015) {
29387                    if (symbolHasNonMethodDeclaration(prop)) {
29388                        if (errorNode) {
29389                            error(errorNode, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
29390                        }
29391                        return false;
29392                    }
29393                }
29394                if (flags & ModifierFlags.Abstract) {
29395                    // A method cannot be accessed in a super property access if the method is abstract.
29396                    // This error could mask a private property access error. But, a member
29397                    // cannot simultaneously be private and abstract, so this will trigger an
29398                    // additional error elsewhere.
29399                    if (errorNode) {
29400                        error(errorNode,
29401                            Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression,
29402                            symbolToString(prop),
29403                            typeToString(getDeclaringClass(prop)!));
29404                    }
29405                    return false;
29406                }
29407            }
29408
29409            // Referencing abstract properties within their own constructors is not allowed
29410            if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop) &&
29411                (isThisProperty(location) || isThisInitializedObjectBindingExpression(location) || isObjectBindingPattern(location.parent) && isThisInitializedDeclaration(location.parent.parent))) {
29412                const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!);
29413                if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(location)) {
29414                    if (errorNode) {
29415                        error(errorNode,
29416                            Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor,
29417                            symbolToString(prop),
29418                            getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!));
29419                    }
29420                    return false;
29421                }
29422            }
29423
29424            // Public properties are otherwise accessible.
29425            if (!(flags & ModifierFlags.NonPublicAccessibilityModifier)) {
29426                return true;
29427            }
29428
29429            // Property is known to be private or protected at this point
29430
29431            // Private property is accessible if the property is within the declaring class
29432            if (flags & ModifierFlags.Private) {
29433                const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!)!;
29434                if (!isNodeWithinClass(location, declaringClassDeclaration)) {
29435                    if (errorNode) {
29436                        error(errorNode,
29437                            Diagnostics.Property_0_is_private_and_only_accessible_within_class_1,
29438                            symbolToString(prop),
29439                            typeToString(getDeclaringClass(prop)!));
29440                    }
29441                    return false;
29442                }
29443                return true;
29444            }
29445
29446            // Property is known to be protected at this point
29447
29448            // All protected properties of a supertype are accessible in a super access
29449            if (isSuper) {
29450                return true;
29451            }
29452
29453            // Find the first enclosing class that has the declaring classes of the protected constituents
29454            // of the property as base classes
29455            let enclosingClass = forEachEnclosingClass(location, enclosingDeclaration => {
29456                const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!) as InterfaceType;
29457                return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing);
29458            });
29459            // A protected property is accessible if the property is within the declaring class or classes derived from it
29460            if (!enclosingClass) {
29461                // allow PropertyAccessibility if context is in function with this parameter
29462                // static member access is disallowed
29463                enclosingClass = getEnclosingClassFromThisParameter(location);
29464                enclosingClass = enclosingClass && isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing);
29465                if (flags & ModifierFlags.Static || !enclosingClass) {
29466                    if (errorNode) {
29467                        error(errorNode,
29468                            Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses,
29469                            symbolToString(prop),
29470                            typeToString(getDeclaringClass(prop) || containingType));
29471                    }
29472                    return false;
29473                }
29474            }
29475            // No further restrictions for static properties
29476            if (flags & ModifierFlags.Static) {
29477                return true;
29478            }
29479            if (containingType.flags & TypeFlags.TypeParameter) {
29480                // get the original type -- represented as the type constraint of the 'this' type
29481                containingType = (containingType as TypeParameter).isThisType ? getConstraintOfTypeParameter(containingType as TypeParameter)! : getBaseConstraintOfType(containingType as TypeParameter)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined
29482            }
29483            if (!containingType || !hasBaseType(containingType, enclosingClass)) {
29484                if (errorNode) {
29485                    error(errorNode,
29486                        Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1_This_is_an_instance_of_class_2,
29487                        symbolToString(prop), typeToString(enclosingClass), typeToString(containingType));
29488                }
29489                return false;
29490            }
29491            return true;
29492        }
29493
29494        function getEnclosingClassFromThisParameter(node: Node): InterfaceType | undefined {
29495            const thisParameter = getThisParameterFromNodeContext(node);
29496            let thisType = thisParameter?.type && getTypeFromTypeNode(thisParameter.type);
29497            if (thisType && thisType.flags & TypeFlags.TypeParameter) {
29498                thisType = getConstraintOfTypeParameter(thisType as TypeParameter);
29499            }
29500            if (thisType && getObjectFlags(thisType) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
29501                return getTargetType(thisType) as InterfaceType;
29502            }
29503            return undefined;
29504        }
29505
29506        function getThisParameterFromNodeContext(node: Node) {
29507            const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false);
29508            return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined;
29509        }
29510
29511        function symbolHasNonMethodDeclaration(symbol: Symbol) {
29512            return !!forEachProperty(symbol, prop => !(prop.flags & SymbolFlags.Method));
29513        }
29514
29515        function checkNonNullExpression(node: Expression | QualifiedName, checkMode?: CheckMode) {
29516            return checkNonNullType(checkExpression(node, checkMode), node);
29517        }
29518
29519        function isNullableType(type: Type) {
29520            return !!(getTypeFacts(type) & TypeFacts.IsUndefinedOrNull);
29521        }
29522
29523        function getNonNullableTypeIfNeeded(type: Type) {
29524            return isNullableType(type) ? getNonNullableType(type) : type;
29525        }
29526
29527        function reportObjectPossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) {
29528            const nodeText = isEntityNameExpression(node) ? entityNameToString(node) : undefined;
29529            if (node.kind === SyntaxKind.NullKeyword) {
29530                error(node, Diagnostics.The_value_0_cannot_be_used_here, "null");
29531                return;
29532            }
29533            if (nodeText !== undefined && nodeText.length < 100) {
29534                if (isIdentifier(node) && nodeText === "undefined") {
29535                    error(node, Diagnostics.The_value_0_cannot_be_used_here, "undefined");
29536                    return;
29537                }
29538                error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ?
29539                    Diagnostics._0_is_possibly_null_or_undefined :
29540                    Diagnostics._0_is_possibly_undefined :
29541                    Diagnostics._0_is_possibly_null,
29542                    nodeText
29543                );
29544            }
29545            else {
29546                error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ?
29547                    Diagnostics.Object_is_possibly_null_or_undefined :
29548                    Diagnostics.Object_is_possibly_undefined :
29549                    Diagnostics.Object_is_possibly_null
29550                );
29551            }
29552        }
29553
29554        function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) {
29555            error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ?
29556                Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined :
29557                Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined :
29558                Diagnostics.Cannot_invoke_an_object_which_is_possibly_null
29559            );
29560        }
29561
29562        function checkNonNullTypeWithReporter(
29563            type: Type,
29564            node: Node,
29565            reportError: (node: Node, facts: TypeFacts) => void
29566        ): Type {
29567            if (strictNullChecks && type.flags & TypeFlags.Unknown) {
29568                if (isEntityNameExpression(node)) {
29569                    const nodeText = entityNameToString(node);
29570                    if (nodeText.length < 100) {
29571                        error(node, Diagnostics._0_is_of_type_unknown, nodeText);
29572                        return errorType;
29573                    }
29574                }
29575                error(node, Diagnostics.Object_is_of_type_unknown);
29576                return errorType;
29577            }
29578            const facts = getTypeFacts(type);
29579            if (facts & TypeFacts.IsUndefinedOrNull) {
29580                reportError(node, facts);
29581                const t = getNonNullableType(type);
29582                return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t;
29583            }
29584            return type;
29585        }
29586
29587        function checkNonNullType(type: Type, node: Node) {
29588            return checkNonNullTypeWithReporter(type, node, reportObjectPossiblyNullOrUndefinedError);
29589        }
29590
29591        function checkNonNullNonVoidType(type: Type, node: Node): Type {
29592            const nonNullType = checkNonNullType(type, node);
29593            if (nonNullType.flags & TypeFlags.Void) {
29594                if (isEntityNameExpression(node)) {
29595                    const nodeText = entityNameToString(node);
29596                    if (isIdentifier(node) && nodeText === "undefined") {
29597                        error(node, Diagnostics.The_value_0_cannot_be_used_here, nodeText);
29598                        return nonNullType;
29599                    }
29600                    if (nodeText.length < 100) {
29601                        error(node, Diagnostics._0_is_possibly_undefined, nodeText);
29602                        return nonNullType;
29603                    }
29604                }
29605                error(node, Diagnostics.Object_is_possibly_undefined);
29606            }
29607            return nonNullType;
29608        }
29609
29610
29611        function checkPropertyAccessExpression(node: PropertyAccessExpression, checkMode: CheckMode | undefined) {
29612            if (checkMode !== CheckMode.SkipEtsComponentBody) {
29613                propertyAccessExpressionConditionCheck(node);
29614            }
29615            return node.flags & NodeFlags.OptionalChain ? checkPropertyAccessChain(node as PropertyAccessChain, checkMode) :
29616                checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullExpression(node.expression), node.name, checkMode);
29617        }
29618
29619        function checkPropertyAccessChain(node: PropertyAccessChain, checkMode: CheckMode | undefined) {
29620            const leftType = checkExpression(node.expression);
29621            const nonOptionalType = getOptionalExpressionType(leftType, node.expression);
29622            return propagateOptionalTypeMarker(checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullType(nonOptionalType, node.expression), node.name, checkMode), node, nonOptionalType !== leftType);
29623        }
29624
29625        function checkQualifiedName(node: QualifiedName, checkMode: CheckMode | undefined) {
29626            const leftType = isPartOfTypeQuery(node) && isThisIdentifier(node.left) ? checkNonNullType(checkThisExpression(node.left), node.left) : checkNonNullExpression(node.left);
29627            return checkPropertyAccessExpressionOrQualifiedName(node, node.left, leftType, node.right, checkMode);
29628        }
29629
29630        function isMethodAccessForCall(node: Node) {
29631            while (node.parent.kind === SyntaxKind.ParenthesizedExpression) {
29632                node = node.parent;
29633            }
29634            return isCallOrNewExpression(node.parent) && node.parent.expression === node;
29635        }
29636
29637        // Lookup the private identifier lexically.
29638        function lookupSymbolForPrivateIdentifierDeclaration(propName: __String, location: Node): Symbol | undefined {
29639            for (let containingClass = getContainingClass(location); !!containingClass; containingClass = getContainingClass(containingClass)) {
29640                const { symbol } = containingClass;
29641                const name = getSymbolNameForPrivateIdentifier(symbol, propName);
29642                const prop = (symbol.members && symbol.members.get(name)) || (symbol.exports && symbol.exports.get(name));
29643                if (prop) {
29644                    return prop;
29645                }
29646            }
29647        }
29648
29649        function checkGrammarPrivateIdentifierExpression(privId: PrivateIdentifier): boolean {
29650            if (!getContainingClass(privId)) {
29651                return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
29652            }
29653
29654            if (!isForInStatement(privId.parent)) {
29655                if (!isExpressionNode(privId)) {
29656                    return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression);
29657                }
29658
29659                const isInOperation = isBinaryExpression(privId.parent) && privId.parent.operatorToken.kind === SyntaxKind.InKeyword;
29660                if (!getSymbolForPrivateIdentifierExpression(privId) && !isInOperation) {
29661                    return grammarErrorOnNode(privId, Diagnostics.Cannot_find_name_0, idText(privId));
29662                }
29663            }
29664
29665            return false;
29666        }
29667
29668        function checkPrivateIdentifierExpression(privId: PrivateIdentifier): Type {
29669            checkGrammarPrivateIdentifierExpression(privId);
29670            const symbol = getSymbolForPrivateIdentifierExpression(privId);
29671            if (symbol) {
29672                markPropertyAsReferenced(symbol, /* nodeForCheckWriteOnly: */ undefined, /* isThisAccess: */ false);
29673            }
29674            return anyType;
29675        }
29676
29677        function getSymbolForPrivateIdentifierExpression(privId: PrivateIdentifier): Symbol | undefined {
29678            if (!isExpressionNode(privId)) {
29679                return undefined;
29680            }
29681
29682            const links = getNodeLinks(privId);
29683            if (links.resolvedSymbol === undefined) {
29684                links.resolvedSymbol = lookupSymbolForPrivateIdentifierDeclaration(privId.escapedText, privId);
29685            }
29686            return links.resolvedSymbol;
29687        }
29688
29689        function getPrivateIdentifierPropertyOfType(leftType: Type, lexicallyScopedIdentifier: Symbol): Symbol | undefined {
29690            return getPropertyOfType(leftType, lexicallyScopedIdentifier.escapedName);
29691        }
29692
29693        function checkPrivateIdentifierPropertyAccess(leftType: Type, right: PrivateIdentifier, lexicallyScopedIdentifier: Symbol | undefined): boolean {
29694            // Either the identifier could not be looked up in the lexical scope OR the lexically scoped identifier did not exist on the type.
29695            // Find a private identifier with the same description on the type.
29696            let propertyOnType: Symbol | undefined;
29697            const properties = getPropertiesOfType(leftType);
29698            if (properties) {
29699                forEach(properties, (symbol: Symbol) => {
29700                    const decl = symbol.valueDeclaration;
29701                    if (decl && isNamedDeclaration(decl) && isPrivateIdentifier(decl.name) && decl.name.escapedText === right.escapedText) {
29702                        propertyOnType = symbol;
29703                        return true;
29704                    }
29705                });
29706            }
29707            const diagName = diagnosticName(right);
29708            if (propertyOnType) {
29709                const typeValueDecl = Debug.checkDefined(propertyOnType.valueDeclaration);
29710                const typeClass = Debug.checkDefined(getContainingClass(typeValueDecl));
29711                // We found a private identifier property with the same description.
29712                // Either:
29713                // - There is a lexically scoped private identifier AND it shadows the one we found on the type.
29714                // - It is an attempt to access the private identifier outside of the class.
29715                if (lexicallyScopedIdentifier?.valueDeclaration) {
29716                    const lexicalValueDecl = lexicallyScopedIdentifier.valueDeclaration;
29717                    const lexicalClass = getContainingClass(lexicalValueDecl);
29718                    Debug.assert(!!lexicalClass);
29719                    if (findAncestor(lexicalClass, n => typeClass === n)) {
29720                        const diagnostic = error(
29721                            right,
29722                            Diagnostics.The_property_0_cannot_be_accessed_on_type_1_within_this_class_because_it_is_shadowed_by_another_private_identifier_with_the_same_spelling,
29723                            diagName,
29724                            typeToString(leftType)
29725                        );
29726
29727                        addRelatedInfo(
29728                            diagnostic,
29729                            createDiagnosticForNode(
29730                                lexicalValueDecl,
29731                                Diagnostics.The_shadowing_declaration_of_0_is_defined_here,
29732                                diagName
29733                            ),
29734                            createDiagnosticForNode(
29735                                typeValueDecl,
29736                                Diagnostics.The_declaration_of_0_that_you_probably_intended_to_use_is_defined_here,
29737                                diagName
29738                            )
29739                        );
29740                        return true;
29741                    }
29742                }
29743                error(
29744                    right,
29745                    Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier,
29746                    diagName,
29747                    diagnosticName(typeClass.name || anon)
29748                );
29749                return true;
29750            }
29751            return false;
29752        }
29753
29754        function isThisPropertyAccessInConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) {
29755            return (isConstructorDeclaredProperty(prop) || isThisProperty(node) && isAutoTypedProperty(prop))
29756                && getThisContainer(node, /*includeArrowFunctions*/ true) === getDeclaringConstructor(prop);
29757        }
29758
29759        function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined) {
29760            const parentSymbol = getNodeLinks(left).resolvedSymbol;
29761            const assignmentKind = getAssignmentTargetKind(node);
29762            const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType);
29763            const isAnyLike = isTypeAny(apparentType) || apparentType === silentNeverType;
29764            let prop: Symbol | undefined;
29765
29766            if (isPropertyAccessExpression(node) && isConstEnumObjectType(leftType)) {
29767                checkConstEnumRelate(node, leftType.symbol);
29768            }
29769
29770            if (isPrivateIdentifier(right)) {
29771                if (languageVersion < ScriptTarget.ESNext) {
29772                    if (assignmentKind !== AssignmentKind.None) {
29773                        checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldSet);
29774                    }
29775                    if (assignmentKind !== AssignmentKind.Definite) {
29776                        checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldGet);
29777                    }
29778                }
29779
29780                const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(right.escapedText, right);
29781                if (assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration && isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration)) {
29782                    grammarErrorOnNode(right, Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, idText(right));
29783                }
29784
29785                if (isAnyLike) {
29786                    if (lexicallyScopedSymbol) {
29787                        return isErrorType(apparentType) ? errorType : apparentType;
29788                    }
29789                    if (!getContainingClass(right)) {
29790                        grammarErrorOnNode(right, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
29791                        return anyType;
29792                    }
29793                }
29794                prop = lexicallyScopedSymbol ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedSymbol) : undefined;
29795                // Check for private-identifier-specific shadowing and lexical-scoping errors.
29796                if (!prop && checkPrivateIdentifierPropertyAccess(leftType, right, lexicallyScopedSymbol)) {
29797                    return errorType;
29798                }
29799                else {
29800                    const isSetonlyAccessor = prop && prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
29801                    if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite) {
29802                        error(node, Diagnostics.Private_accessor_was_defined_without_a_getter);
29803                    }
29804                }
29805            }
29806            else {
29807                if (isAnyLike) {
29808                    if (isIdentifier(left) && parentSymbol) {
29809                        markAliasReferenced(parentSymbol, node);
29810                    }
29811                    return isErrorType(apparentType) ? errorType : apparentType;
29812                }
29813                prop = getPropertyOfType(apparentType, right.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ node.kind === SyntaxKind.QualifiedName);
29814                if (!prop) {
29815                    const etsComponentExpressionNode = getEtsComponentExpressionInnerCallExpressionNode(node)
29816                        || getRootEtsComponentInnerCallExpressionNode(node);
29817                    const locals = getSourceFileOfNode(node).locals;
29818                    if (etsComponentExpressionNode && locals?.has(right.escapedText)) {
29819                        const extraSymbol = locals?.get(right.escapedText);
29820                        const decorators = getAllDecorators(extraSymbol?.valueDeclaration);
29821                        const etsComponentName = etsComponentExpressionNode.expression.kind === SyntaxKind.Identifier ? (<Identifier>etsComponentExpressionNode.expression).escapedText : undefined;
29822                        if (getEtsExtendDecoratorsComponentNames(decorators, compilerOptions).find(extendComponentName => extendComponentName === etsComponentName)) {
29823                            prop = extraSymbol;
29824                        }
29825                        if (hasEtsStylesDecoratorNames(decorators, compilerOptions)) {
29826                            prop = extraSymbol;
29827                        }
29828                    }
29829                    const props = getContainingStruct(node)?.symbol.members;
29830                    if (etsComponentExpressionNode && props?.has(right.escapedText)) {
29831                        const stylesSymbol = props?.get(right.escapedText);
29832                        const decorators = getAllDecorators(stylesSymbol?.valueDeclaration);
29833                        if (hasEtsStylesDecoratorNames(decorators, compilerOptions)) {
29834                            prop = stylesSymbol;
29835                        }
29836                    }
29837                }
29838            }
29839            // In `Foo.Bar.Baz`, 'Foo' is not referenced if 'Bar' is a const enum or a module containing only const enums.
29840            // `Foo` is also not referenced in `enum FooCopy { Bar = Foo.Bar }`, because the enum member value gets inlined
29841            // here even if `Foo` is not a const enum.
29842            //
29843            // The exceptions are:
29844            //   1. if 'isolatedModules' is enabled, because the const enum value will not be inlined, and
29845            //   2. if 'preserveConstEnums' is enabled and the expression is itself an export, e.g. `export = Foo.Bar.Baz`.
29846            if (isIdentifier(left) && parentSymbol && (
29847                compilerOptions.isolatedModules ||
29848                !(prop && (isConstEnumOrConstEnumOnlyModule(prop) || prop.flags & SymbolFlags.EnumMember && node.parent.kind === SyntaxKind.EnumMember)) ||
29849                shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(node)
29850            )) {
29851                markAliasReferenced(parentSymbol, node);
29852            }
29853
29854            let propType: Type;
29855            if (!prop) {
29856                const indexInfo = !isPrivateIdentifier(right) && (assignmentKind === AssignmentKind.None || !isGenericObjectType(leftType) || isThisTypeParameter(leftType)) ?
29857                    getApplicableIndexInfoForName(apparentType, right.escapedText) : undefined;
29858                if (!(indexInfo && indexInfo.type)) {
29859                    const isUncheckedJS = isUncheckedJSSuggestion(node, leftType.symbol, /*excludeClasses*/ true);
29860                    if (!isUncheckedJS && isJSLiteralType(leftType)) {
29861                        return anyType;
29862                    }
29863                    if (leftType.symbol === globalThisSymbol) {
29864                        if (globalThisSymbol.exports!.has(right.escapedText) && (globalThisSymbol.exports!.get(right.escapedText)!.flags & SymbolFlags.BlockScoped)) {
29865                            error(right, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(right.escapedText), typeToString(leftType));
29866                        }
29867                        else if (noImplicitAny) {
29868                            error(right, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType));
29869                        }
29870                        return anyType;
29871                    }
29872                    if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
29873                        reportNonexistentProperty(right, isThisTypeParameter(leftType) ? apparentType : leftType, isUncheckedJS);
29874                    }
29875                    return errorType;
29876                }
29877                if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) {
29878                    error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType));
29879                }
29880
29881                propType = (compilerOptions.noUncheckedIndexedAccess && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type;
29882                if (compilerOptions.noPropertyAccessFromIndexSignature && isPropertyAccessExpression(node)) {
29883                    error(right, Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, unescapeLeadingUnderscores(right.escapedText));
29884                }
29885                if (indexInfo.declaration && getCombinedNodeFlags(indexInfo.declaration) & NodeFlags.Deprecated) {
29886                    addDeprecatedSuggestion(right, [indexInfo.declaration], right.escapedText as string);
29887                }
29888            }
29889            else {
29890                if (isDeprecatedSymbol(prop) && isUncalledFunctionReference(node, prop) && prop.declarations) {
29891                    addDeprecatedSuggestion(right, prop.declarations, right.escapedText as string);
29892                }
29893                checkPropertyNotUsedBeforeDeclaration(prop, node, right);
29894                markPropertyAsReferenced(prop, node, isSelfTypeAccess(left, parentSymbol));
29895                getNodeLinks(node).resolvedSymbol = prop;
29896                const writing = isWriteAccess(node);
29897                checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, writing, apparentType, prop);
29898                if (isAssignmentToReadonlyEntity(node as Expression, prop, assignmentKind)) {
29899                    error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, idText(right));
29900                    return errorType;
29901                }
29902
29903                propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop);
29904            }
29905
29906            return getFlowTypeOfAccessExpression(node, prop, propType, right, checkMode);
29907        }
29908
29909        function checkConstEnumRelate(node: Node, originalSymbol: Symbol): void {
29910            const symbol = resolveSymbol(originalSymbol);
29911            let filePath = getSourceFileOfNode(node)?.resolvedPath;
29912            if (!symbol || !filePath) { return; }
29913            if (!constEnumRelate.has(filePath)) {
29914                constEnumRelate.set(filePath, new Map());
29915            }
29916            symbol.declarations?.forEach(decl => {
29917                let file = getSourceFileOfNode(decl);
29918                if (!file || file.resolvedPath === filePath) {
29919                    return;
29920                }
29921                constEnumRelate.get(filePath)?.set(file.resolvedPath, file.version);
29922            });
29923        }
29924
29925        /**
29926         * Determines whether a did-you-mean error should be a suggestion in an unchecked JS file.
29927         * Only applies to unchecked JS files without checkJS, // @ts-check or // @ts-nocheck
29928         * It does not suggest when the suggestion:
29929         * - Is from a global file that is different from the reference file, or
29930         * - (optionally) Is a class, or is a this.x property access expression
29931         */
29932        function isUncheckedJSSuggestion(node: Node | undefined, suggestion: Symbol | undefined, excludeClasses: boolean): boolean {
29933            const file = getSourceFileOfNode(node);
29934            if (file) {
29935                if (compilerOptions.checkJs === undefined && file.checkJsDirective === undefined && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX)) {
29936                    const declarationFile = forEach(suggestion?.declarations, getSourceFileOfNode);
29937                    return !(file !== declarationFile && !!declarationFile && isGlobalSourceFile(declarationFile))
29938                        && !(excludeClasses && suggestion && suggestion.flags & SymbolFlags.Class)
29939                        && !(!!node && excludeClasses && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword);
29940                }
29941            }
29942            return false;
29943        }
29944
29945        function getFlowTypeOfAccessExpression(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, propType: Type, errorNode: Node, checkMode: CheckMode | undefined) {
29946            // Only compute control flow type if this is a property access expression that isn't an
29947            // assignment target, and the referenced property was declared as a variable, property,
29948            // accessor, or optional method.
29949            const assignmentKind = getAssignmentTargetKind(node);
29950            if (assignmentKind === AssignmentKind.Definite) {
29951                return removeMissingType(propType, !!(prop && prop.flags & SymbolFlags.Optional));
29952            }
29953            if (prop &&
29954                !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor))
29955                && !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)
29956                && !isDuplicatedCommonJSExport(prop.declarations)) {
29957                return propType;
29958            }
29959            if (propType === autoType) {
29960                return getFlowTypeOfProperty(node, prop);
29961            }
29962            propType = getNarrowableTypeForReference(propType, node, checkMode);
29963            // If strict null checks and strict property initialization checks are enabled, if we have
29964            // a this.xxx property access, if the property is an instance property without an initializer,
29965            // and if we are in a constructor of the same class as the property declaration, assume that
29966            // the property is uninitialized at the top of the control flow.
29967            let assumeUninitialized = false;
29968            if (strictNullChecks && strictPropertyInitialization && isAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword) {
29969                const declaration = prop && prop.valueDeclaration;
29970                if (declaration && isPropertyWithoutInitializer(declaration)) {
29971                    if (!isStatic(declaration)) {
29972                        const flowContainer = getControlFlowContainer(node);
29973                        if (flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent && !(declaration.flags & NodeFlags.Ambient)) {
29974                            assumeUninitialized = true;
29975                        }
29976                    }
29977                }
29978            }
29979            else if (strictNullChecks && prop && prop.valueDeclaration &&
29980                isPropertyAccessExpression(prop.valueDeclaration) &&
29981                getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) &&
29982                getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration)) {
29983                assumeUninitialized = true;
29984            }
29985            const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType);
29986            if (assumeUninitialized && !containsUndefinedType(propType) && containsUndefinedType(flowType)) {
29987                error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217
29988                // Return the declared type to reduce follow-on errors
29989                return propType;
29990            }
29991            return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
29992        }
29993
29994        function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier | PrivateIdentifier): void {
29995            const { valueDeclaration } = prop;
29996            if (!valueDeclaration || getSourceFileOfNode(node).isDeclarationFile) {
29997                return;
29998            }
29999
30000            let diagnosticMessage;
30001            const declarationName = idText(right);
30002            if (isInPropertyInitializerOrClassStaticBlock(node)
30003                && !isOptionalPropertyDeclaration(valueDeclaration)
30004                && !(isAccessExpression(node) && isAccessExpression(node.expression))
30005                && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)
30006                && !(isMethodDeclaration(valueDeclaration) && getCombinedModifierFlags(valueDeclaration) & ModifierFlags.Static)
30007                && (compilerOptions.useDefineForClassFields || !isPropertyDeclaredInAncestorClass(prop))) {
30008                let needInitialization: boolean | undefined = false;
30009                let hasRequireDecorator: boolean = false;
30010                const decorators = getAllDecorators(prop?.valueDeclaration)
30011                if (decorators) {
30012                    needInitialization = host.getCompilerOptions().ets?.propertyDecorators.some(property => {
30013                        return decorators?.some(decorator => {
30014                            if (isIdentifier(decorator.expression)
30015                                && property.name === decorator.expression.escapedText.toString()
30016                                && !property.needInitialization) {
30017                                    return true;
30018                            }
30019                            else {
30020                                return false;
30021                            }
30022                        });
30023                    });
30024                    hasRequireDecorator = decorators.some(decorator => {
30025                        return isIdentifier(decorator.expression) &&
30026                            decorator.expression.escapedText.toString() === REQUIRE_DECORATOR;
30027                    });
30028                }
30029                // In the following cases, property can be uninitialized:
30030                // 1. Property is decorated with property decorators which allow no initialization, such as `@Link`, `@Prop`, `@ObjectLink` and `@Consume`.
30031                // 2. Property is decorated with `@Require` and satisfied the following conditions:
30032                //     a. Property has been declared before used.
30033                //     b. Property is declared and used in the same struct.
30034                if (!needInitialization &&
30035                    !(hasRequireDecorator && checkStructPropertyPosition(valueDeclaration, node))) {
30036                    diagnosticMessage = error(right, Diagnostics.Property_0_is_used_before_its_initialization, declarationName);
30037                }
30038            }
30039            else if (valueDeclaration.kind === SyntaxKind.ClassDeclaration &&
30040                node.parent.kind !== SyntaxKind.TypeReference &&
30041                !(valueDeclaration.flags & NodeFlags.Ambient) &&
30042                !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)) {
30043                diagnosticMessage = error(right, Diagnostics.Class_0_used_before_its_declaration, declarationName);
30044            }
30045
30046            if (diagnosticMessage) {
30047                addRelatedInfo(diagnosticMessage,
30048                    createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here, declarationName)
30049                );
30050            }
30051        }
30052
30053        function isInPropertyInitializerOrClassStaticBlock(node: Node): boolean {
30054            return !!findAncestor(node, node => {
30055                switch (node.kind) {
30056                    case SyntaxKind.PropertyDeclaration:
30057                        return true;
30058                    case SyntaxKind.PropertyAssignment:
30059                    case SyntaxKind.MethodDeclaration:
30060                    case SyntaxKind.GetAccessor:
30061                    case SyntaxKind.SetAccessor:
30062                    case SyntaxKind.SpreadAssignment:
30063                    case SyntaxKind.ComputedPropertyName:
30064                    case SyntaxKind.TemplateSpan:
30065                    case SyntaxKind.JsxExpression:
30066                    case SyntaxKind.JsxAttribute:
30067                    case SyntaxKind.JsxAttributes:
30068                    case SyntaxKind.JsxSpreadAttribute:
30069                    case SyntaxKind.JsxOpeningElement:
30070                    case SyntaxKind.ExpressionWithTypeArguments:
30071                    case SyntaxKind.HeritageClause:
30072                        return false;
30073                    case SyntaxKind.ArrowFunction:
30074                    case SyntaxKind.ExpressionStatement:
30075                        return isBlock(node.parent) && isClassStaticBlockDeclaration(node.parent.parent) ? true : "quit";
30076                    default:
30077                        return isExpressionNode(node) ? false : "quit";
30078                }
30079            });
30080        }
30081
30082        /**
30083         * It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass.
30084         * In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration.
30085         */
30086        function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean {
30087            if (!(prop.parent!.flags & SymbolFlags.Class)) {
30088                return false;
30089            }
30090            let classType: InterfaceType | undefined = getTypeOfSymbol(prop.parent!) as InterfaceType;
30091            while (true) {
30092                classType = classType.symbol && getSuperClass(classType) as InterfaceType | undefined;
30093                if (!classType) {
30094                    return false;
30095                }
30096                const superProperty = getPropertyOfType(classType, prop.escapedName);
30097                if (superProperty && superProperty.valueDeclaration) {
30098                    return true;
30099                }
30100            }
30101        }
30102
30103        function getSuperClass(classType: InterfaceType): Type | undefined {
30104            const x = getBaseTypes(classType);
30105            if (x.length === 0) {
30106                return undefined;
30107            }
30108            return getIntersectionType(x);
30109        }
30110
30111        function reportNonexistentProperty(propNode: Identifier | PrivateIdentifier, containingType: Type, isUncheckedJS: boolean) {
30112            let errorInfo: DiagnosticMessageChain | undefined;
30113            let relatedInfo: Diagnostic | undefined;
30114            if (!isPrivateIdentifier(propNode) && containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
30115                for (const subtype of (containingType as UnionType).types) {
30116                    if (!getPropertyOfType(subtype, propNode.escapedText) && !getApplicableIndexInfoForName(subtype, propNode.escapedText)) {
30117                        errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype));
30118                        break;
30119                    }
30120                }
30121            }
30122            if (typeHasStaticProperty(propNode.escapedText, containingType)) {
30123                const propName = declarationNameToString(propNode);
30124                const typeName = typeToString(containingType);
30125                errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName, typeName, typeName + "." + propName);
30126            }
30127            else {
30128                const promisedType = getPromisedTypeOfPromise(containingType);
30129                if (promisedType && getPropertyOfType(promisedType, propNode.escapedText)) {
30130                    errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
30131                    relatedInfo = createDiagnosticForNode(propNode, Diagnostics.Did_you_forget_to_use_await);
30132                }
30133                else {
30134                    const missingProperty = declarationNameToString(propNode);
30135                    const container = typeToString(containingType);
30136                    const libSuggestion = getSuggestedLibForNonExistentProperty(missingProperty, containingType);
30137                    if (libSuggestion !== undefined) {
30138                        errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2_or_later, missingProperty, container, libSuggestion);
30139                    }
30140                    else {
30141                        const suggestion = getSuggestedSymbolForNonexistentProperty(propNode, containingType);
30142                        if (suggestion !== undefined) {
30143                            const suggestedName = symbolName(suggestion);
30144                            const message = isUncheckedJS ? Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2 : Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2;
30145                            errorInfo = chainDiagnosticMessages(errorInfo, message, missingProperty, container, suggestedName);
30146                            relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName);
30147                        }
30148                        else {
30149                            const diagnostic = containerSeemsToBeEmptyDomElement(containingType)
30150                                ? Diagnostics.Property_0_does_not_exist_on_type_1_Try_changing_the_lib_compiler_option_to_include_dom
30151                                : Diagnostics.Property_0_does_not_exist_on_type_1;
30152                            errorInfo = chainDiagnosticMessages(elaborateNeverIntersection(errorInfo, containingType), diagnostic, missingProperty, container);
30153                        }
30154                    }
30155                }
30156            }
30157            const resultDiagnostic = createDiagnosticForNodeFromMessageChain(propNode, errorInfo);
30158            if (relatedInfo) {
30159                addRelatedInfo(resultDiagnostic, relatedInfo);
30160            }
30161            addErrorOrSuggestion(!isUncheckedJS || errorInfo.code !== Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, resultDiagnostic);
30162        }
30163
30164        function containerSeemsToBeEmptyDomElement(containingType: Type) {
30165            return (compilerOptions.lib && !compilerOptions.lib.includes("dom")) &&
30166                everyContainedType(containingType, type => type.symbol && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) &&
30167                isEmptyObjectType(containingType);
30168        }
30169
30170        function typeHasStaticProperty(propName: __String, containingType: Type): boolean {
30171            const prop = containingType.symbol && getPropertyOfType(getTypeOfSymbol(containingType.symbol), propName);
30172            return prop !== undefined && !!prop.valueDeclaration && isStatic(prop.valueDeclaration);
30173        }
30174
30175        function getSuggestedLibForNonExistentName(name: __String | Identifier) {
30176            const missingName = diagnosticName(name);
30177            const allFeatures = getScriptTargetFeatures();
30178            const libTargets = getOwnKeys(allFeatures);
30179            for (const libTarget of libTargets) {
30180                const containingTypes = getOwnKeys(allFeatures[libTarget]);
30181                if (containingTypes !== undefined && contains(containingTypes, missingName)) {
30182                    return libTarget;
30183                }
30184            }
30185        }
30186
30187        function getSuggestedLibForNonExistentProperty(missingProperty: string, containingType: Type) {
30188            const container = getApparentType(containingType).symbol;
30189            if (!container) {
30190                return undefined;
30191            }
30192            const allFeatures = getScriptTargetFeatures();
30193            const libTargets = getOwnKeys(allFeatures);
30194            for (const libTarget of libTargets) {
30195                const featuresOfLib = allFeatures[libTarget];
30196                const featuresOfContainingType = featuresOfLib[symbolName(container)];
30197                if (featuresOfContainingType !== undefined && contains(featuresOfContainingType, missingProperty)) {
30198                    return libTarget;
30199                }
30200            }
30201        }
30202
30203        function getSuggestedSymbolForNonexistentClassMember(name: string, baseType: Type): Symbol | undefined {
30204            return getSpellingSuggestionForName(name, getPropertiesOfType(baseType), SymbolFlags.ClassMember);
30205        }
30206
30207        function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined {
30208            let props = getPropertiesOfType(containingType);
30209            if (typeof name !== "string") {
30210                const parent = name.parent;
30211                if (isPropertyAccessExpression(parent)) {
30212                    props = filter(props, prop => isValidPropertyAccessForCompletions(parent, containingType, prop));
30213                }
30214                name = idText(name);
30215            }
30216            return getSpellingSuggestionForName(name, props, SymbolFlags.Value);
30217        }
30218
30219        function getSuggestedSymbolForNonexistentJSXAttribute(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined {
30220            const strName = isString(name) ? name : idText(name);
30221            const properties = getPropertiesOfType(containingType);
30222            const jsxSpecific = strName === "for" ? find(properties, x => symbolName(x) === "htmlFor")
30223                : strName === "class" ? find(properties, x => symbolName(x) === "className")
30224                : undefined;
30225            return jsxSpecific ?? getSpellingSuggestionForName(strName, properties, SymbolFlags.Value);
30226        }
30227
30228        function getSuggestionForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): string | undefined {
30229            const suggestion = getSuggestedSymbolForNonexistentProperty(name, containingType);
30230            return suggestion && symbolName(suggestion);
30231        }
30232
30233        function getSuggestedSymbolForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined {
30234            Debug.assert(outerName !== undefined, "outername should always be defined");
30235            const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, /*getSpellingSuggestions*/ true, (symbols, name, meaning, node) => {
30236                Debug.assertEqual(outerName, name, "name should equal outerName");
30237                const symbol = getSymbol(symbols, name, meaning, node);
30238                // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function
30239                // So the table *contains* `x` but `x` isn't actually in scope.
30240                // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion.
30241                if (symbol) return symbol;
30242                let candidates: Symbol[];
30243                if (symbols === globals) {
30244                    const primitives = mapDefined(
30245                        ["string", "number", "boolean", "object", "bigint", "symbol"],
30246                        s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String)
30247                            ? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol
30248                            : undefined);
30249                    candidates = primitives.concat(arrayFrom(symbols.values()));
30250                }
30251                else {
30252                    candidates = arrayFrom(symbols.values());
30253                }
30254                return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning);
30255            });
30256            return result;
30257        }
30258
30259        function getSuggestionForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined {
30260            const symbolResult = getSuggestedSymbolForNonexistentSymbol(location, outerName, meaning);
30261            return symbolResult && symbolName(symbolResult);
30262        }
30263
30264        function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined {
30265            return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember);
30266        }
30267
30268        function getSuggestionForNonexistentExport(name: Identifier, targetModule: Symbol): string | undefined {
30269            const suggestion = getSuggestedSymbolForNonexistentModule(name, targetModule);
30270            return suggestion && symbolName(suggestion);
30271        }
30272
30273        function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression, keyedType: Type): string | undefined {
30274            // check if object type has setter or getter
30275            function hasProp(name: "set" | "get") {
30276                const prop = getPropertyOfObjectType(objectType, name as __String);
30277                if (prop) {
30278                    const s = getSingleCallSignature(getTypeOfSymbol(prop));
30279                    return !!s && getMinArgumentCount(s) >= 1 && isTypeAssignableTo(keyedType, getTypeAtPosition(s, 0));
30280                }
30281                return false;
30282            }
30283
30284            const suggestedMethod = isAssignmentTarget(expr) ? "set" : "get";
30285            if (!hasProp(suggestedMethod)) {
30286                return undefined;
30287            }
30288
30289            let suggestion = tryGetPropertyAccessOrIdentifierToString(expr.expression);
30290            if (suggestion === undefined) {
30291                suggestion = suggestedMethod;
30292            }
30293            else {
30294                suggestion += "." + suggestedMethod;
30295            }
30296
30297            return suggestion;
30298        }
30299
30300        function getSuggestedTypeForNonexistentStringLiteralType(source: StringLiteralType, target: UnionType): StringLiteralType | undefined {
30301            const candidates = target.types.filter((type): type is StringLiteralType => !!(type.flags & TypeFlags.StringLiteral));
30302            return getSpellingSuggestion(source.value, candidates, type => type.value);
30303        }
30304
30305        /**
30306         * Given a name and a list of symbols whose names are *not* equal to the name, return a spelling suggestion if there is one that is close enough.
30307         * Names less than length 3 only check for case-insensitive equality, not levenshtein distance.
30308         *
30309         * If there is a candidate that's the same except for case, return that.
30310         * If there is a candidate that's within one edit of the name, return that.
30311         * Otherwise, return the candidate with the smallest Levenshtein distance,
30312         *    except for candidates:
30313         *      * With no name
30314         *      * Whose meaning doesn't match the `meaning` parameter.
30315         *      * Whose length differs from the target name by more than 0.34 of the length of the name.
30316         *      * Whose levenshtein distance is more than 0.4 of the length of the name
30317         *        (0.4 allows 1 substitution/transposition for every 5 characters,
30318         *         and 1 insertion/deletion at 3 characters)
30319         */
30320        function getSpellingSuggestionForName(name: string, symbols: Symbol[], meaning: SymbolFlags): Symbol | undefined {
30321            return getSpellingSuggestion(name, symbols, getCandidateName);
30322
30323            function getCandidateName(candidate: Symbol) {
30324                const candidateName = symbolName(candidate);
30325                if (startsWith(candidateName, "\"")) {
30326                    return undefined;
30327                }
30328
30329                if (candidate.flags & meaning) {
30330                    return candidateName;
30331                }
30332
30333                if (candidate.flags & SymbolFlags.Alias) {
30334                    const alias = tryResolveAlias(candidate);
30335                    if (alias && alias.flags & meaning) {
30336                        return candidateName;
30337                    }
30338                }
30339
30340                return undefined;
30341            }
30342        }
30343
30344        function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined, isSelfTypeAccess: boolean) {
30345            const valueDeclaration = prop && (prop.flags & SymbolFlags.ClassMember) && prop.valueDeclaration;
30346            if (!valueDeclaration) {
30347                return;
30348            }
30349            const hasPrivateModifier = hasEffectiveModifier(valueDeclaration, ModifierFlags.Private);
30350            const hasPrivateIdentifier = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) && isPrivateIdentifier(prop.valueDeclaration.name);
30351            if (!hasPrivateModifier && !hasPrivateIdentifier) {
30352                return;
30353            }
30354            if (nodeForCheckWriteOnly && isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & SymbolFlags.SetAccessor)) {
30355                return;
30356            }
30357            if (isSelfTypeAccess) {
30358                // Find any FunctionLikeDeclaration because those create a new 'this' binding. But this should only matter for methods (or getters/setters).
30359                const containingMethod = findAncestor(nodeForCheckWriteOnly, isFunctionLikeDeclaration);
30360                if (containingMethod && containingMethod.symbol === prop) {
30361                    return;
30362                }
30363            }
30364
30365            (getCheckFlags(prop) & CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop)!.isReferenced = SymbolFlags.All;
30366        }
30367
30368        function isSelfTypeAccess(name: Expression | QualifiedName, parent: Symbol | undefined) {
30369            return name.kind === SyntaxKind.ThisKeyword
30370                || !!parent && isEntityNameExpression(name) && parent === getResolvedSymbol(getFirstIdentifier(name));
30371        }
30372
30373        function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: __String): boolean {
30374            switch (node.kind) {
30375                case SyntaxKind.PropertyAccessExpression:
30376                    return isValidPropertyAccessWithType(node, node.expression.kind === SyntaxKind.SuperKeyword, propertyName, getWidenedType(checkExpression(node.expression)));
30377                case SyntaxKind.QualifiedName:
30378                    return isValidPropertyAccessWithType(node, /*isSuper*/ false, propertyName, getWidenedType(checkExpression(node.left)));
30379                case SyntaxKind.ImportType:
30380                    return isValidPropertyAccessWithType(node, /*isSuper*/ false, propertyName, getTypeFromTypeNode(node));
30381            }
30382        }
30383
30384        /**
30385         * Checks if an existing property access is valid for completions purposes.
30386         * @param node a property access-like node where we want to check if we can access a property.
30387         * This node does not need to be an access of the property we are checking.
30388         * e.g. in completions, this node will often be an incomplete property access node, as in `foo.`.
30389         * Besides providing a location (i.e. scope) used to check property accessibility, we use this node for
30390         * computing whether this is a `super` property access.
30391         * @param type the type whose property we are checking.
30392         * @param property the accessed property's symbol.
30393         */
30394        function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName, type: Type, property: Symbol): boolean {
30395            return isPropertyAccessible(node,
30396                node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword,
30397                /* isWrite */ false,
30398                type,
30399                property);
30400            // Previously we validated the 'this' type of methods but this adversely affected performance. See #31377 for more context.
30401        }
30402
30403        function isValidPropertyAccessWithType(
30404            node: PropertyAccessExpression | QualifiedName | ImportTypeNode,
30405            isSuper: boolean,
30406            propertyName: __String,
30407            type: Type): boolean {
30408
30409            // Short-circuiting for improved performance.
30410            if (isTypeAny(type)) {
30411                return true;
30412            }
30413
30414            const prop = getPropertyOfType(type, propertyName);
30415            return !!prop && isPropertyAccessible(node, isSuper, /* isWrite */ false, type, prop);
30416        }
30417
30418        /**
30419         * Checks if a property can be accessed in a location.
30420         * The location is given by the `node` parameter.
30421         * The node does not need to be a property access.
30422         * @param node location where to check property accessibility
30423         * @param isSuper whether to consider this a `super` property access, e.g. `super.foo`.
30424         * @param isWrite whether this is a write access, e.g. `++foo.x`.
30425         * @param containingType type where the property comes from.
30426         * @param property property symbol.
30427         */
30428        function isPropertyAccessible(
30429            node: Node,
30430            isSuper: boolean,
30431            isWrite: boolean,
30432            containingType: Type,
30433            property: Symbol): boolean {
30434
30435            // Short-circuiting for improved performance.
30436            if (isTypeAny(containingType)) {
30437                return true;
30438            }
30439
30440            // A #private property access in an optional chain is an error dealt with by the parser.
30441             // The checker does not check for it, so we need to do our own check here.
30442             if (property.valueDeclaration && isPrivateIdentifierClassElementDeclaration(property.valueDeclaration)) {
30443                const declClass = getContainingClass(property.valueDeclaration);
30444                return !isOptionalChain(node) && !!findAncestor(node, parent => parent === declClass);
30445            }
30446
30447            return checkPropertyAccessibilityAtLocation(node, isSuper, isWrite, containingType, property);
30448        }
30449
30450        /**
30451         * Return the symbol of the for-in variable declared or referenced by the given for-in statement.
30452         */
30453        function getForInVariableSymbol(node: ForInStatement): Symbol | undefined {
30454            const initializer = node.initializer;
30455            if (initializer.kind === SyntaxKind.VariableDeclarationList) {
30456                const variable = (initializer as VariableDeclarationList).declarations[0];
30457                if (variable && !isBindingPattern(variable.name)) {
30458                    return getSymbolOfNode(variable);
30459                }
30460            }
30461            else if (initializer.kind === SyntaxKind.Identifier) {
30462                return getResolvedSymbol(initializer as Identifier);
30463            }
30464            return undefined;
30465        }
30466
30467        /**
30468         * Return true if the given type is considered to have numeric property names.
30469         */
30470        function hasNumericPropertyNames(type: Type) {
30471            return getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, numberType);
30472        }
30473
30474        /**
30475         * Return true if given node is an expression consisting of an identifier (possibly parenthesized)
30476         * that references a for-in variable for an object with numeric property names.
30477         */
30478        function isForInVariableForNumericPropertyNames(expr: Expression) {
30479            const e = skipParentheses(expr);
30480            if (e.kind === SyntaxKind.Identifier) {
30481                const symbol = getResolvedSymbol(e as Identifier);
30482                if (symbol.flags & SymbolFlags.Variable) {
30483                    let child: Node = expr;
30484                    let node = expr.parent;
30485                    while (node) {
30486                        if (node.kind === SyntaxKind.ForInStatement &&
30487                            child === (node as ForInStatement).statement &&
30488                            getForInVariableSymbol(node as ForInStatement) === symbol &&
30489                            hasNumericPropertyNames(getTypeOfExpression((node as ForInStatement).expression))) {
30490                            return true;
30491                        }
30492                        child = node;
30493                        node = node.parent;
30494                    }
30495                }
30496            }
30497            return false;
30498        }
30499
30500        function checkIndexedAccess(node: ElementAccessExpression, checkMode: CheckMode | undefined): Type {
30501            return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain, checkMode) :
30502                checkElementAccessExpression(node, checkNonNullExpression(node.expression), checkMode);
30503        }
30504
30505        function checkElementAccessChain(node: ElementAccessChain, checkMode: CheckMode | undefined) {
30506            const exprType = checkExpression(node.expression);
30507            const nonOptionalType = getOptionalExpressionType(exprType, node.expression);
30508            return propagateOptionalTypeMarker(checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression), checkMode), node, nonOptionalType !== exprType);
30509        }
30510
30511        function checkElementAccessExpression(node: ElementAccessExpression, exprType: Type, checkMode: CheckMode | undefined): Type {
30512            const objectType = getAssignmentTargetKind(node) !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(exprType) : exprType;
30513            const indexExpression = node.argumentExpression;
30514            const indexType = checkExpression(indexExpression);
30515
30516            if (isErrorType(objectType) || objectType === silentNeverType) {
30517                return objectType;
30518            }
30519
30520            if (isConstEnumObjectType(objectType) && !isStringLiteralLike(indexExpression)) {
30521                error(indexExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
30522                return errorType;
30523            }
30524
30525            if (isConstEnumObjectType(objectType)) {
30526                checkConstEnumRelate(node, objectType.symbol);
30527            }
30528
30529            const effectiveIndexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType;
30530            const accessFlags = isAssignmentTarget(node) ?
30531                AccessFlags.Writing | (isGenericObjectType(objectType) && !isThisTypeParameter(objectType) ? AccessFlags.NoIndexSignatures : 0) :
30532                AccessFlags.ExpressionPosition;
30533            const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, accessFlags, node) || errorType;
30534            return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode), node);
30535        }
30536
30537        function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement {
30538            return isCallOrNewExpression(node) || isTaggedTemplateExpression(node) || isJsxOpeningLikeElement(node);
30539        }
30540
30541        function resolveUntypedCall(node: CallLikeExpression): Signature {
30542            if (callLikeExpressionMayHaveTypeArguments(node)) {
30543                // Check type arguments even though we will give an error that untyped calls may not accept type arguments.
30544                // This gets us diagnostics for the type arguments and marks them as referenced.
30545                forEach(node.typeArguments, checkSourceElement);
30546            }
30547
30548            if (node.kind === SyntaxKind.TaggedTemplateExpression) {
30549                checkExpression(node.template);
30550            }
30551            else if (isJsxOpeningLikeElement(node)) {
30552                checkExpression(node.attributes);
30553            }
30554            else if (node.kind !== SyntaxKind.Decorator) {
30555                forEach((node as CallExpression).arguments, argument => {
30556                    checkExpression(argument);
30557                });
30558            }
30559            return anySignature;
30560        }
30561
30562        function resolveErrorCall(node: CallLikeExpression): Signature {
30563            resolveUntypedCall(node);
30564            return unknownSignature;
30565        }
30566
30567        // Re-order candidate signatures into the result array. Assumes the result array to be empty.
30568        // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
30569        // A nit here is that we reorder only signatures that belong to the same symbol,
30570        // so order how inherited signatures are processed is still preserved.
30571        // interface A { (x: string): void }
30572        // interface B extends A { (x: 'foo'): string }
30573        // const b: B;
30574        // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
30575        function reorderCandidates(signatures: readonly Signature[], result: Signature[], callChainFlags: SignatureFlags): void {
30576            let lastParent: Node | undefined;
30577            let lastSymbol: Symbol | undefined;
30578            let cutoffIndex = 0;
30579            let index: number | undefined;
30580            let specializedIndex = -1;
30581            let spliceIndex: number;
30582            Debug.assert(!result.length);
30583            for (const signature of signatures) {
30584                const symbol = signature.declaration && getSymbolOfNode(signature.declaration);
30585                const parent = signature.declaration && signature.declaration.parent;
30586                if (!lastSymbol || symbol === lastSymbol) {
30587                    if (lastParent && parent === lastParent) {
30588                        index = index! + 1;
30589                    }
30590                    else {
30591                        lastParent = parent;
30592                        index = cutoffIndex;
30593                    }
30594                }
30595                else {
30596                    // current declaration belongs to a different symbol
30597                    // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex
30598                    index = cutoffIndex = result.length;
30599                    lastParent = parent;
30600                }
30601                lastSymbol = symbol;
30602
30603                // specialized signatures always need to be placed before non-specialized signatures regardless
30604                // of the cutoff position; see GH#1133
30605                if (signatureHasLiteralTypes(signature)) {
30606                    specializedIndex++;
30607                    spliceIndex = specializedIndex;
30608                    // The cutoff index always needs to be greater than or equal to the specialized signature index
30609                    // in order to prevent non-specialized signatures from being added before a specialized
30610                    // signature.
30611                    cutoffIndex++;
30612                }
30613                else {
30614                    spliceIndex = index;
30615                }
30616
30617                result.splice(spliceIndex, 0, callChainFlags ? getOptionalCallSignature(signature, callChainFlags) : signature);
30618            }
30619        }
30620
30621        function isSpreadArgument(arg: Expression | undefined): arg is Expression {
30622            return !!arg && (arg.kind === SyntaxKind.SpreadElement || arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).isSpread);
30623        }
30624
30625        function getSpreadArgumentIndex(args: readonly Expression[]): number {
30626            return findIndex(args, isSpreadArgument);
30627        }
30628
30629        function acceptsVoid(t: Type): boolean {
30630            return !!(t.flags & TypeFlags.Void);
30631        }
30632
30633        function acceptsVoidUndefinedUnknownOrAny(t: Type): boolean {
30634            return !!(t.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Unknown | TypeFlags.Any));
30635        }
30636
30637        function hasCorrectArity(node: CallLikeExpression, args: readonly Expression[], signature: Signature, signatureHelpTrailingComma = false) {
30638            let argCount: number;
30639            let callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments
30640            let effectiveParameterCount = getParameterCount(signature);
30641            let effectiveMinimumArguments = getMinArgumentCount(signature);
30642
30643            if (node.kind === SyntaxKind.TaggedTemplateExpression) {
30644                argCount = args.length;
30645                if (node.template.kind === SyntaxKind.TemplateExpression) {
30646                    // If a tagged template expression lacks a tail literal, the call is incomplete.
30647                    // Specifically, a template only can end in a TemplateTail or a Missing literal.
30648                    const lastSpan = last(node.template.templateSpans); // we should always have at least one span.
30649                    callIsIncomplete = nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated;
30650                }
30651                else {
30652                    // If the template didn't end in a backtick, or its beginning occurred right prior to EOF,
30653                    // then this might actually turn out to be a TemplateHead in the future;
30654                    // so we consider the call to be incomplete.
30655                    const templateLiteral = node.template as LiteralExpression;
30656                    Debug.assert(templateLiteral.kind === SyntaxKind.NoSubstitutionTemplateLiteral);
30657                    callIsIncomplete = !!templateLiteral.isUnterminated;
30658                }
30659            }
30660            else if (node.kind === SyntaxKind.Decorator) {
30661                argCount = getDecoratorArgumentCount(node, signature);
30662            }
30663            else if (isJsxOpeningLikeElement(node)) {
30664                callIsIncomplete = node.attributes.end === node.end;
30665                if (callIsIncomplete) {
30666                    return true;
30667                }
30668                argCount = effectiveMinimumArguments === 0 ? args.length : 1;
30669                effectiveParameterCount = args.length === 0 ? effectiveParameterCount : 1; // class may have argumentless ctor functions - still resolve ctor and compare vs props member type
30670                effectiveMinimumArguments = Math.min(effectiveMinimumArguments, 1); // sfc may specify context argument - handled by framework and not typechecked
30671            }
30672            else if (!node.arguments) {
30673                // This only happens when we have something of the form: 'new C'
30674                Debug.assert(node.kind === SyntaxKind.NewExpression);
30675                return getMinArgumentCount(signature) === 0;
30676            }
30677            else {
30678                argCount = signatureHelpTrailingComma ? args.length + 1 : args.length;
30679
30680                // If we are missing the close parenthesis, the call is incomplete.
30681                callIsIncomplete = node.arguments.end === node.end;
30682
30683                // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range.
30684                const spreadArgIndex = getSpreadArgumentIndex(args);
30685                if (spreadArgIndex >= 0) {
30686                    return spreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || spreadArgIndex < getParameterCount(signature));
30687                }
30688            }
30689
30690            // Too many arguments implies incorrect arity.
30691            if (!hasEffectiveRestParameter(signature) && argCount > effectiveParameterCount) {
30692                return false;
30693            }
30694
30695            // If the call is incomplete, we should skip the lower bound check.
30696            // JSX signatures can have extra parameters provided by the library which we don't check
30697            if (callIsIncomplete || argCount >= effectiveMinimumArguments) {
30698                return true;
30699            }
30700            for (let i = argCount; i < effectiveMinimumArguments; i++) {
30701                const type = getTypeAtPosition(signature, i);
30702                if (filterType(type, isInJSFile(node) && !strictNullChecks ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid).flags & TypeFlags.Never) {
30703                    return false;
30704                }
30705            }
30706            return true;
30707        }
30708
30709        function hasCorrectTypeArgumentArity(signature: Signature, typeArguments: NodeArray<TypeNode> | undefined, virtual?: boolean) {
30710            // If the user supplied type arguments, but the number of type arguments does not match
30711            // the declared number of type parameters, the call has an incorrect arity.
30712            const numTypeParameters = virtual ? 1 : length(signature.typeParameters);
30713            const minTypeArgumentCount = virtual ? 1 : getMinTypeArgumentCount(signature.typeParameters);
30714            return !some(typeArguments) ||
30715                (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters);
30716        }
30717
30718        // If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
30719        function getSingleCallSignature(type: Type): Signature | undefined {
30720            return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false);
30721        }
30722
30723        function getSingleCallOrConstructSignature(type: Type): Signature | undefined {
30724            return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false) ||
30725                getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ false);
30726        }
30727
30728        function getSingleSignature(type: Type, kind: SignatureKind, allowMembers: boolean): Signature | undefined {
30729            if (type.flags & TypeFlags.Object) {
30730                const resolved = resolveStructuredTypeMembers(type as ObjectType);
30731                if (allowMembers || resolved.properties.length === 0 && resolved.indexInfos.length === 0) {
30732                    if (kind === SignatureKind.Call && resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0) {
30733                        return resolved.callSignatures[0];
30734                    }
30735                    if (kind === SignatureKind.Construct && resolved.constructSignatures.length === 1 && resolved.callSignatures.length === 0) {
30736                        return resolved.constructSignatures[0];
30737                    }
30738                }
30739            }
30740            return undefined;
30741        }
30742
30743        // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
30744        function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, inferenceContext?: InferenceContext, compareTypes?: TypeComparer): Signature {
30745            const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes);
30746            // We clone the inferenceContext to avoid fixing. For example, when the source signature is <T>(x: T) => T[] and
30747            // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any')
30748            // for T but leave it possible to later infer '[any]' back to A.
30749            const restType = getEffectiveRestType(contextualSignature);
30750            const mapper = inferenceContext && (restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper);
30751            const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature;
30752            applyToParameterTypes(sourceSignature, signature, (source, target) => {
30753                // Type parameters from outer context referenced by source type are fixed by instantiation of the source type
30754                inferTypes(context.inferences, source, target);
30755            });
30756            if (!inferenceContext) {
30757                applyToReturnTypes(contextualSignature, signature, (source, target) => {
30758                    inferTypes(context.inferences, source, target, InferencePriority.ReturnType);
30759                });
30760            }
30761            return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration));
30762        }
30763
30764        function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, checkMode: CheckMode, context: InferenceContext): Type[] {
30765            const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node);
30766            const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode);
30767            inferTypes(context.inferences, checkAttrType, paramType);
30768            return getInferredTypes(context);
30769        }
30770
30771        function getThisArgumentType(thisArgumentNode: LeftHandSideExpression | undefined) {
30772            if (!thisArgumentNode) {
30773                return voidType;
30774            }
30775            const thisArgumentType = checkExpression(thisArgumentNode);
30776            return isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType) :
30777                isOptionalChain(thisArgumentNode.parent) ? removeOptionalTypeMarker(thisArgumentType) :
30778                thisArgumentType;
30779        }
30780
30781        function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: readonly Expression[], checkMode: CheckMode, context: InferenceContext): Type[] {
30782            if (isJsxOpeningLikeElement(node)) {
30783                return inferJsxTypeArguments(node, signature, checkMode, context);
30784            }
30785
30786            // If a contextual type is available, infer from that type to the return type of the call expression. For
30787            // example, given a 'function wrap<T, U>(cb: (x: T) => U): (x: T) => U' and a call expression
30788            // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the
30789            // return type of 'wrap'.
30790            if (node.kind !== SyntaxKind.Decorator) {
30791                const skipBindingPatterns = every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p));
30792                const contextualType = getContextualType(node, skipBindingPatterns ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
30793                if (contextualType) {
30794                    const inferenceTargetType = getReturnTypeOfSignature(signature);
30795                    if (couldContainTypeVariables(inferenceTargetType)) {
30796                        const outerContext = getInferenceContext(node);
30797                        const isFromBindingPattern = !skipBindingPatterns && getContextualType(node, ContextFlags.SkipBindingPatterns) !== contextualType;
30798                        // A return type inference from a binding pattern can be used in instantiating the contextual
30799                        // type of an argument later in inference, but cannot stand on its own as the final return type.
30800                        // It is incorporated into `context.returnMapper` which is used in `instantiateContextualType`,
30801                        // but doesn't need to go into `context.inferences`. This allows a an array binding pattern to
30802                        // produce a tuple for `T` in
30803                        //   declare function f<T>(cb: () => T): T;
30804                        //   const [e1, e2, e3] = f(() => [1, "hi", true]);
30805                        // but does not produce any inference for `T` in
30806                        //   declare function f<T>(): T;
30807                        //   const [e1, e2, e3] = f();
30808                        if (!isFromBindingPattern) {
30809                            // We clone the inference context to avoid disturbing a resolution in progress for an
30810                            // outer call expression. Effectively we just want a snapshot of whatever has been
30811                            // inferred for any outer call expression so far.
30812                            const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
30813                            const instantiatedType = instantiateType(contextualType, outerMapper);
30814                            // If the contextual type is a generic function type with a single call signature, we
30815                            // instantiate the type with its own type parameters and type arguments. This ensures that
30816                            // the type parameters are not erased to type any during type inference such that they can
30817                            // be inferred as actual types from the contextual type. For example:
30818                            //   declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
30819                            //   const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
30820                            // Above, the type of the 'value' parameter is inferred to be 'A'.
30821                            const contextualSignature = getSingleCallSignature(instantiatedType);
30822                            const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
30823                                getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
30824                                instantiatedType;
30825                            // Inferences made from return types have lower priority than all other inferences.
30826                            inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
30827                        }
30828                        // Create a type mapper for instantiating generic contextual types using the inferences made
30829                        // from the return type. We need a separate inference pass here because (a) instantiation of
30830                        // the source type uses the outer context's return mapper (which excludes inferences made from
30831                        // outer arguments), and (b) we don't want any further inferences going into this context.
30832                        const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
30833                        const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
30834                        inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
30835                        context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
30836                    }
30837                }
30838            }
30839
30840            const restType = getNonArrayRestType(signature);
30841            const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
30842            if (restType && restType.flags & TypeFlags.TypeParameter) {
30843                const info = find(context.inferences, info => info.typeParameter === restType);
30844                if (info) {
30845                    info.impliedArity = findIndex(args, isSpreadArgument, argCount) < 0 ? args.length - argCount : undefined;
30846                }
30847            }
30848
30849            const thisType = getThisTypeOfSignature(signature);
30850            if (thisType && couldContainTypeVariables(thisType)) {
30851                const thisArgumentNode = getThisArgumentOfCall(node);
30852                inferTypes(context.inferences, getThisArgumentType(thisArgumentNode), thisType);
30853            }
30854
30855            for (let i = 0; i < argCount; i++) {
30856                const arg = args[i];
30857                if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg))) {
30858                    const paramType = getTypeAtPosition(signature, i);
30859                    if (couldContainTypeVariables(paramType)) {
30860                        const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
30861                        inferTypes(context.inferences, argType, paramType);
30862                    }
30863                }
30864            }
30865
30866            if (restType && couldContainTypeVariables(restType)) {
30867                const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, context, checkMode);
30868                inferTypes(context.inferences, spreadType, restType);
30869            }
30870
30871            return getInferredTypes(context);
30872        }
30873
30874        function getMutableArrayOrTupleType(type: Type) {
30875            return type.flags & TypeFlags.Union ? mapType(type, getMutableArrayOrTupleType) :
30876                type.flags & TypeFlags.Any || isMutableArrayOrTuple(getBaseConstraintOfType(type) || type) ? type :
30877                isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.elementFlags, /*readonly*/ false, type.target.labeledElementDeclarations) :
30878                createTupleType([type], [ElementFlags.Variadic]);
30879        }
30880
30881        function getSpreadArgumentType(args: readonly Expression[], index: number, argCount: number, restType: Type, context: InferenceContext | undefined, checkMode: CheckMode) {
30882            if (index >= argCount - 1) {
30883                const arg = args[argCount - 1];
30884                if (isSpreadArgument(arg)) {
30885                    // We are inferring from a spread expression in the last argument position, i.e. both the parameter
30886                    // and the argument are ...x forms.
30887                    return getMutableArrayOrTupleType(arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type :
30888                        checkExpressionWithContextualType((arg as SpreadElement).expression, restType, context, checkMode));
30889                }
30890            }
30891            const types = [];
30892            const flags = [];
30893            const names = [];
30894            for (let i = index; i < argCount; i++) {
30895                const arg = args[i];
30896                if (isSpreadArgument(arg)) {
30897                    const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type : checkExpression((arg as SpreadElement).expression);
30898                    if (isArrayLikeType(spreadType)) {
30899                        types.push(spreadType);
30900                        flags.push(ElementFlags.Variadic);
30901                    }
30902                    else {
30903                        types.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg));
30904                        flags.push(ElementFlags.Rest);
30905                    }
30906                }
30907                else {
30908                    const contextualType = getIndexedAccessType(restType, getNumberLiteralType(i - index), AccessFlags.Contextual);
30909                    const argType = checkExpressionWithContextualType(arg, contextualType, context, checkMode);
30910                    const hasPrimitiveContextualType = maybeTypeOfKind(contextualType, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping);
30911                    types.push(hasPrimitiveContextualType ? getRegularTypeOfLiteralType(argType) : getWidenedLiteralType(argType));
30912                    flags.push(ElementFlags.Required);
30913                }
30914                if (arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).tupleNameSource) {
30915                    names.push((arg as SyntheticExpression).tupleNameSource!);
30916                }
30917            }
30918            return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined);
30919        }
30920
30921        function checkTypeArguments(signature: Signature, typeArgumentNodes: readonly TypeNode[], reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | undefined {
30922            const isJavascript = isInJSFile(signature.declaration);
30923            const typeParameters = signature.typeParameters!;
30924            const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript);
30925            let mapper: TypeMapper | undefined;
30926            for (let i = 0; i < typeArgumentNodes.length; i++) {
30927                Debug.assert(typeParameters[i] !== undefined, "Should not call checkTypeArguments with too many type arguments");
30928                const constraint = getConstraintOfTypeParameter(typeParameters[i]);
30929                if (constraint) {
30930                    const errorInfo = reportErrors && headMessage ? (() => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1)) : undefined;
30931                    const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1;
30932                    if (!mapper) {
30933                        mapper = createTypeMapper(typeParameters, typeArgumentTypes);
30934                    }
30935                    const typeArgument = typeArgumentTypes[i];
30936                    if (!checkTypeAssignableTo(
30937                        typeArgument,
30938                        getTypeWithThisArgument(instantiateType(constraint, mapper), typeArgument),
30939                        reportErrors ? typeArgumentNodes[i] : undefined,
30940                        typeArgumentHeadMessage,
30941                        errorInfo)) {
30942                        return undefined;
30943                    }
30944                }
30945            }
30946            return typeArgumentTypes;
30947        }
30948
30949        function getJsxReferenceKind(node: JsxOpeningLikeElement): JsxReferenceKind {
30950            if (isJsxIntrinsicIdentifier(node.tagName)) {
30951                return JsxReferenceKind.Mixed;
30952            }
30953            const tagType = getApparentType(checkExpression(node.tagName));
30954            if (length(getSignaturesOfType(tagType, SignatureKind.Construct))) {
30955                return JsxReferenceKind.Component;
30956            }
30957            if (length(getSignaturesOfType(tagType, SignatureKind.Call))) {
30958                return JsxReferenceKind.Function;
30959            }
30960            return JsxReferenceKind.Mixed;
30961        }
30962
30963        /**
30964         * Check if the given signature can possibly be a signature called by the JSX opening-like element.
30965         * @param node a JSX opening-like element we are trying to figure its call signature
30966         * @param signature a candidate signature we are trying whether it is a call signature
30967         * @param relation a relationship to check parameter and argument type
30968         */
30969        function checkApplicableSignatureForJsxOpeningLikeElement(
30970            node: JsxOpeningLikeElement,
30971            signature: Signature,
30972            relation: ESMap<string, RelationComparisonResult>,
30973            checkMode: CheckMode,
30974            reportErrors: boolean,
30975            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
30976            errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean }
30977        ) {
30978            // Stateless function components can have maximum of three arguments: "props", "context", and "updater".
30979            // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
30980            // can be specified by users through attributes property.
30981            const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node);
30982            const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*inferenceContext*/ undefined, checkMode);
30983            return checkTagNameDoesNotExpectTooManyArguments() && checkTypeRelatedToAndOptionallyElaborate(
30984                attributesType,
30985                paramType,
30986                relation,
30987                reportErrors ? node.tagName : undefined,
30988                node.attributes,
30989                /*headMessage*/ undefined,
30990                containingMessageChain,
30991                errorOutputContainer);
30992
30993            function checkTagNameDoesNotExpectTooManyArguments(): boolean {
30994                if (getJsxNamespaceContainerForImplicitImport(node)) {
30995                    return true; // factory is implicitly jsx/jsxdev - assume it fits the bill, since we don't strongly look for the jsx/jsxs/jsxDEV factory APIs anywhere else (at least not yet)
30996                }
30997                const tagType = isJsxOpeningElement(node) || isJsxSelfClosingElement(node) && !isJsxIntrinsicIdentifier(node.tagName) ? checkExpression(node.tagName) : undefined;
30998                if (!tagType) {
30999                    return true;
31000                }
31001                const tagCallSignatures = getSignaturesOfType(tagType, SignatureKind.Call);
31002                if (!length(tagCallSignatures)) {
31003                    return true;
31004                }
31005                const factory = getJsxFactoryEntity(node);
31006                if (!factory) {
31007                    return true;
31008                }
31009                const factorySymbol = resolveEntityName(factory, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, node);
31010                if (!factorySymbol) {
31011                    return true;
31012                }
31013
31014                const factoryType = getTypeOfSymbol(factorySymbol);
31015                const callSignatures = getSignaturesOfType(factoryType, SignatureKind.Call);
31016                if (!length(callSignatures)) {
31017                    return true;
31018                }
31019
31020                let hasFirstParamSignatures = false;
31021                let maxParamCount = 0;
31022                // Check that _some_ first parameter expects a FC-like thing, and that some overload of the SFC expects an acceptable number of arguments
31023                for (const sig of callSignatures) {
31024                    const firstparam = getTypeAtPosition(sig, 0);
31025                    const signaturesOfParam = getSignaturesOfType(firstparam, SignatureKind.Call);
31026                    if (!length(signaturesOfParam)) continue;
31027                    for (const paramSig of signaturesOfParam) {
31028                        hasFirstParamSignatures = true;
31029                        if (hasEffectiveRestParameter(paramSig)) {
31030                            return true; // some signature has a rest param, so function components can have an arbitrary number of arguments
31031                        }
31032                        const paramCount = getParameterCount(paramSig);
31033                        if (paramCount > maxParamCount) {
31034                            maxParamCount = paramCount;
31035                        }
31036                    }
31037                }
31038                if (!hasFirstParamSignatures) {
31039                    // Not a single signature had a first parameter which expected a signature - for back compat, and
31040                    // to guard against generic factories which won't have signatures directly, do not error
31041                    return true;
31042                }
31043                let absoluteMinArgCount = Infinity;
31044                for (const tagSig of tagCallSignatures) {
31045                    const tagRequiredArgCount = getMinArgumentCount(tagSig);
31046                    if (tagRequiredArgCount < absoluteMinArgCount) {
31047                        absoluteMinArgCount = tagRequiredArgCount;
31048                    }
31049                }
31050                if (absoluteMinArgCount <= maxParamCount) {
31051                    return true; // some signature accepts the number of arguments the function component provides
31052                }
31053
31054                if (reportErrors) {
31055                    const diag = createDiagnosticForNode(node.tagName, Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, entityNameToString(node.tagName), absoluteMinArgCount, entityNameToString(factory), maxParamCount);
31056                    const tagNameDeclaration = getSymbolAtLocation(node.tagName)?.valueDeclaration;
31057                    if (tagNameDeclaration) {
31058                        addRelatedInfo(diag, createDiagnosticForNode(tagNameDeclaration, Diagnostics._0_is_declared_here, entityNameToString(node.tagName)));
31059                    }
31060                    if (errorOutputContainer && errorOutputContainer.skipLogging) {
31061                        (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
31062                    }
31063                    if (!errorOutputContainer.skipLogging) {
31064                        diagnostics.add(diag);
31065                    }
31066                }
31067                return false;
31068            }
31069        }
31070
31071        function getSignatureApplicabilityError(
31072            node: CallLikeExpression,
31073            args: readonly Expression[],
31074            signature: Signature,
31075            relation: ESMap<string, RelationComparisonResult>,
31076            checkMode: CheckMode,
31077            reportErrors: boolean,
31078            containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined,
31079        ): readonly Diagnostic[] | undefined {
31080
31081            const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } = { errors: undefined, skipLogging: true };
31082            if (isJsxOpeningLikeElement(node)) {
31083                if (!checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) {
31084                    Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors");
31085                    return errorOutputContainer.errors || emptyArray;
31086                }
31087                return undefined;
31088            }
31089            const thisType = getThisTypeOfSignature(signature);
31090            if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) {
31091                // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType
31092                // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible.
31093                // If the expression is a new expression, then the check is skipped.
31094                const thisArgumentNode = getThisArgumentOfCall(node);
31095                const thisArgumentType = getThisArgumentType(thisArgumentNode);
31096                const errorNode = reportErrors ? (thisArgumentNode || node) : undefined;
31097                const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1;
31098                if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) {
31099                    Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors");
31100                    return errorOutputContainer.errors || emptyArray;
31101                }
31102            }
31103            const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
31104            const restType = getNonArrayRestType(signature);
31105            const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
31106            for (let i = 0; i < argCount; i++) {
31107                const arg = args[i];
31108                if (arg.kind !== SyntaxKind.OmittedExpression) {
31109                    const paramType = getTypeAtPosition(signature, i);
31110                    const argType = checkExpressionWithContextualType(arg, paramType, /*inferenceContext*/ undefined, checkMode);
31111                    // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive),
31112                    // we obtain the regular type of any object literal arguments because we may not have inferred complete
31113                    // parameter types yet and therefore excess property checks may yield false positives (see #17041).
31114                    const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType;
31115                    if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) {
31116                        Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors");
31117                        maybeAddMissingAwaitInfo(arg, checkArgType, paramType);
31118                        return errorOutputContainer.errors || emptyArray;
31119                    }
31120                }
31121            }
31122            if (restType) {
31123                const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined, checkMode);
31124                const restArgCount = args.length - argCount;
31125                const errorNode = !reportErrors ? undefined :
31126                    restArgCount === 0 ? node :
31127                    restArgCount === 1 ? args[argCount] :
31128                    setTextRangePosEnd(createSyntheticExpression(node, spreadType), args[argCount].pos, args[args.length - 1].end);
31129                if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) {
31130                    Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors");
31131                    maybeAddMissingAwaitInfo(errorNode, spreadType, restType);
31132                    return errorOutputContainer.errors || emptyArray;
31133                }
31134            }
31135            return undefined;
31136
31137            function maybeAddMissingAwaitInfo(errorNode: Node | undefined, source: Type, target: Type) {
31138                if (errorNode && reportErrors && errorOutputContainer.errors && errorOutputContainer.errors.length) {
31139                    // Bail if target is Promise-like---something else is wrong
31140                    if (getAwaitedTypeOfPromise(target)) {
31141                        return;
31142                    }
31143                    const awaitedTypeOfSource = getAwaitedTypeOfPromise(source);
31144                    if (awaitedTypeOfSource && isTypeRelatedTo(awaitedTypeOfSource, target, relation)) {
31145                        addRelatedInfo(errorOutputContainer.errors[0], createDiagnosticForNode(errorNode, Diagnostics.Did_you_forget_to_use_await));
31146                    }
31147                }
31148            }
31149        }
31150
31151        /**
31152         * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise.
31153         */
31154        function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression | undefined {
31155            const expression = node.kind === SyntaxKind.CallExpression ? node.expression :
31156                node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag : undefined;
31157            if (expression) {
31158                const callee = skipOuterExpressions(expression);
31159                if (isAccessExpression(callee)) {
31160                    return callee.expression;
31161                }
31162            }
31163        }
31164
31165        function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember) {
31166            const result = parseNodeFactory.createSyntheticExpression(type, isSpread, tupleNameSource);
31167            setTextRange(result, parent);
31168            setParent(result, parent);
31169            return result;
31170        }
31171
31172        /**
31173         * Returns the effective arguments for an expression that works like a function invocation.
31174         */
31175        function getEffectiveCallArguments(node: CallLikeExpression): readonly Expression[] {
31176            if (node.kind === SyntaxKind.TaggedTemplateExpression) {
31177                const template = node.template;
31178                const args: Expression[] = [createSyntheticExpression(template, getGlobalTemplateStringsArrayType())];
31179                if (template.kind === SyntaxKind.TemplateExpression) {
31180                    forEach(template.templateSpans, span => {
31181                        args.push(span.expression);
31182                    });
31183                }
31184                return args;
31185            }
31186            if (node.kind === SyntaxKind.Decorator) {
31187                return getEffectiveDecoratorArguments(node);
31188            }
31189            if (isJsxOpeningLikeElement(node)) {
31190                return node.attributes.properties.length > 0 || (isJsxOpeningElement(node) && node.parent.children.length > 0) ? [node.attributes] : emptyArray;
31191            }
31192            const args = node.arguments || emptyArray;
31193            const spreadIndex = getSpreadArgumentIndex(args);
31194            if (spreadIndex >= 0) {
31195                // Create synthetic arguments from spreads of tuple types.
31196                const effectiveArgs = args.slice(0, spreadIndex);
31197                for (let i = spreadIndex; i < args.length; i++) {
31198                    const arg = args[i];
31199                    // We can call checkExpressionCached because spread expressions never have a contextual type.
31200                    const spreadType = arg.kind === SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg as SpreadElement).expression) : checkExpressionCached((arg as SpreadElement).expression));
31201                    if (spreadType && isTupleType(spreadType)) {
31202                        forEach(getTypeArguments(spreadType), (t, i) => {
31203                            const flags = spreadType.target.elementFlags[i];
31204                            const syntheticArg = createSyntheticExpression(arg, flags & ElementFlags.Rest ? createArrayType(t) : t,
31205                                !!(flags & ElementFlags.Variable), spreadType.target.labeledElementDeclarations?.[i]);
31206                            effectiveArgs.push(syntheticArg);
31207                        });
31208                    }
31209                    else {
31210                        effectiveArgs.push(arg);
31211                    }
31212                }
31213                return effectiveArgs;
31214            }
31215            return args;
31216        }
31217
31218        /**
31219         * Returns the synthetic argument list for a decorator invocation.
31220         */
31221        function getEffectiveDecoratorArguments(node: Decorator): readonly Expression[] {
31222            const parent = node.parent;
31223            const expr = node.expression;
31224            switch (parent.kind) {
31225                case SyntaxKind.ClassDeclaration:
31226                case SyntaxKind.ClassExpression:
31227                case SyntaxKind.StructDeclaration:
31228                    // For a class decorator, the `target` is the type of the class (e.g. the
31229                    // "static" or "constructor" side of the class).
31230                    return [
31231                        createSyntheticExpression(expr, getTypeOfSymbol(getSymbolOfNode(parent)))
31232                    ];
31233                case SyntaxKind.Parameter:
31234                    // A parameter declaration decorator will have three arguments (see
31235                    // `ParameterDecorator` in core.d.ts).
31236                    const func = parent.parent as FunctionLikeDeclaration;
31237                    return [
31238                        createSyntheticExpression(expr, parent.parent.kind === SyntaxKind.Constructor ? getTypeOfSymbol(getSymbolOfNode(func)) : errorType),
31239                        createSyntheticExpression(expr, anyType),
31240                        createSyntheticExpression(expr, numberType)
31241                    ];
31242                case SyntaxKind.PropertyDeclaration:
31243                case SyntaxKind.MethodDeclaration:
31244                case SyntaxKind.GetAccessor:
31245                case SyntaxKind.SetAccessor:
31246                    // A method or accessor declaration decorator will have two or three arguments (see
31247                    // `PropertyDecorator` and `MethodDecorator` in core.d.ts). If we are emitting decorators
31248                    // for ES3, we will only pass two arguments.
31249                    const hasPropDesc = languageVersion !== ScriptTarget.ES3 && (!isPropertyDeclaration(parent) || hasAccessorModifier(parent));
31250                    return [
31251                        createSyntheticExpression(expr, getParentTypeOfClassElement(parent as ClassElement)),
31252                        createSyntheticExpression(expr, getClassElementPropertyKeyType(parent as ClassElement)),
31253                        createSyntheticExpression(expr, hasPropDesc ? createTypedPropertyDescriptorType(getTypeOfNode(parent)) : anyType)
31254                    ];
31255                case SyntaxKind.FunctionDeclaration:
31256                    if (isEtsFunctionDecorators(getNameOfDecorator(node), compilerOptions)) {
31257                        const symbol = getSymbolOfNode(expr);
31258                        return symbol
31259                            ? [
31260                                createSyntheticExpression(expr, getTypeOfSymbol(symbol))
31261                            ]
31262                            : [];
31263                    }
31264                    return Debug.fail();
31265            }
31266            return Debug.fail();
31267        }
31268
31269        /**
31270         * Returns the argument count for a decorator node that works like a function invocation.
31271         */
31272        function getDecoratorArgumentCount(node: Decorator, signature: Signature) {
31273            switch (node.parent.kind) {
31274                case SyntaxKind.ClassDeclaration:
31275                case SyntaxKind.ClassExpression:
31276                case SyntaxKind.StructDeclaration:
31277                    return 1;
31278                case SyntaxKind.PropertyDeclaration:
31279                    return hasAccessorModifier(node.parent) ? 3 : 2;
31280                case SyntaxKind.MethodDeclaration:
31281                case SyntaxKind.GetAccessor:
31282                case SyntaxKind.SetAccessor:
31283                    // For ES3 or decorators with only two parameters we supply only two arguments
31284                    return languageVersion === ScriptTarget.ES3 || signature.parameters.length <= 2 ? 2 : 3;
31285                case SyntaxKind.Parameter:
31286                    return 3;
31287                case SyntaxKind.FunctionDeclaration:
31288                    if (isEtsFunctionDecorators(getNameOfDecorator(node), compilerOptions)) {
31289                        return isCallExpression(node.expression) ? 1 : 0;
31290                    }
31291                    return Debug.fail();
31292                default:
31293                    return Debug.fail();
31294            }
31295        }
31296        function getDiagnosticSpanForCallNode(node: CallExpression, doNotIncludeArguments?: boolean) {
31297            let start: number;
31298            let length: number;
31299            const sourceFile = getSourceFileOfNode(node);
31300
31301            if (isPropertyAccessExpression(node.expression)) {
31302                const nameSpan = getErrorSpanForNode(sourceFile, node.expression.name);
31303                start = nameSpan.start;
31304                length = doNotIncludeArguments ? nameSpan.length : node.end - start;
31305            }
31306            else {
31307                const expressionSpan = getErrorSpanForNode(sourceFile, node.expression);
31308                start = expressionSpan.start;
31309                length = doNotIncludeArguments ? expressionSpan.length : node.end - start;
31310            }
31311            return { start, length, sourceFile };
31312        }
31313        function getDiagnosticForCallNode(node: CallLikeExpression, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): DiagnosticWithLocation {
31314            if (isCallExpression(node)) {
31315                const { sourceFile, start, length } = getDiagnosticSpanForCallNode(node);
31316                return createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2, arg3);
31317            }
31318            else {
31319                return createDiagnosticForNode(node, message, arg0, arg1, arg2, arg3);
31320            }
31321        }
31322
31323        function isPromiseResolveArityError(node: CallLikeExpression) {
31324            if (!isCallExpression(node) || !isIdentifier(node.expression)) return false;
31325
31326            const symbol = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, undefined, undefined, false);
31327            const decl = symbol?.valueDeclaration;
31328            if (!decl || !isParameter(decl) || !isFunctionExpressionOrArrowFunction(decl.parent) || !isNewExpression(decl.parent.parent) || !isIdentifier(decl.parent.parent.expression)) {
31329                return false;
31330            }
31331
31332            const globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false);
31333            if (!globalPromiseSymbol) return false;
31334
31335            const constructorSymbol = getSymbolAtLocation(decl.parent.parent.expression, /*ignoreErrors*/ true);
31336            return constructorSymbol === globalPromiseSymbol;
31337        }
31338
31339        function getArgumentArityError(node: CallLikeExpression, signatures: readonly Signature[], args: readonly Expression[]) {
31340            const spreadIndex = getSpreadArgumentIndex(args);
31341            if (spreadIndex > -1) {
31342                return createDiagnosticForNode(args[spreadIndex], Diagnostics.A_spread_argument_must_either_have_a_tuple_type_or_be_passed_to_a_rest_parameter);
31343            }
31344            let min = Number.POSITIVE_INFINITY; // smallest parameter count
31345            let max = Number.NEGATIVE_INFINITY; // largest parameter count
31346            let maxBelow = Number.NEGATIVE_INFINITY; // largest parameter count that is smaller than the number of arguments
31347            let minAbove = Number.POSITIVE_INFINITY; // smallest parameter count that is larger than the number of arguments
31348
31349            let closestSignature: Signature | undefined;
31350            for (const sig of signatures) {
31351                const minParameter = getMinArgumentCount(sig);
31352                const maxParameter = getParameterCount(sig);
31353                // smallest/largest parameter counts
31354                if (minParameter < min) {
31355                    min = minParameter;
31356                    closestSignature = sig;
31357                }
31358                max = Math.max(max, maxParameter);
31359                // shortest parameter count *longer than the call*/longest parameter count *shorter than the call*
31360                if (minParameter < args.length && minParameter > maxBelow) maxBelow = minParameter;
31361                if (args.length < maxParameter && maxParameter < minAbove) minAbove = maxParameter;
31362            }
31363            const hasRestParameter = some(signatures, hasEffectiveRestParameter);
31364            const parameterRange = hasRestParameter ? min
31365                : min < max ? min + "-" + max
31366                : min;
31367            const isVoidPromiseError = !hasRestParameter && parameterRange === 1 && args.length === 0 && isPromiseResolveArityError(node);
31368            if (isVoidPromiseError && isInJSFile(node)) {
31369                return getDiagnosticForCallNode(node, Diagnostics.Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments);
31370            }
31371            const error = hasRestParameter
31372                ? Diagnostics.Expected_at_least_0_arguments_but_got_1
31373                : isVoidPromiseError
31374                    ? Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise
31375                    : Diagnostics.Expected_0_arguments_but_got_1;
31376            if (min < args.length && args.length < max) {
31377                // between min and max, but with no matching overload
31378                return getDiagnosticForCallNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, args.length, maxBelow, minAbove);
31379            }
31380            else if (args.length < min) {
31381                // too short: put the error span on the call expression, not any of the args
31382                const diagnostic = getDiagnosticForCallNode(node, error, parameterRange, args.length);
31383                const parameter = closestSignature?.declaration?.parameters[closestSignature.thisParameter ? args.length + 1 : args.length];
31384                if (parameter) {
31385                    const parameterError = createDiagnosticForNode(
31386                        parameter,
31387                        isBindingPattern(parameter.name) ? Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided
31388                            : isRestParameter(parameter) ? Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided
31389                            : Diagnostics.An_argument_for_0_was_not_provided,
31390                        !parameter.name ? args.length : !isBindingPattern(parameter.name) ? idText(getFirstIdentifier(parameter.name)) : undefined
31391                    );
31392                    return addRelatedInfo(diagnostic, parameterError);
31393                }
31394                return diagnostic;
31395            }
31396            else {
31397                // too long; error goes on the excess parameters
31398                const errorSpan = factory.createNodeArray(args.slice(max));
31399                const pos = first(errorSpan).pos;
31400                let end = last(errorSpan).end;
31401                if (end === pos) {
31402                    end++;
31403                }
31404                setTextRangePosEnd(errorSpan, pos, end);
31405                return createDiagnosticForNodeArray(getSourceFileOfNode(node), errorSpan, error, parameterRange, args.length);
31406            }
31407        }
31408
31409        function getTypeArgumentArityError(node: Node, signatures: readonly Signature[], typeArguments: NodeArray<TypeNode>) {
31410            const argCount = typeArguments.length;
31411            // No overloads exist
31412            if (signatures.length === 1) {
31413                const sig = signatures[0];
31414                const min = getMinTypeArgumentCount(sig.typeParameters);
31415                const max = length(sig.typeParameters);
31416                return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, min < max ? min + "-" + max : min , argCount);
31417            }
31418            // Overloads exist
31419            let belowArgCount = -Infinity;
31420            let aboveArgCount = Infinity;
31421            for (const sig of signatures) {
31422                const min = getMinTypeArgumentCount(sig.typeParameters);
31423                const max = length(sig.typeParameters);
31424                if (min > argCount) {
31425                    aboveArgCount = Math.min(aboveArgCount, min);
31426                }
31427                else if (max < argCount) {
31428                    belowArgCount = Math.max(belowArgCount, max);
31429                }
31430            }
31431            if (belowArgCount !== -Infinity && aboveArgCount !== Infinity) {
31432                return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, argCount, belowArgCount, aboveArgCount);
31433            }
31434            return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount);
31435        }
31436
31437        function resolveCall(node: CallLikeExpression, signatures: readonly Signature[], candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, callChainFlags: SignatureFlags, fallbackError?: DiagnosticMessage): Signature {
31438            const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
31439            const isDecorator = node.kind === SyntaxKind.Decorator;
31440            const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node);
31441            const isEtsComponentExpression = node.kind === SyntaxKind.EtsComponentExpression;
31442            const reportErrors = !candidatesOutArray;
31443
31444            let typeArguments: NodeArray<TypeNode> | undefined;
31445            let virtual: boolean | undefined;
31446
31447            if (!isDecorator && !isSuperCall(node)) {
31448                typeArguments = (node as CallExpression).typeArguments;
31449                virtual = typeArguments?.some(typeArgument => typeArgument.virtual);
31450
31451                // We already perform checking on the type arguments on the class declaration itself.
31452                if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (node as CallExpression).expression.kind !== SyntaxKind.SuperKeyword) {
31453                    forEach(typeArguments, checkSourceElement);
31454                }
31455
31456                if (isEtsComponentExpression && checkMode !== CheckMode.SkipEtsComponentBody) {
31457                    checkSourceElement((<EtsComponentExpression>node).body);
31458                }
31459            }
31460
31461            const candidates = candidatesOutArray || [];
31462            // reorderCandidates fills up the candidates array directly
31463            reorderCandidates(signatures, candidates, callChainFlags);
31464            if (!candidates.length) {
31465                if (reportErrors) {
31466                    diagnostics.add(getDiagnosticForCallNode(node, Diagnostics.Call_target_does_not_contain_any_signatures));
31467                }
31468                return resolveErrorCall(node);
31469            }
31470
31471            const args = getEffectiveCallArguments(node);
31472
31473            // The excludeArgument array contains true for each context sensitive argument (an argument
31474            // is context sensitive it is susceptible to a one-time permanent contextual typing).
31475            //
31476            // The idea is that we will perform type argument inference & assignability checking once
31477            // without using the susceptible parameters that are functions, and once more for those
31478            // parameters, contextually typing each as we go along.
31479            //
31480            // For a tagged template, then the first argument be 'undefined' if necessary because it
31481            // represents a TemplateStringsArray.
31482            //
31483            // For a decorator, no arguments are susceptible to contextual typing due to the fact
31484            // decorators are applied to a declaration by the emitter, and not to an expression.
31485            const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
31486            let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal;
31487            argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions;
31488
31489            // The following variables are captured and modified by calls to chooseOverload.
31490            // If overload resolution or type argument inference fails, we want to report the
31491            // best error possible. The best error is one which says that an argument was not
31492            // assignable to a parameter. This implies that everything else about the overload
31493            // was fine. So if there is any overload that is only incorrect because of an
31494            // argument, we will report an error on that one.
31495            //
31496            //     function foo(s: string): void;
31497            //     function foo(n: number): void; // Report argument error on this overload
31498            //     function foo(): void;
31499            //     foo(true);
31500            //
31501            // If none of the overloads even made it that far, there are two possibilities.
31502            // There was a problem with type arguments for some overload, in which case
31503            // report an error on that. Or none of the overloads even had correct arity,
31504            // in which case give an arity error.
31505            //
31506            //     function foo<T extends string>(x: T): void; // Report type argument error
31507            //     function foo(): void;
31508            //     foo<number>(0);
31509            //
31510            let candidatesForArgumentError: Signature[] | undefined;
31511            let candidateForArgumentArityError: Signature | undefined;
31512            let candidateForTypeArgumentError: Signature | undefined;
31513            let result: Signature | undefined;
31514
31515            // If we are in signature help, a trailing comma indicates that we intend to provide another argument,
31516            // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
31517            const signatureHelpTrailingComma =
31518                !!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma;
31519
31520            // Section 4.12.1:
31521            // if the candidate list contains one or more signatures for which the type of each argument
31522            // expression is a subtype of each corresponding parameter type, the return type of the first
31523            // of those signatures becomes the return type of the function call.
31524            // Otherwise, the return type of the first signature in the candidate list becomes the return
31525            // type of the function call.
31526            //
31527            // Whether the call is an error is determined by assignability of the arguments. The subtype pass
31528            // is just important for choosing the best signature. So in the case where there is only one
31529            // signature, the subtype pass is useless. So skipping it is an optimization.
31530            if (candidates.length > 1) {
31531                result = chooseOverload(candidates, subtypeRelation, isSingleNonGenericCandidate, signatureHelpTrailingComma);
31532            }
31533            if (!result) {
31534                result = chooseOverload(candidates, assignableRelation, isSingleNonGenericCandidate, signatureHelpTrailingComma);
31535            }
31536            if (result) {
31537                return result;
31538            }
31539
31540            result = getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray, checkMode);
31541            // Preemptively cache the result; getResolvedSignature will do this after we return, but
31542            // we need to ensure that the result is present for the error checks below so that if
31543            // this signature is encountered again, we handle the circularity (rather than producing a
31544            // different result which may produce no errors and assert). Callers of getResolvedSignature
31545            // don't hit this issue because they only observe this result after it's had a chance to
31546            // be cached, but the error reporting code below executes before getResolvedSignature sets
31547            // resolvedSignature.
31548            getNodeLinks(node).resolvedSignature = result;
31549
31550            // No signatures were applicable. Now report errors based on the last applicable signature with
31551            // no arguments excluded from assignability checks.
31552            // If candidate is undefined, it means that no candidates had a suitable arity. In that case,
31553            // skip the checkApplicableSignature check.
31554            if (reportErrors) {
31555                if (candidatesForArgumentError) {
31556                    if (candidatesForArgumentError.length === 1 || candidatesForArgumentError.length > 3) {
31557                        const last = candidatesForArgumentError[candidatesForArgumentError.length - 1];
31558                        let chain: DiagnosticMessageChain | undefined;
31559                        if (candidatesForArgumentError.length > 3) {
31560                            chain = chainDiagnosticMessages(chain, Diagnostics.The_last_overload_gave_the_following_error);
31561                            chain = chainDiagnosticMessages(chain, Diagnostics.No_overload_matches_this_call);
31562                        }
31563                        const diags = getSignatureApplicabilityError(node, args, last, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, () => chain);
31564                        if (diags) {
31565                            for (const d of diags) {
31566                                if (last.declaration && candidatesForArgumentError.length > 3) {
31567                                    addRelatedInfo(d, createDiagnosticForNode(last.declaration, Diagnostics.The_last_overload_is_declared_here));
31568                                }
31569                                addImplementationSuccessElaboration(last, d);
31570                                diagnostics.add(d);
31571                            }
31572                        }
31573                        else {
31574                            Debug.fail("No error for last overload signature");
31575                        }
31576                    }
31577                    else {
31578                        const allDiagnostics: (readonly DiagnosticRelatedInformation[])[] = [];
31579                        let max = 0;
31580                        let min = Number.MAX_VALUE;
31581                        let minIndex = 0;
31582                        let i = 0;
31583                        for (const c of candidatesForArgumentError) {
31584                            const chain = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, candidates.length, signatureToString(c));
31585                            const diags = getSignatureApplicabilityError(node, args, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain);
31586                            if (diags) {
31587                                if (diags.length <= min) {
31588                                    min = diags.length;
31589                                    minIndex = i;
31590                                }
31591                                max = Math.max(max, diags.length);
31592                                allDiagnostics.push(diags);
31593                            }
31594                            else {
31595                                Debug.fail("No error for 3 or fewer overload signatures");
31596                            }
31597                            i++;
31598                        }
31599
31600                        const diags = max > 1 ? allDiagnostics[minIndex] : flatten(allDiagnostics);
31601                        Debug.assert(diags.length > 0, "No errors reported for 3 or fewer overload signatures");
31602                        const chain = chainDiagnosticMessages(
31603                            map(diags, createDiagnosticMessageChainFromDiagnostic),
31604                            Diagnostics.No_overload_matches_this_call);
31605                        // The below is a spread to guarantee we get a new (mutable) array - our `flatMap` helper tries to do "smart" optimizations where it reuses input
31606                        // arrays and the emptyArray singleton where possible, which is decidedly not what we want while we're still constructing this diagnostic
31607                        const related = [...flatMap(diags, d => (d as Diagnostic).relatedInformation) as DiagnosticRelatedInformation[]];
31608                        let diag: Diagnostic;
31609                        if (every(diags, d => d.start === diags[0].start && d.length === diags[0].length && d.file === diags[0].file)) {
31610                            const { file, start, length } = diags[0];
31611                            diag = { file, start, length, code: chain.code, category: chain.category, messageText: chain, relatedInformation: related };
31612                        }
31613                        else {
31614                            diag = createDiagnosticForNodeFromMessageChain(node, chain, related);
31615                        }
31616                        addImplementationSuccessElaboration(candidatesForArgumentError[0], diag);
31617                        diagnostics.add(diag);
31618                    }
31619                }
31620                else if (candidateForArgumentArityError) {
31621                    diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args));
31622                }
31623                else if (candidateForTypeArgumentError) {
31624                    checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression | JsxOpeningLikeElement).typeArguments!, /*reportErrors*/ true, fallbackError);
31625                }
31626                else {
31627                    const signaturesWithCorrectTypeArgumentArity = filter(signatures, s => hasCorrectTypeArgumentArity(s, typeArguments, virtual));
31628                    if (signaturesWithCorrectTypeArgumentArity.length === 0) {
31629                        diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments!));
31630                    }
31631                    else if (!isDecorator) {
31632                        diagnostics.add(getArgumentArityError(node, signaturesWithCorrectTypeArgumentArity, args));
31633                    }
31634                    else if (fallbackError) {
31635                        diagnostics.add(getDiagnosticForCallNode(node, fallbackError));
31636                    }
31637                }
31638            }
31639
31640            return result;
31641
31642            function addImplementationSuccessElaboration(failed: Signature, diagnostic: Diagnostic) {
31643                const oldCandidatesForArgumentError = candidatesForArgumentError;
31644                const oldCandidateForArgumentArityError = candidateForArgumentArityError;
31645                const oldCandidateForTypeArgumentError = candidateForTypeArgumentError;
31646
31647                const failedSignatureDeclarations = failed.declaration?.symbol?.declarations || emptyArray;
31648                const isOverload = failedSignatureDeclarations.length > 1;
31649                const implDecl = isOverload ? find(failedSignatureDeclarations, d => isFunctionLikeDeclaration(d) && nodeIsPresent(d.body)) : undefined;
31650                if (implDecl) {
31651                    const candidate = getSignatureFromDeclaration(implDecl as FunctionLikeDeclaration);
31652                    const isSingleNonGenericCandidate = !candidate.typeParameters;
31653                    if (chooseOverload([candidate], assignableRelation, isSingleNonGenericCandidate)) {
31654                        addRelatedInfo(diagnostic, createDiagnosticForNode(implDecl, Diagnostics.The_call_would_have_succeeded_against_this_implementation_but_implementation_signatures_of_overloads_are_not_externally_visible));
31655                    }
31656                }
31657
31658                candidatesForArgumentError = oldCandidatesForArgumentError;
31659                candidateForArgumentArityError = oldCandidateForArgumentArityError;
31660                candidateForTypeArgumentError = oldCandidateForTypeArgumentError;
31661            }
31662
31663            function chooseOverload(candidates: Signature[], relation: ESMap<string, RelationComparisonResult>, isSingleNonGenericCandidate: boolean, signatureHelpTrailingComma = false) {
31664                candidatesForArgumentError = undefined;
31665                candidateForArgumentArityError = undefined;
31666                candidateForTypeArgumentError = undefined;
31667
31668                if (isSingleNonGenericCandidate) {
31669                    const candidate = candidates[0];
31670                    if ((some(typeArguments) && !virtual) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
31671                        return undefined;
31672                    }
31673                    if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
31674                        candidatesForArgumentError = [candidate];
31675                        return undefined;
31676                    }
31677                    return candidate;
31678                }
31679
31680                for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) {
31681                    const candidate = candidates[candidateIndex];
31682                    if (!hasCorrectTypeArgumentArity(candidate, typeArguments, virtual) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) {
31683                        continue;
31684                    }
31685
31686                    let checkCandidate: Signature;
31687                    let inferenceContext: InferenceContext | undefined;
31688
31689                    if (candidate.typeParameters) {
31690                        let typeArgumentTypes: Type[] | undefined;
31691                        if (some(typeArguments)) {
31692                            typeArgumentTypes = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
31693                            if (!typeArgumentTypes) {
31694                                candidateForTypeArgumentError = candidate;
31695                                continue;
31696                            }
31697                        }
31698                        else {
31699                            inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
31700                            typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext);
31701                            argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal;
31702                        }
31703                        checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters);
31704                        // If the original signature has a generic rest type, instantiation may produce a
31705                        // signature with different arity and we need to perform another arity check.
31706                        if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
31707                            candidateForArgumentArityError = checkCandidate;
31708                            continue;
31709                        }
31710                    }
31711                    else {
31712                        checkCandidate = candidate;
31713                    }
31714                    if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
31715                        // Give preference to error candidates that have no rest parameters (as they are more specific)
31716                        (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
31717                        continue;
31718                    }
31719                    if (argCheckMode) {
31720                        // If one or more context sensitive arguments were excluded, we start including
31721                        // them now (and keeping do so for any subsequent candidates) and perform a second
31722                        // round of type inference and applicability checking for this particular candidate.
31723                        argCheckMode = checkMode & CheckMode.IsForStringLiteralArgumentCompletions;
31724                        if (inferenceContext) {
31725                            const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext);
31726                            checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters);
31727                            // If the original signature has a generic rest type, instantiation may produce a
31728                            // signature with different arity and we need to perform another arity check.
31729                            if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
31730                                candidateForArgumentArityError = checkCandidate;
31731                                continue;
31732                            }
31733                        }
31734                        if (getSignatureApplicabilityError(node, args, checkCandidate, relation, argCheckMode, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) {
31735                            // Give preference to error candidates that have no rest parameters (as they are more specific)
31736                            (candidatesForArgumentError || (candidatesForArgumentError = [])).push(checkCandidate);
31737                            continue;
31738                        }
31739                    }
31740                    candidates[candidateIndex] = checkCandidate;
31741                    return checkCandidate;
31742                }
31743
31744                return undefined;
31745            }
31746        }
31747
31748        // No signature was applicable. We have already reported the errors for the invalid signature.
31749        function getCandidateForOverloadFailure(
31750            node: CallLikeExpression,
31751            candidates: Signature[],
31752            args: readonly Expression[],
31753            hasCandidatesOutArray: boolean,
31754            checkMode: CheckMode,
31755        ): Signature {
31756            Debug.assert(candidates.length > 0); // Else should not have called this.
31757            checkNodeDeferred(node);
31758            // Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
31759            // Don't do this if there is a `candidatesOutArray`,
31760            // because then we want the chosen best candidate to be one of the overloads, not a combination.
31761            return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
31762                ? pickLongestCandidateSignature(node, candidates, args, checkMode)
31763                : createUnionOfSignaturesForOverloadFailure(candidates);
31764        }
31765
31766        function createUnionOfSignaturesForOverloadFailure(candidates: readonly Signature[]): Signature {
31767            const thisParameters = mapDefined(candidates, c => c.thisParameter);
31768            let thisParameter: Symbol | undefined;
31769            if (thisParameters.length) {
31770                thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter));
31771            }
31772            const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
31773            const parameters: Symbol[] = [];
31774            for (let i = 0; i < maxNonRestParam; i++) {
31775                const symbols = mapDefined(candidates, s => signatureHasRestParameter(s) ?
31776                    i < s.parameters.length - 1 ? s.parameters[i] : last(s.parameters) :
31777                    i < s.parameters.length ? s.parameters[i] : undefined);
31778                Debug.assert(symbols.length !== 0);
31779                parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
31780            }
31781            const restParameterSymbols = mapDefined(candidates, c => signatureHasRestParameter(c) ? last(c.parameters) : undefined);
31782            let flags = SignatureFlags.None;
31783            if (restParameterSymbols.length !== 0) {
31784                const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
31785                parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
31786                flags |= SignatureFlags.HasRestParameter;
31787            }
31788            if (candidates.some(signatureHasLiteralTypes)) {
31789                flags |= SignatureFlags.HasLiteralTypes;
31790            }
31791            return createSignature(
31792                candidates[0].declaration,
31793                /*typeParameters*/ undefined, // Before calling this we tested for `!candidates.some(c => !!c.typeParameters)`.
31794                thisParameter,
31795                parameters,
31796                /*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
31797                /*typePredicate*/ undefined,
31798                minArgumentCount,
31799                flags);
31800        }
31801
31802        function getNumNonRestParameters(signature: Signature): number {
31803            const numParams = signature.parameters.length;
31804            return signatureHasRestParameter(signature) ? numParams - 1 : numParams;
31805        }
31806
31807        function createCombinedSymbolFromTypes(sources: readonly Symbol[], types: Type[]): Symbol {
31808            return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype));
31809        }
31810
31811        function createCombinedSymbolForOverloadFailure(sources: readonly Symbol[], type: Type): Symbol {
31812            // This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
31813            return createSymbolWithType(first(sources), type);
31814        }
31815
31816        function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[], checkMode: CheckMode): Signature {
31817            // Pick the longest signature. This way we can get a contextual type for cases like:
31818            //     declare function f(a: { xa: number; xb: number; }, b: number);
31819            //     f({ |
31820            // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
31821            //     declare function f<T>(k: keyof T);
31822            //     f<Foo>("
31823            const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
31824            const candidate = candidates[bestIndex];
31825            const { typeParameters } = candidate;
31826            if (!typeParameters) {
31827                return candidate;
31828            }
31829
31830            const typeArgumentNodes: readonly TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined;
31831            const instantiated = typeArgumentNodes
31832                ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node)))
31833                : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args, checkMode);
31834            candidates[bestIndex] = instantiated;
31835            return instantiated;
31836        }
31837
31838        function getTypeArgumentsFromNodes(typeArgumentNodes: readonly TypeNode[], typeParameters: readonly TypeParameter[], isJs: boolean): readonly Type[] {
31839            const typeArguments = typeArgumentNodes.map(getTypeOfNode);
31840            while (typeArguments.length > typeParameters.length) {
31841                typeArguments.pop();
31842            }
31843            while (typeArguments.length < typeParameters.length) {
31844                typeArguments.push(getDefaultFromTypeParameter(typeParameters[typeArguments.length]) || getConstraintOfTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isJs));
31845            }
31846            return typeArguments;
31847        }
31848
31849        function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[], checkMode: CheckMode): Signature {
31850            const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
31851            const typeArgumentTypes = inferTypeArguments(node, candidate, args, checkMode | CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext);
31852            return createSignatureInstantiation(candidate, typeArgumentTypes);
31853        }
31854
31855        function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
31856            let maxParamsIndex = -1;
31857            let maxParams = -1;
31858
31859            for (let i = 0; i < candidates.length; i++) {
31860                const candidate = candidates[i];
31861                const paramCount = getParameterCount(candidate);
31862                if (hasEffectiveRestParameter(candidate) || paramCount >= argsCount) {
31863                    return i;
31864                }
31865                if (paramCount > maxParams) {
31866                    maxParams = paramCount;
31867                    maxParamsIndex = i;
31868                }
31869            }
31870
31871            return maxParamsIndex;
31872        }
31873
31874        function resolveCallExpression(node: CallExpression | EtsComponentExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
31875            if (node.expression.kind === SyntaxKind.SuperKeyword) {
31876                const superType = checkSuperExpression(node.expression);
31877                if (isTypeAny(superType)) {
31878                    for (const arg of node.arguments) {
31879                        checkExpression(arg); // Still visit arguments so they get marked for visibility, etc
31880                    }
31881                    return anySignature;
31882                }
31883                if (!isErrorType(superType)) {
31884                    // In super call, the candidate signatures are the matching arity signatures of the base constructor function instantiated
31885                    // with the type arguments specified in the extends clause.
31886                    const baseTypeNode = getEffectiveBaseTypeNode(getContainingClass(node)!);
31887                    if (baseTypeNode) {
31888                        const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode);
31889                        return resolveCall(node, baseConstructors, candidatesOutArray, checkMode, SignatureFlags.None);
31890                    }
31891                }
31892                return resolveUntypedCall(node);
31893            }
31894
31895            let callChainFlags: SignatureFlags;
31896            let checkExpressionCheckMode: CheckMode | undefined = checkMode;
31897            if (checkMode !== CheckMode.SkipEtsComponentBody) {
31898                checkExpressionCheckMode = undefined;
31899            }
31900            let funcType = checkExpression(node.expression, checkExpressionCheckMode);
31901            if (isCallChain(node)) {
31902                const nonOptionalType = getOptionalExpressionType(funcType, node.expression);
31903                callChainFlags = nonOptionalType === funcType ? SignatureFlags.None :
31904                    isOutermostOptionalChain(node) ? SignatureFlags.IsOuterCallChain :
31905                    SignatureFlags.IsInnerCallChain;
31906                funcType = nonOptionalType;
31907            }
31908            else {
31909                callChainFlags = SignatureFlags.None;
31910            }
31911
31912            funcType = checkNonNullTypeWithReporter(
31913                funcType,
31914                node.expression,
31915                reportCannotInvokePossiblyNullOrUndefinedError
31916            );
31917
31918            if (funcType === silentNeverType) {
31919                return silentNeverSignature;
31920            }
31921
31922            const apparentType = getApparentType(funcType);
31923            if (isErrorType(apparentType)) {
31924                // Another error has already been reported
31925                return resolveErrorCall(node);
31926            }
31927
31928            // Technically, this signatures list may be incomplete. We are taking the apparent type,
31929            // but we are not including call signatures that may have been added to the Object or
31930            // Function interface, since they have none by default. This is a bit of a leap of faith
31931            // that the user will not add any.
31932            const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
31933            const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
31934            const numConstructSignatures = constructSignatures.length;
31935
31936            // TS 1.0 Spec: 4.12
31937            // In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
31938            // types are provided for the argument expressions, and the result is always of type Any.
31939            if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, numConstructSignatures)) {
31940                // The unknownType indicates that an error already occurred (and was reported).  No
31941                // need to report another error in this case.
31942                if (!isErrorType(funcType) && node.typeArguments) {
31943                    error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
31944                }
31945                return resolveUntypedCall(node);
31946            }
31947            // If FuncExpr's apparent type(section 3.8.1) is a function type, the call is a typed function call.
31948            // TypeScript employs overload resolution in typed function calls in order to support functions
31949            // with multiple call signatures.
31950            const isStructDeclaration = isCalledStructDeclaration(apparentType.symbol?.declarations);
31951            if (!callSignatures.length) {
31952                if (numConstructSignatures) {
31953                    if (!isStructDeclaration) {
31954                        error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
31955                    }
31956                    else {
31957                        return resolveCall(node, constructSignatures, candidatesOutArray, checkMode, SignatureFlags.None);
31958                    }
31959                }
31960                else {
31961                    let relatedInformation: DiagnosticRelatedInformation | undefined;
31962                    if (node.arguments.length === 1) {
31963                        const text = getSourceFileOfNode(node).text;
31964                        if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) {
31965                            relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.Are_you_missing_a_semicolon);
31966                        }
31967                    }
31968                    invocationError(node.expression, apparentType, SignatureKind.Call, relatedInformation);
31969                }
31970                return resolveErrorCall(node);
31971            }
31972            // When a call to a generic function is an argument to an outer call to a generic function for which
31973            // inference is in process, we have a choice to make. If the inner call relies on inferences made from
31974            // its contextual type to its return type, deferring the inner call processing allows the best possible
31975            // contextual type to accumulate. But if the outer call relies on inferences made from the return type of
31976            // the inner call, the inner call should be processed early. There's no sure way to know which choice is
31977            // right (only a full unification algorithm can determine that), so we resort to the following heuristic:
31978            // If no type arguments are specified in the inner call and at least one call signature is generic and
31979            // returns a function type, we choose to defer processing. This narrowly permits function composition
31980            // operators to flow inferences through return types, but otherwise processes calls right away. We
31981            // use the resolvingSignature singleton to indicate that we deferred processing. This result will be
31982            // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and
31983            // from which we never make inferences).
31984            if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) {
31985                skippedGenericFunction(node, checkMode);
31986                return resolvingSignature;
31987            }
31988            // If the function is explicitly marked with `@class`, then it must be constructed.
31989            if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) {
31990                error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
31991                return resolveErrorCall(node);
31992            }
31993
31994            return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags);
31995        }
31996
31997        function isGenericFunctionReturningFunction(signature: Signature) {
31998            return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature)));
31999        }
32000
32001        /**
32002         * TS 1.0 spec: 4.12
32003         * If FuncExpr is of type Any, or of an object type that has no call or construct signatures
32004         * but is a subtype of the Function interface, the call is an untyped function call.
32005         */
32006        function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number): boolean {
32007            // We exclude union types because we may have a union of function types that happen to have no common signatures.
32008            return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & TypeFlags.TypeParameter) ||
32009                !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & TypeFlags.Union) && !(getReducedType(apparentFuncType).flags & TypeFlags.Never) && isTypeAssignableTo(funcType, globalFunctionType);
32010        }
32011
32012        function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
32013            if (node.arguments && languageVersion < ScriptTarget.ES5) {
32014                const spreadIndex = getSpreadArgumentIndex(node.arguments);
32015                if (spreadIndex >= 0) {
32016                    error(node.arguments[spreadIndex], Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher);
32017                }
32018            }
32019
32020            let expressionType = checkNonNullExpression(node.expression, checkMode);
32021            if (expressionType === silentNeverType) {
32022                return silentNeverSignature;
32023            }
32024
32025            // If expressionType's apparent type(section 3.8.1) is an object type with one or
32026            // more construct signatures, the expression is processed in the same manner as a
32027            // function call, but using the construct signatures as the initial set of candidate
32028            // signatures for overload resolution. The result type of the function call becomes
32029            // the result type of the operation.
32030            expressionType = getApparentType(expressionType);
32031            if (isErrorType(expressionType)) {
32032                // Another error has already been reported
32033                return resolveErrorCall(node);
32034            }
32035
32036            // TS 1.0 spec: 4.11
32037            // If expressionType is of type Any, Args can be any argument
32038            // list and the result of the operation is of type Any.
32039            if (isTypeAny(expressionType)) {
32040                if (node.typeArguments) {
32041                    error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
32042                }
32043                return resolveUntypedCall(node);
32044            }
32045
32046            // Technically, this signatures list may be incomplete. We are taking the apparent type,
32047            // but we are not including construct signatures that may have been added to the Object or
32048            // Function interface, since they have none by default. This is a bit of a leap of faith
32049            // that the user will not add any.
32050            const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
32051            if (constructSignatures.length) {
32052                if (!isConstructorAccessible(node, constructSignatures[0])) {
32053                    return resolveErrorCall(node);
32054                }
32055                // If the expression is a class of abstract type, or an abstract construct signature,
32056                // then it cannot be instantiated.
32057                // In the case of a merged class-module or class-interface declaration,
32058                // only the class declaration node will have the Abstract flag set.
32059                if (someSignature(constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract))) {
32060                    error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class);
32061                    return resolveErrorCall(node);
32062                }
32063                const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol);
32064                if (valueDecl && hasSyntacticModifier(valueDecl, ModifierFlags.Abstract)) {
32065                    error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class);
32066                    return resolveErrorCall(node);
32067                }
32068
32069                return resolveCall(node, constructSignatures, candidatesOutArray, checkMode, SignatureFlags.None);
32070            }
32071
32072            // If expressionType's apparent type is an object type with no construct signatures but
32073            // one or more call signatures, the expression is processed as a function call. A compile-time
32074            // error occurs if the result of the function call is not Void. The type of the result of the
32075            // operation is Any. It is an error to have a Void this type.
32076            const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
32077            if (callSignatures.length) {
32078                const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None);
32079                if (!noImplicitAny) {
32080                    if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
32081                        error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
32082                    }
32083                    if (getThisTypeOfSignature(signature) === voidType) {
32084                        error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void);
32085                    }
32086                }
32087                return signature;
32088            }
32089
32090            invocationError(node.expression, expressionType, SignatureKind.Construct);
32091            return resolveErrorCall(node);
32092        }
32093
32094        function someSignature(signatures: Signature | readonly Signature[], f: (s: Signature) => boolean): boolean {
32095            if (isArray(signatures)) {
32096                return some(signatures, signature => someSignature(signature, f));
32097            }
32098            return signatures.compositeKind === TypeFlags.Union ? some(signatures.compositeSignatures, f) : f(signatures);
32099        }
32100
32101        function typeHasProtectedAccessibleBase(target: Symbol, type: InterfaceType): boolean {
32102            const baseTypes = getBaseTypes(type);
32103            if (!length(baseTypes)) {
32104                return false;
32105            }
32106            const firstBase = baseTypes[0];
32107            if (firstBase.flags & TypeFlags.Intersection) {
32108                const types = (firstBase as IntersectionType).types;
32109                const mixinFlags = findMixins(types);
32110                let i = 0;
32111                for (const intersectionMember of (firstBase as IntersectionType).types) {
32112                    // We want to ignore mixin ctors
32113                    if (!mixinFlags[i]) {
32114                        if (getObjectFlags(intersectionMember) & (ObjectFlags.Class | ObjectFlags.Interface)) {
32115                            if (intersectionMember.symbol === target) {
32116                                return true;
32117                            }
32118                            if (typeHasProtectedAccessibleBase(target, intersectionMember as InterfaceType)) {
32119                                return true;
32120                            }
32121                        }
32122                    }
32123                    i++;
32124                }
32125                return false;
32126            }
32127            if (firstBase.symbol === target) {
32128                return true;
32129            }
32130            return typeHasProtectedAccessibleBase(target, firstBase as InterfaceType);
32131        }
32132
32133        function isConstructorAccessible(node: NewExpression, signature: Signature) {
32134            if (!signature || !signature.declaration) {
32135                return true;
32136            }
32137
32138            const declaration = signature.declaration;
32139            const modifiers = getSelectedEffectiveModifierFlags(declaration, ModifierFlags.NonPublicAccessibilityModifier);
32140
32141            // (1) Public constructors and (2) constructor functions are always accessible.
32142            if (!modifiers || declaration.kind !== SyntaxKind.Constructor) {
32143                return true;
32144            }
32145
32146            const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol)!;
32147            const declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol) as InterfaceType;
32148
32149            // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected)
32150            if (!isNodeWithinClass(node, declaringClassDeclaration)) {
32151                const containingClass = getContainingClass(node);
32152                if (containingClass && modifiers & ModifierFlags.Protected) {
32153                    const containingType = getTypeOfNode(containingClass);
32154                    if (typeHasProtectedAccessibleBase(declaration.parent.symbol, containingType as InterfaceType)) {
32155                        return true;
32156                    }
32157                }
32158                if (modifiers & ModifierFlags.Private) {
32159                    error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass));
32160                }
32161                if (modifiers & ModifierFlags.Protected) {
32162                    error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass));
32163                }
32164                return false;
32165            }
32166
32167            return true;
32168        }
32169
32170        function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain, relatedMessage: DiagnosticMessage | undefined } {
32171            let errorInfo: DiagnosticMessageChain | undefined;
32172            const isCall = kind === SignatureKind.Call;
32173            const awaitedType = getAwaitedType(apparentType);
32174            const maybeMissingAwait = awaitedType && getSignaturesOfType(awaitedType, kind).length > 0;
32175            if (apparentType.flags & TypeFlags.Union) {
32176                const types = (apparentType as UnionType).types;
32177                let hasSignatures = false;
32178                for (const constituent of types) {
32179                    const signatures = getSignaturesOfType(constituent, kind);
32180                    if (signatures.length !== 0) {
32181                        hasSignatures = true;
32182                        if (errorInfo) {
32183                            // Bail early if we already have an error, no chance of "No constituent of type is callable"
32184                            break;
32185                        }
32186                    }
32187                    else {
32188                        // Error on the first non callable constituent only
32189                        if (!errorInfo) {
32190                            errorInfo = chainDiagnosticMessages(
32191                                errorInfo,
32192                                isCall ?
32193                                    Diagnostics.Type_0_has_no_call_signatures :
32194                                    Diagnostics.Type_0_has_no_construct_signatures,
32195                                typeToString(constituent)
32196                            );
32197                            errorInfo = chainDiagnosticMessages(
32198                                errorInfo,
32199                                isCall ?
32200                                    Diagnostics.Not_all_constituents_of_type_0_are_callable :
32201                                    Diagnostics.Not_all_constituents_of_type_0_are_constructable,
32202                                typeToString(apparentType)
32203                            );
32204                        }
32205                        if (hasSignatures) {
32206                            // Bail early if we already found a siganture, no chance of "No constituent of type is callable"
32207                            break;
32208                        }
32209                    }
32210                }
32211                if (!hasSignatures) {
32212                    errorInfo = chainDiagnosticMessages(
32213                        /* detials */ undefined,
32214                        isCall ?
32215                            Diagnostics.No_constituent_of_type_0_is_callable :
32216                            Diagnostics.No_constituent_of_type_0_is_constructable,
32217                        typeToString(apparentType)
32218                    );
32219                }
32220                if (!errorInfo) {
32221                    errorInfo = chainDiagnosticMessages(
32222                        errorInfo,
32223                        isCall ?
32224                            Diagnostics.Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other :
32225                            Diagnostics.Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other,
32226                        typeToString(apparentType)
32227                    );
32228                }
32229            }
32230            else {
32231                errorInfo = chainDiagnosticMessages(
32232                    errorInfo,
32233                    isCall ?
32234                        Diagnostics.Type_0_has_no_call_signatures :
32235                        Diagnostics.Type_0_has_no_construct_signatures,
32236                    typeToString(apparentType)
32237                );
32238            }
32239
32240            let headMessage = isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable;
32241
32242            // Diagnose get accessors incorrectly called as functions
32243            if (isCallExpression(errorTarget.parent) && errorTarget.parent.arguments.length === 0) {
32244                const { resolvedSymbol } = getNodeLinks(errorTarget);
32245                if (resolvedSymbol && resolvedSymbol.flags & SymbolFlags.GetAccessor) {
32246                    headMessage = Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without;
32247                }
32248            }
32249
32250            return {
32251                messageChain: chainDiagnosticMessages(errorInfo, headMessage),
32252                relatedMessage: maybeMissingAwait ? Diagnostics.Did_you_forget_to_use_await : undefined,
32253            };
32254        }
32255        function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
32256            const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(errorTarget, apparentType, kind);
32257            const diagnostic = createDiagnosticForNodeFromMessageChain(errorTarget, messageChain);
32258            if (relatedInfo) {
32259                addRelatedInfo(diagnostic, createDiagnosticForNode(errorTarget, relatedInfo));
32260            }
32261            if (isCallExpression(errorTarget.parent)) {
32262                const { start, length } = getDiagnosticSpanForCallNode(errorTarget.parent, /* doNotIncludeArguments */ true);
32263                diagnostic.start = start;
32264                diagnostic.length = length;
32265            }
32266            diagnostics.add(diagnostic);
32267            invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic);
32268        }
32269
32270        function invocationErrorRecovery(apparentType: Type, kind: SignatureKind, diagnostic: Diagnostic) {
32271            if (!apparentType.symbol) {
32272                return;
32273            }
32274            const importNode = getSymbolLinks(apparentType.symbol).originatingImport;
32275            // Create a diagnostic on the originating import if possible onto which we can attach a quickfix
32276            //  An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site
32277            if (importNode && !isImportCall(importNode)) {
32278                const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target!), kind);
32279                if (!sigs || !sigs.length) return;
32280
32281                addRelatedInfo(diagnostic,
32282                    createDiagnosticForNode(importNode, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)
32283                );
32284            }
32285        }
32286
32287        function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
32288            const tagType = checkExpression(node.tag);
32289            const apparentType = getApparentType(tagType);
32290
32291            if (isErrorType(apparentType)) {
32292                // Another error has already been reported
32293                return resolveErrorCall(node);
32294            }
32295
32296            const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
32297            const numConstructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct).length;
32298
32299            if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, numConstructSignatures)) {
32300                return resolveUntypedCall(node);
32301            }
32302
32303            if (!callSignatures.length) {
32304                if (isArrayLiteralExpression(node.parent)) {
32305                    const diagnostic = createDiagnosticForNode(node.tag, Diagnostics.It_is_likely_that_you_are_missing_a_comma_to_separate_these_two_template_expressions_They_form_a_tagged_template_expression_which_cannot_be_invoked);
32306                    diagnostics.add(diagnostic);
32307                    return resolveErrorCall(node);
32308                }
32309
32310                invocationError(node.tag, apparentType, SignatureKind.Call);
32311                return resolveErrorCall(node);
32312            }
32313
32314            return resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None);
32315        }
32316
32317        /**
32318         * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression.
32319         */
32320        function getDiagnosticHeadMessageForDecoratorResolution(node: Decorator) {
32321            switch (node.parent.kind) {
32322                case SyntaxKind.ClassDeclaration:
32323                case SyntaxKind.ClassExpression:
32324                case SyntaxKind.StructDeclaration:
32325                    return Diagnostics.Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression;
32326
32327                case SyntaxKind.Parameter:
32328                    return Diagnostics.Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression;
32329
32330                case SyntaxKind.PropertyDeclaration:
32331                    return Diagnostics.Unable_to_resolve_signature_of_property_decorator_when_called_as_an_expression;
32332
32333                case SyntaxKind.MethodDeclaration:
32334                case SyntaxKind.GetAccessor:
32335                case SyntaxKind.SetAccessor:
32336                    return Diagnostics.Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression;
32337
32338                case SyntaxKind.FunctionDeclaration:
32339                    const decoratorName = getNameOfDecorator(node);
32340                    if (isEtsFunctionDecorators(decoratorName, compilerOptions)) {
32341                        return Diagnostics.Unable_to_resolve_signature_of_function_decorator_when_decorators_are_not_valid;
32342                    }
32343                    return Debug.fail();
32344
32345                default:
32346                    return Debug.fail();
32347            }
32348        }
32349
32350        function annotationHasDefaultValue(node: Annotation): boolean {
32351            const members = node.annotationDeclaration!.members;
32352            return every(members, (elem) => (elem as AnnotationPropertyDeclaration).initializer !== undefined);
32353        }
32354
32355        /**
32356         * Resolves an annotation as if it were a call expression.
32357         */
32358        function resolveAnnotation(node: Annotation): Signature {
32359            // @Anno
32360            // class C {}
32361            //
32362            // or
32363            //
32364            // @t.Anno
32365            // class C {}
32366            if (isIdentifier(node.expression) || isPropertyAccessExpression(node.expression)) {
32367                const identType = checkExpression(node.expression);
32368                Debug.assert(identType.symbol.flags & SymbolFlags.Annotation);
32369
32370                if (!annotationHasDefaultValue(node)) {
32371                    const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false);
32372                    error(node, Diagnostics.When_annotation_0_is_applied_all_fields_without_default_values_must_be_provided, nodeStr);
32373                    return resolveErrorCall(node);
32374                }
32375                return annotationDefaultSignature;
32376            }
32377
32378            Debug.assert(isCallExpression(node.expression));
32379            // let d = {}
32380            // @Anno(d)
32381            // class C {}
32382            if (!node.expression.arguments ||
32383                node.expression.arguments.length !== 1 ||
32384                !isObjectLiteralExpression(node.expression.arguments[0])) {
32385                const nodeStr = getTextOfNode(node.expression.arguments[0] || node.expression, /*includeTrivia*/ false);
32386                error(node, Diagnostics.Only_an_object_literal_have_to_be_provided_as_annotation_parameters_list_got_Colon_0, nodeStr);
32387                return resolveErrorCall(node);
32388            }
32389
32390            // let bar = goo()
32391            // @Anno({foo: bar})
32392            // class C {}
32393            const arg = node.expression.arguments[0];
32394            const evaluatedProps = new Map<__String, AnnotationConstantExpressionType>();
32395            for (const prop of arg.properties) {
32396                if (!isPropertyAssignment(prop)) {
32397                    const nodeStr = getTextOfNode(arg, /*includeTrivia*/ false);
32398                    error(node, Diagnostics.Only_an_object_literal_have_to_be_provided_as_annotation_parameters_list_got_Colon_0, nodeStr);
32399                    return resolveErrorCall(node);
32400                }
32401                const evaluated = evaluateAnnotationPropertyConstantExpression(prop.initializer);
32402                if (evaluated === undefined) {
32403                    const nodeStr = getTextOfNode(prop.initializer, /*includeTrivia*/ false);
32404                    error(node, Diagnostics.All_members_of_object_literal_which_is_provided_as_annotation_parameters_list_have_to_be_constant_expressions_got_Colon_0, nodeStr);
32405                    return resolveErrorCall(node);
32406                }
32407                evaluatedProps.set(tryGetTextOfPropertyName(prop.name)!, evaluated);
32408            }
32409
32410            // @Anno()
32411            // class C {}
32412            //
32413            // or
32414            //
32415            // @Anno({...})
32416            // class C {}
32417            const funcType = checkExpression(node.expression);
32418            const apparentType = getApparentType(funcType);
32419            if (isErrorType(apparentType)) {
32420                return resolveErrorCall(node);
32421            }
32422
32423            const members = node.annotationDeclaration!.members;
32424            for (const m of members) {
32425                const memberName = tryGetTextOfPropertyName(m.name)!;
32426                if (evaluatedProps.has(memberName)) {
32427                    const propValue = annotationEvaluatedValueToExpr(evaluatedProps.get(memberName)!, getTypeOfNode(m))!;
32428                    if (getNodeLinks(node).annotationObjectLiteralEvaluatedProps === undefined) {
32429                        getNodeLinks(node).annotationObjectLiteralEvaluatedProps = new Map<__String, Expression>();
32430                    }
32431                    getNodeLinks(node).annotationObjectLiteralEvaluatedProps!.set(memberName, propValue);
32432                }
32433            }
32434            return getResolvedSignature(node.expression);
32435        }
32436
32437        /**
32438         * Resolves a decorator as if it were a call expression.
32439         */
32440        function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
32441            const funcType = checkExpression(node.expression);
32442            const apparentType = getApparentType(funcType);
32443            if (isErrorType(apparentType)) {
32444                return resolveErrorCall(node);
32445            }
32446
32447            const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
32448            const numConstructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct).length;
32449            if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, numConstructSignatures)) {
32450                return resolveUntypedCall(node);
32451            }
32452
32453            if (isPotentiallyUncalledDecorator(node, callSignatures)) {
32454                const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false);
32455                error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr);
32456                return resolveErrorCall(node);
32457            }
32458
32459            const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node);
32460            if (!callSignatures.length) {
32461                const errorDetails = invocationErrorDetails(node.expression, apparentType, SignatureKind.Call);
32462                const messageChain = chainDiagnosticMessages(errorDetails.messageChain, headMessage);
32463                const diag = createDiagnosticForNodeFromMessageChain(node.expression, messageChain);
32464                if (errorDetails.relatedMessage) {
32465                    addRelatedInfo(diag, createDiagnosticForNode(node.expression, errorDetails.relatedMessage));
32466                }
32467                diagnostics.add(diag);
32468                invocationErrorRecovery(apparentType, SignatureKind.Call, diag);
32469                return resolveErrorCall(node);
32470            }
32471
32472            return resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None, headMessage);
32473        }
32474
32475        function createSignatureForJSXIntrinsic(node: JsxOpeningLikeElement, result: Type): Signature {
32476            const namespace = getJsxNamespaceAt(node);
32477            const exports = namespace && getExportsOfSymbol(namespace);
32478            // We fake up a SFC signature for each intrinsic, however a more specific per-element signature drawn from the JSX declaration
32479            // file would probably be preferable.
32480            const typeSymbol = exports && getSymbol(exports, JsxNames.Element, SymbolFlags.Type);
32481            const returnNode = typeSymbol && nodeBuilder.symbolToEntityName(typeSymbol, SymbolFlags.Type, node);
32482            const declaration = factory.createFunctionTypeNode(/*typeParameters*/ undefined,
32483                [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotdotdot*/ undefined, "props", /*questionMark*/ undefined, nodeBuilder.typeToTypeNode(result, node))],
32484                returnNode ? factory.createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
32485            );
32486            const parameterSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "props" as __String);
32487            parameterSymbol.type = result;
32488            return createSignature(
32489                declaration,
32490                /*typeParameters*/ undefined,
32491                /*thisParameter*/ undefined,
32492                [parameterSymbol],
32493                typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType,
32494                /*returnTypePredicate*/ undefined,
32495                1,
32496                SignatureFlags.None
32497            );
32498        }
32499
32500        function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
32501            if (isJsxIntrinsicIdentifier(node.tagName)) {
32502                const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
32503                const fakeSignature = createSignatureForJSXIntrinsic(node, result);
32504                checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes);
32505                if (length(node.typeArguments)) {
32506                    forEach(node.typeArguments, checkSourceElement);
32507                    diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), node.typeArguments!, Diagnostics.Expected_0_type_arguments_but_got_1, 0, length(node.typeArguments)));
32508                }
32509                return fakeSignature;
32510            }
32511            const exprTypes = checkExpression(node.tagName);
32512            const apparentType = getApparentType(exprTypes);
32513            if (isErrorType(apparentType)) {
32514                return resolveErrorCall(node);
32515            }
32516
32517            const signatures = getUninstantiatedJsxSignaturesOfType(exprTypes, node);
32518            if (isUntypedFunctionCall(exprTypes, apparentType, signatures.length, /*constructSignatures*/ 0)) {
32519                return resolveUntypedCall(node);
32520            }
32521
32522            if (signatures.length === 0) {
32523                // We found no signatures at all, which is an error
32524                error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName));
32525                return resolveErrorCall(node);
32526            }
32527
32528            return resolveCall(node, signatures, candidatesOutArray, checkMode, SignatureFlags.None);
32529        }
32530
32531        /**
32532         * Sometimes, we have a decorator that could accept zero arguments,
32533         * but is receiving too many arguments as part of the decorator invocation.
32534         * In those cases, a user may have meant to *call* the expression before using it as a decorator.
32535         */
32536        function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: readonly Signature[]) {
32537            return signatures.length && every(signatures, signature =>
32538                signature.minArgumentCount === 0 &&
32539                !signatureHasRestParameter(signature) &&
32540                signature.parameters.length < getDecoratorArgumentCount(decorator, signature));
32541        }
32542
32543        function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
32544            switch (node.kind) {
32545                case SyntaxKind.CallExpression:
32546                case SyntaxKind.EtsComponentExpression:
32547                    return resolveCallExpression(node, candidatesOutArray, checkMode);
32548                case SyntaxKind.NewExpression:
32549                    return resolveNewExpression(node, candidatesOutArray, checkMode);
32550                case SyntaxKind.TaggedTemplateExpression:
32551                    return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode);
32552                case SyntaxKind.Decorator:
32553                    if (isAnnotation(node)) {
32554                        return resolveAnnotation(node);
32555                    }
32556                    return resolveDecorator(node, candidatesOutArray, checkMode);
32557                case SyntaxKind.JsxOpeningElement:
32558                case SyntaxKind.JsxSelfClosingElement:
32559                    return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode);
32560            }
32561        }
32562
32563        /**
32564         * Resolve a signature of a given call-like expression.
32565         * @param node a call-like expression to try resolve a signature for
32566         * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service;
32567         *                           the function will fill it up with appropriate candidate signatures
32568         * @return a signature of the call-like expression or undefined if one can't be found
32569         */
32570        function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, checkMode?: CheckMode): Signature {
32571            const links = getNodeLinks(node);
32572            // If getResolvedSignature has already been called, we will have cached the resolvedSignature.
32573            // However, it is possible that either candidatesOutArray was not passed in the first time,
32574            // or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
32575            // to correctly fill the candidatesOutArray.
32576            const cached = links.resolvedSignature;
32577            if (cached && cached !== resolvingSignature && !candidatesOutArray) {
32578                return cached;
32579            }
32580            links.resolvedSignature = resolvingSignature;
32581            const result = resolveSignature(node, candidatesOutArray, checkMode || CheckMode.Normal);
32582            // When CheckMode.SkipGenericFunctions is set we use resolvingSignature to indicate that call
32583            // resolution should be deferred.
32584            if (result !== resolvingSignature) {
32585                // If signature resolution originated in control flow type analysis (for example to compute the
32586                // assigned type in a flow assignment) we don't cache the result as it may be based on temporary
32587                // types from the control flow analysis.
32588                links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached;
32589            }
32590            return result;
32591        }
32592
32593        /**
32594         * Indicates whether a declaration can be treated as a constructor in a JavaScript
32595         * file.
32596         */
32597        function isJSConstructor(node: Node | undefined): node is FunctionDeclaration | FunctionExpression {
32598            if (!node || !isInJSFile(node)) {
32599                return false;
32600            }
32601            const func = isFunctionDeclaration(node) || isFunctionExpression(node) ? node :
32602                (isVariableDeclaration(node) || isPropertyAssignment(node)) && node.initializer && isFunctionExpression(node.initializer) ? node.initializer :
32603                undefined;
32604            if (func) {
32605                // If the node has a @class or @constructor tag, treat it like a constructor.
32606                if (getJSDocClassTag(node)) return true;
32607
32608                // If the node is a property of an object literal.
32609                if (isPropertyAssignment(walkUpParenthesizedExpressions(func.parent))) return false;
32610
32611                // If the symbol of the node has members, treat it like a constructor.
32612                const symbol = getSymbolOfNode(func);
32613                return !!symbol?.members?.size;
32614            }
32615            return false;
32616        }
32617
32618        function mergeJSSymbols(target: Symbol, source: Symbol | undefined) {
32619            if (source) {
32620                const links = getSymbolLinks(source);
32621                if (!links.inferredClassSymbol || !links.inferredClassSymbol.has(getSymbolId(target))) {
32622                    const inferred = isTransientSymbol(target) ? target : cloneSymbol(target) as TransientSymbol;
32623                    inferred.exports = inferred.exports || createSymbolTable();
32624                    inferred.members = inferred.members || createSymbolTable();
32625                    inferred.flags |= source.flags & SymbolFlags.Class;
32626                    if (source.exports?.size) {
32627                        mergeSymbolTable(inferred.exports, source.exports);
32628                    }
32629                    if (source.members?.size) {
32630                        mergeSymbolTable(inferred.members, source.members);
32631                    }
32632                    (links.inferredClassSymbol || (links.inferredClassSymbol = new Map())).set(getSymbolId(inferred), inferred);
32633                    return inferred;
32634                }
32635                return links.inferredClassSymbol.get(getSymbolId(target));
32636            }
32637        }
32638
32639        function getAssignedClassSymbol(decl: Declaration): Symbol | undefined {
32640            const assignmentSymbol = decl && getSymbolOfExpando(decl, /*allowDeclaration*/ true);
32641            const prototype = assignmentSymbol?.exports?.get("prototype" as __String);
32642            const init = prototype?.valueDeclaration && getAssignedJSPrototype(prototype.valueDeclaration);
32643            return init ? getSymbolOfNode(init) : undefined;
32644        }
32645
32646        function getSymbolOfExpando(node: Node, allowDeclaration: boolean): Symbol | undefined {
32647            if (!node.parent) {
32648                return undefined;
32649            }
32650            let name: Expression | BindingName | undefined;
32651            let decl: Node | undefined;
32652            if (isVariableDeclaration(node.parent) && node.parent.initializer === node) {
32653                if (!isInJSFile(node) && !(isVarConst(node.parent) && isFunctionLikeDeclaration(node))) {
32654                    return undefined;
32655                }
32656                name = node.parent.name;
32657                decl = node.parent;
32658            }
32659            else if (isBinaryExpression(node.parent)) {
32660                const parentNode = node.parent;
32661                const parentNodeOperator = node.parent.operatorToken.kind;
32662                if (parentNodeOperator === SyntaxKind.EqualsToken && (allowDeclaration || parentNode.right === node)) {
32663                    name = parentNode.left;
32664                    decl = name;
32665                }
32666                else if (parentNodeOperator === SyntaxKind.BarBarToken || parentNodeOperator === SyntaxKind.QuestionQuestionToken) {
32667                    if (isVariableDeclaration(parentNode.parent) && parentNode.parent.initializer === parentNode) {
32668                        name = parentNode.parent.name;
32669                        decl = parentNode.parent;
32670                    }
32671                    else if (isBinaryExpression(parentNode.parent) && parentNode.parent.operatorToken.kind === SyntaxKind.EqualsToken && (allowDeclaration || parentNode.parent.right === parentNode)) {
32672                        name = parentNode.parent.left;
32673                        decl = name;
32674                    }
32675
32676                    if (!name || !isBindableStaticNameExpression(name) || !isSameEntityName(name, parentNode.left)) {
32677                        return undefined;
32678                    }
32679                }
32680            }
32681            else if (allowDeclaration && isFunctionDeclaration(node)) {
32682                name = node.name;
32683                decl = node;
32684            }
32685
32686            if (!decl || !name || (!allowDeclaration && !getExpandoInitializer(node, isPrototypeAccess(name)))) {
32687                return undefined;
32688            }
32689            return getSymbolOfNode(decl);
32690        }
32691
32692
32693        function getAssignedJSPrototype(node: Node) {
32694            if (!node.parent) {
32695                return false;
32696            }
32697            let parent: Node = node.parent;
32698            while (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
32699                parent = parent.parent;
32700            }
32701            if (parent && isBinaryExpression(parent) && isPrototypeAccess(parent.left) && parent.operatorToken.kind === SyntaxKind.EqualsToken) {
32702                const right = getInitializerOfBinaryExpression(parent);
32703                return isObjectLiteralExpression(right) && right;
32704            }
32705        }
32706
32707        /**
32708         * Syntactically and semantically checks a call or new expression.
32709         * @param node The call/new expression to be checked.
32710         * @returns On success, the expression's signature's return type. On failure, anyType.
32711         */
32712        function checkCallExpression(node: CallExpression | NewExpression | EtsComponentExpression, checkMode?: CheckMode): Type {
32713            checkGrammarTypeArguments(node, node.typeArguments);
32714
32715            const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode);
32716            if (signature === resolvingSignature) {
32717                // CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that
32718                // returns a function type. We defer checking and return silentNeverType.
32719                return silentNeverType;
32720            }
32721
32722            checkDeprecatedSignature(signature, node);
32723
32724            if (node.expression.kind === SyntaxKind.SuperKeyword) {
32725                return voidType;
32726            }
32727
32728            if (node.kind === SyntaxKind.NewExpression) {
32729                const declaration = signature.declaration;
32730
32731                if (declaration &&
32732                    declaration.kind !== SyntaxKind.Constructor &&
32733                    declaration.kind !== SyntaxKind.ConstructSignature &&
32734                    declaration.kind !== SyntaxKind.ConstructorType &&
32735                    !isJSDocConstructSignature(declaration) &&
32736                    !isJSConstructor(declaration)) {
32737
32738                    // When resolved signature is a call signature (and not a construct signature) the result type is any
32739                    if (noImplicitAny) {
32740                        error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
32741                    }
32742                    return anyType;
32743                }
32744            }
32745
32746            // In JavaScript files, calls to any identifier 'require' are treated as external module imports
32747            if (isInJSFile(node) && isCommonJsRequire(node)) {
32748                return resolveExternalModuleTypeByLiteral(node.arguments![0] as StringLiteral);
32749            }
32750
32751            const returnType = getReturnTypeOfSignature(signature);
32752            // Treat any call to the global 'Symbol' function that is part of a const variable or readonly property
32753            // as a fresh unique symbol literal type.
32754            if (returnType.flags & TypeFlags.ESSymbolLike && isSymbolOrSymbolForCall(node)) {
32755                return getESSymbolLikeTypeForNode(walkUpParenthesizedExpressions(node.parent));
32756            }
32757            if (node.kind === SyntaxKind.CallExpression && !node.questionDotToken && node.parent.kind === SyntaxKind.ExpressionStatement &&
32758                returnType.flags & TypeFlags.Void && getTypePredicateOfSignature(signature)) {
32759                if (!isDottedName(node.expression)) {
32760                    error(node.expression, Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name);
32761                }
32762                else if (!getEffectsSignature(node)) {
32763                    const diagnostic = error(node.expression, Diagnostics.Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation);
32764                    getTypeOfDottedName(node.expression, diagnostic);
32765                }
32766            }
32767
32768            if (isInJSFile(node)) {
32769                const jsSymbol = getSymbolOfExpando(node, /*allowDeclaration*/ false);
32770                if (jsSymbol?.exports?.size) {
32771                    const jsAssignmentType = createAnonymousType(jsSymbol, jsSymbol.exports, emptyArray, emptyArray, emptyArray);
32772                    jsAssignmentType.objectFlags |= ObjectFlags.JSLiteral;
32773                    return getIntersectionType([returnType, jsAssignmentType]);
32774                }
32775            }
32776
32777            // System UI components can only be used in build/pageTransition method or method/function with the decorator "@Builder"
32778            if (isInETSFile(node) &&
32779                isIdentifier(node.expression) &&
32780                !isNewExpression(node) &&
32781                isSystemEtsComponent(node.expression, compilerOptions) &&
32782                !isInBuildOrPageTransitionContext(node, compilerOptions)) {
32783                error(node.expression, Diagnostics.UI_component_0_cannot_be_used_in_this_place, diagnosticName(node.expression));
32784            }
32785
32786            return returnType;
32787        }
32788
32789        function isSystemEtsComponent(node: Identifier, compilerOptions: CompilerOptions): boolean {
32790            // Check if the node's name is in the components list
32791            const name = getTextOfPropertyName(node).toString();
32792            if (!compilerOptions.ets?.components.some(component => component === name)) {
32793                return false;
32794            }
32795
32796            // we believe node is an system ets component if it's declared in "ets-loader/declarations/" in sdk
32797            if (!compilerOptions.etsLoaderPath) {
32798                return false;
32799            }
32800            const declarationsPath = resolvePath(compilerOptions.etsLoaderPath, "declarations");
32801            const symbol = resolveSymbol(getSymbolAtLocation(node));
32802            const declarations = symbol?.declarations;
32803            // Check if it only has one declaration and was declared in sdk
32804            if (!declarations || declarations.length !== 1) {
32805                return false;
32806            }
32807            const sourceFile = getSourceFileOfNode(declarations[0]);
32808            const fileName = sourceFile?.fileName;
32809            return !!fileName?.startsWith(declarationsPath);
32810        }
32811
32812        function propertyAccessExpressionConditionCheck(node: PropertyAccessExpression) {
32813            if (!jsDocFileCheckInfo.fileNeedCheck || !getJsDocNodeCheckedConfig) {
32814                return;
32815            }
32816            const sourceFile = getSourceFileOfNode(node);
32817            const sourceSymbol: Symbol | undefined = getPropertyAccessExpressionNameSymbol(node);
32818            if (!sourceSymbol || !sourceSymbol.valueDeclaration) {
32819                return;
32820            }
32821            const sourceSymbolSourceFile = getSourceFileOfNode(sourceSymbol.valueDeclaration);
32822            if (!sourceSymbolSourceFile) {
32823                return;
32824            }
32825            const checkParam = getJsDocNodeCheckedConfig(jsDocFileCheckInfo, sourceSymbolSourceFile.fileName);
32826            if (!checkParam.nodeNeedCheck) {
32827                return;
32828            }
32829            if (isIdentifier(node.name)) {
32830                if (sourceSymbol?.declarations && sourceSymbol?.declarations.length >= 2) {
32831                    const signatureDeclaration = tryGetSignatureDeclaration(checker, node);
32832                    if (signatureDeclaration) {
32833                        expressionCheckByJsDoc(signatureDeclaration, node.name, sourceFile, checkParam.checkConfig);
32834                    }
32835                } else {
32836                    sourceSymbol?.declarations?.forEach(item => {
32837                        if (isIdentifier(node.name)) {
32838                            expressionCheckByJsDoc(item, node.name, sourceFile, checkParam.checkConfig);
32839                        }
32840                    })
32841                }
32842            }
32843        }
32844
32845        function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
32846            const callLike = getAncestorCallLikeExpression(node);
32847            const signature = callLike && typeChecker.tryGetResolvedSignatureWithoutCheck(callLike);
32848            // Don't go to a function type, go to the value having that type.
32849            return tryCast(signature && signature.declaration, (d): d is SignatureDeclaration => isFunctionLike(d) && !isFunctionTypeNode(d));
32850        }
32851
32852        function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined {
32853            const target = findAncestor(node, n => ! isRightSideOfAccessExpression(n));
32854            const callLike = target?.parent;
32855            return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target ? callLike : undefined;
32856        }
32857
32858        function getPropertyAccessExpressionNameSymbol(node: PropertyAccessExpression) {
32859            const right = node.name;
32860            const leftType = checkNonNullExpression(node.expression);
32861            const assignmentKind = getAssignmentTargetKind(node);
32862            const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType);
32863            let sourceSymbol: Symbol | undefined;
32864            if (isPrivateIdentifier(right)) {
32865                const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(right.escapedText, right);
32866                sourceSymbol = lexicallyScopedSymbol ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedSymbol) : undefined;
32867            }
32868            else {
32869                sourceSymbol = getPropertyOfType(apparentType, right.escapedText);
32870                if (!sourceSymbol) {
32871                    const etsComponentExpressionNode = getEtsComponentExpressionInnerExpressionStatementNode(node)
32872                        || getRootEtsComponentInnerCallExpressionNode(node);
32873                    if (etsComponentExpressionNode) {
32874                        sourceSymbol = getEtsComponentExpressionPropertyOfType(node, etsComponentExpressionNode, right);
32875                    }
32876                }
32877            }
32878            return sourceSymbol;
32879        }
32880
32881        function getEtsComponentExpressionPropertyOfType(node: PropertyAccessExpression, etsComponentExpressionNode: CallExpression | EtsComponentExpression | PropertyAccessExpression | Identifier, right: Identifier) {
32882            let sourceSymbol: Symbol | undefined;
32883            const locals = getSourceFileOfNode(node).locals;
32884            if (locals?.has(right.escapedText)) {
32885                const extraSymbol = locals?.get(right.escapedText);
32886                const etsComponentName = isIdentifier(etsComponentExpressionNode) ?
32887                    etsComponentExpressionNode.escapedText :
32888                    isIdentifier(node.expression) ?
32889                        node.expression.escapedText :
32890                        undefined;
32891                const decorators = getAllDecorators(extraSymbol?.valueDeclaration);
32892                if (getEtsExtendDecoratorsComponentNames(decorators, compilerOptions).find(extendComponentName => extendComponentName === etsComponentName)) {
32893                    sourceSymbol = extraSymbol;
32894                }
32895                if (hasEtsStylesDecoratorNames(decorators, compilerOptions)) {
32896                    sourceSymbol = extraSymbol;
32897                }
32898            }
32899            const props = getContainingStruct(node)?.symbol.members;
32900            if (props?.has(right.escapedText)) {
32901                const stylesSymbol = props?.get(right.escapedText);
32902                const decorators = getAllDecorators(stylesSymbol?.valueDeclaration);
32903                if (hasEtsStylesDecoratorNames(decorators, compilerOptions)) {
32904                    sourceSymbol = stylesSymbol;
32905                }
32906            }
32907            return sourceSymbol;
32908        }
32909
32910        function conditionCheck(node: Identifier, jsDocs: readonly JSDocTag[], sourceFile: SourceFile, checkConfig: JsDocNodeCheckConfigItem) {
32911            const specifyJsDocTagValue = getSpecifyJsDocTagValue(jsDocs, checkConfig.tagName);
32912            if (specifyJsDocTagValue === undefined) {
32913                return;
32914            }
32915            const hasIfChecked = hasConditionChecked(node, specifyJsDocTagValue, checkConfig.specifyCheckConditionFuncName);
32916            if (!hasIfChecked && host.getJsDocNodeConditionCheckedResult) {
32917                const jsDocTagInfos: JsDocTagInfo[] = [];
32918                jsDocs.forEach(item => {
32919                    jsDocTagInfos.push({
32920                        name: item.tagName.escapedText.toString(),
32921                        text: getTextOfJSDocComment(item.comment),
32922                    });
32923                });
32924                const conditionCheckResult = host.getJsDocNodeConditionCheckedResult(jsDocFileCheckInfo, jsDocTagInfos);
32925                if (conditionCheckResult.valid) {
32926                    return;
32927                } else {
32928                    const diagnostic = createDiagnosticForNodeInSourceFile(sourceFile, node, Diagnostics.The_statement_must_be_written_use_the_function_0_under_the_if_condition, checkConfig.specifyCheckConditionFuncName);
32929                    collectDiagnostics(conditionCheckResult, node, diagnostic);
32930                }
32931            }
32932        }
32933
32934        function expressionCheckByJsDoc(declaration: Declaration, node: Identifier, sourceFile: SourceFile, checkConfig: JsDocNodeCheckConfigItem[]): void {
32935            const jsDocTags = getJSDocTags(declaration);
32936            for (let i = 0; i < checkConfig.length; i++) {
32937                const config = checkConfig[i];
32938                let tagNameCheckNecessity = true;
32939                if (config.checkJsDocSpecialValidCallback) {
32940                    tagNameCheckNecessity = config.checkJsDocSpecialValidCallback(jsDocTags, config);
32941                }
32942                if (!tagNameCheckNecessity) {
32943                    continue;
32944                }
32945                let tagNameExisted = false;
32946                if (!config.tagNameShouldExisted && config.needConditionCheck) {
32947                    conditionCheck(node, jsDocTags, sourceFile, config);
32948                }
32949                jsDocTags.forEach(item => {
32950                    if (config.tagName.includes(item.tagName.escapedText.toString())) {
32951                        if(config.checkValidCallback) {
32952                            tagNameExisted = config.checkValidCallback(item, config);
32953                        } else {
32954                            tagNameExisted = true;
32955                        }
32956                        if (tagNameExisted && !config.tagNameShouldExisted && !config.needConditionCheck) {
32957                            const diagnostic = createDiagnosticForNodeInSourceFile(sourceFile, node, Diagnostics.This_API_has_been_Special_Markings_exercise_caution_when_using_this_API);
32958                            collectDiagnostics(config, node, diagnostic);
32959                        }
32960                    }
32961                });
32962                if (config.tagNameShouldExisted && !tagNameExisted) {
32963                    const diagnostic = createDiagnosticForNodeInSourceFile(sourceFile, node, Diagnostics.This_API_has_been_Special_Markings_exercise_caution_when_using_this_API);
32964                    collectDiagnostics(config, node, diagnostic);
32965                }
32966            }
32967        }
32968
32969        function collectDiagnostics(config: JsDocNodeCheckConfigItem | ConditionCheckResult, node: Identifier, diagnostic: DiagnosticWithLocation): void {
32970            if (config.message) {
32971                // @ts-ignore
32972                diagnostic.messageText = config.message.replace("{0}", node.getText() === "" ? node.text : node.getText());
32973            }
32974            diagnostic.category = config.type ? config.type : ts.DiagnosticCategory.Warning;
32975            diagnostics.add(diagnostic);
32976            suggestionDiagnostics.add(diagnostic);
32977        }
32978
32979        function getSpecifyJsDocTagValue(jsDocs: readonly JSDocTag[], specifyTag: string[]): string | undefined {
32980            let specifyJsDocTagValue;
32981            jsDocs.forEach(item => {
32982                    if (specifyTag.includes(item.tagName.escapedText.toString())) {
32983                        specifyJsDocTagValue = item.comment ?? "";
32984                    }
32985            });
32986            return specifyJsDocTagValue;
32987        }
32988
32989        function hasConditionChecked(expression: Identifier, importSymbol: string, funcSpecify: string): boolean {
32990            const result = { hasIfChecked: false };
32991            const container = findAncestor(expression, isSourceFile);
32992            if (!container) {
32993                return result.hasIfChecked;
32994            }
32995            traversalNode(expression, importSymbol, container, result, funcSpecify);
32996            return result.hasIfChecked;
32997        }
32998
32999        function traversalNode(node: Node, importSymbol: string, parent: Node, result: { hasIfChecked: boolean }, specifyFuncName: string): void {
33000            if (result.hasIfChecked) {
33001                return;
33002            }
33003
33004            if (node.parent !== parent) {
33005                if (isIfStatement(node.parent)) {
33006                    if (isCallExpression(node.parent.expression) && isTargetCallExpression(node.parent.expression, specifyFuncName, importSymbol)) {
33007                        result.hasIfChecked = true;
33008                        return;
33009                    }
33010                    else {
33011                        traversalNode(node.parent, importSymbol, parent, result, specifyFuncName);
33012                    }
33013                }
33014                traversalNode(node.parent, importSymbol, parent, result, specifyFuncName);
33015            }
33016            else {
33017                return;
33018            }
33019        }
33020
33021        function isTargetCallExpression(node: CallExpression, specifyFuncName: string, importSymbol: string): boolean {
33022            if (isIdentifier(node.expression) &&
33023                node.arguments.length === 1 &&
33024                node.expression.escapedText.toString() === specifyFuncName) {
33025                const expression = node.arguments[0];
33026                if (isStringLiteral(expression) && expression.text.toString() === importSymbol) {
33027                    return true;
33028                }
33029            }
33030            return false;
33031        }
33032
33033        function checkDeprecatedSignature(signature: Signature, node: CallLikeExpression) {
33034            if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) {
33035                const suggestionNode = getDeprecatedSuggestionNode(node);
33036                const name = tryGetPropertyAccessOrIdentifierToString(getInvokedExpression(node));
33037                addDeprecatedSuggestionWithSignature(suggestionNode, signature.declaration, name, signatureToString(signature));
33038            }
33039        }
33040
33041        function getDeprecatedSuggestionNode(node: Node): Node {
33042            node = skipParentheses(node);
33043            switch (node.kind) {
33044                case SyntaxKind.CallExpression:
33045                case SyntaxKind.Decorator:
33046                case SyntaxKind.NewExpression:
33047                    return getDeprecatedSuggestionNode((node as Decorator | CallExpression | NewExpression).expression);
33048                case SyntaxKind.TaggedTemplateExpression:
33049                    return getDeprecatedSuggestionNode((node as TaggedTemplateExpression).tag);
33050                case SyntaxKind.JsxOpeningElement:
33051                case SyntaxKind.JsxSelfClosingElement:
33052                    return getDeprecatedSuggestionNode((node as JsxOpeningLikeElement).tagName);
33053                case SyntaxKind.ElementAccessExpression:
33054                    return (node as ElementAccessExpression).argumentExpression;
33055                case SyntaxKind.PropertyAccessExpression:
33056                    return (node as PropertyAccessExpression).name;
33057                case SyntaxKind.TypeReference:
33058                    const typeReference = node as TypeReferenceNode;
33059                    return isQualifiedName(typeReference.typeName) ? typeReference.typeName.right : typeReference;
33060                default:
33061                    return node;
33062            }
33063        }
33064
33065        function isSymbolOrSymbolForCall(node: Node) {
33066            if (!isCallExpression(node)) return false;
33067            let left = node.expression;
33068            if (isPropertyAccessExpression(left) && left.name.escapedText === "for") {
33069                left = left.expression;
33070            }
33071            if (!isIdentifier(left) || left.escapedText !== "Symbol") {
33072                return false;
33073            }
33074
33075            // make sure `Symbol` is the global symbol
33076            const globalESSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false);
33077            if (!globalESSymbol) {
33078                return false;
33079            }
33080
33081            return globalESSymbol === resolveName(left, "Symbol" as __String, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false);
33082        }
33083
33084        function checkImportCallExpression(node: ImportCall): Type {
33085            // Check grammar of dynamic import
33086            checkGrammarImportCallExpression(node);
33087
33088            if (node.arguments.length === 0) {
33089                return createPromiseReturnType(node, anyType);
33090            }
33091
33092            const specifier = node.arguments[0];
33093            const specifierType = checkExpressionCached(specifier);
33094            const optionsType = node.arguments.length > 1 ? checkExpressionCached(node.arguments[1]) : undefined;
33095            // Even though multiple arguments is grammatically incorrect, type-check extra arguments for completion
33096            for (let i = 2; i < node.arguments.length; ++i) {
33097                checkExpressionCached(node.arguments[i]);
33098            }
33099
33100            if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) {
33101                error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType));
33102            }
33103
33104            if (optionsType) {
33105                const importCallOptionsType = getGlobalImportCallOptionsType(/*reportErrors*/ true);
33106                if (importCallOptionsType !== emptyObjectType) {
33107                    checkTypeAssignableTo(optionsType, getNullableType(importCallOptionsType, TypeFlags.Undefined), node.arguments[1]);
33108                }
33109            }
33110
33111            // resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal
33112            const moduleSymbol = resolveExternalModuleName(node, specifier);
33113            if (moduleSymbol) {
33114                const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true, /*suppressUsageError*/ false);
33115                if (esModuleSymbol) {
33116                    return createPromiseReturnType(node,
33117                        getTypeWithSyntheticDefaultOnly(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier) ||
33118                            getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol, specifier)
33119                    );
33120                }
33121            }
33122            return createPromiseReturnType(node, anyType);
33123        }
33124
33125        function createDefaultPropertyWrapperForModule(symbol: Symbol, originalSymbol: Symbol, anonymousSymbol?: Symbol | undefined) {
33126            const memberTable = createSymbolTable();
33127            const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
33128            newSymbol.parent = originalSymbol;
33129            newSymbol.nameType = getStringLiteralType("default");
33130            newSymbol.aliasTarget = resolveSymbol(symbol);
33131            memberTable.set(InternalSymbolName.Default, newSymbol);
33132            return createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray);
33133        }
33134
33135        function getTypeWithSyntheticDefaultOnly(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression) {
33136            const hasDefaultOnly = isOnlyImportedAsDefault(moduleSpecifier);
33137            if (hasDefaultOnly && type && !isErrorType(type)) {
33138                const synthType = type as SyntheticDefaultModuleType;
33139                if (!synthType.defaultOnlyType) {
33140                    const type = createDefaultPropertyWrapperForModule(symbol, originalSymbol);
33141                    synthType.defaultOnlyType = type;
33142                }
33143                return synthType.defaultOnlyType;
33144            }
33145            return undefined;
33146        }
33147
33148        function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression): Type {
33149            if (allowSyntheticDefaultImports && type && !isErrorType(type)) {
33150                const synthType = type as SyntheticDefaultModuleType;
33151                if (!synthType.syntheticType) {
33152                    const file = originalSymbol.declarations?.find(isSourceFile);
33153                    const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false, moduleSpecifier);
33154                    if (hasSyntheticDefault) {
33155                        const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
33156                        const defaultContainingObject = createDefaultPropertyWrapperForModule(symbol, originalSymbol, anonymousSymbol);
33157                        anonymousSymbol.type = defaultContainingObject;
33158                        synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject;
33159                    }
33160                    else {
33161                        synthType.syntheticType = type;
33162                    }
33163                }
33164                return synthType.syntheticType;
33165            }
33166            return type;
33167        }
33168
33169        function isCommonJsRequire(node: Node): boolean {
33170            if (!isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
33171                return false;
33172            }
33173
33174            // Make sure require is not a local function
33175            if (!isIdentifier(node.expression)) return Debug.fail();
33176            const resolvedRequire = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true)!; // TODO: GH#18217
33177            if (resolvedRequire === requireSymbol) {
33178                return true;
33179            }
33180            // project includes symbol named 'require' - make sure that it is ambient and local non-alias
33181            if (resolvedRequire.flags & SymbolFlags.Alias) {
33182                return false;
33183            }
33184
33185            const targetDeclarationKind = resolvedRequire.flags & SymbolFlags.Function
33186                ? SyntaxKind.FunctionDeclaration
33187                : resolvedRequire.flags & SymbolFlags.Variable
33188                    ? SyntaxKind.VariableDeclaration
33189                    : SyntaxKind.Unknown;
33190            if (targetDeclarationKind !== SyntaxKind.Unknown) {
33191                const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind)!;
33192                // function/variable declaration should be ambient
33193                return !!decl && !!(decl.flags & NodeFlags.Ambient);
33194            }
33195            return false;
33196        }
33197
33198        function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type {
33199            if (!checkGrammarTaggedTemplateChain(node)) checkGrammarTypeArguments(node, node.typeArguments);
33200            if (languageVersion < ScriptTarget.ES2015) {
33201                checkExternalEmitHelpers(node, ExternalEmitHelpers.MakeTemplateObject);
33202            }
33203            const signature = getResolvedSignature(node);
33204            checkDeprecatedSignature(signature, node);
33205            return getReturnTypeOfSignature(signature);
33206        }
33207
33208        function checkAssertion(node: AssertionExpression) {
33209            if (node.kind === SyntaxKind.TypeAssertionExpression) {
33210                const file = getSourceFileOfNode(node);
33211                if (file && fileExtensionIsOneOf(file.fileName, [Extension.Cts, Extension.Mts])) {
33212                    grammarErrorOnNode(node, Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead);
33213                }
33214            }
33215            return checkAssertionWorker(node, node.type, node.expression);
33216        }
33217
33218        function isValidConstAssertionArgument(node: Node): boolean {
33219            switch (node.kind) {
33220                case SyntaxKind.StringLiteral:
33221                case SyntaxKind.NoSubstitutionTemplateLiteral:
33222                case SyntaxKind.NumericLiteral:
33223                case SyntaxKind.BigIntLiteral:
33224                case SyntaxKind.TrueKeyword:
33225                case SyntaxKind.FalseKeyword:
33226                case SyntaxKind.ArrayLiteralExpression:
33227                case SyntaxKind.ObjectLiteralExpression:
33228                case SyntaxKind.TemplateExpression:
33229                    return true;
33230                case SyntaxKind.ParenthesizedExpression:
33231                    return isValidConstAssertionArgument((node as ParenthesizedExpression).expression);
33232                case SyntaxKind.PrefixUnaryExpression:
33233                    const op = (node as PrefixUnaryExpression).operator;
33234                    const arg = (node as PrefixUnaryExpression).operand;
33235                    return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) ||
33236                        op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral;
33237                case SyntaxKind.PropertyAccessExpression:
33238                case SyntaxKind.ElementAccessExpression:
33239                    const expr = (node as PropertyAccessExpression | ElementAccessExpression).expression;
33240                    let symbol = getTypeOfNode(expr).symbol;
33241                    if (symbol && symbol.flags & SymbolFlags.Alias) {
33242                        symbol = resolveAlias(symbol);
33243                    }
33244                    return !!(symbol && (getAllSymbolFlags(symbol) & SymbolFlags.Enum) && getEnumKind(symbol) === EnumKind.Literal);
33245            }
33246            return false;
33247        }
33248
33249        function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) {
33250            let exprType = checkExpression(expression, checkMode);
33251            if (isConstTypeReference(type)) {
33252                if (!isValidConstAssertionArgument(expression)) {
33253                    error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals);
33254                }
33255                return getRegularTypeOfLiteralType(exprType);
33256            }
33257            checkSourceElement(type);
33258            exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(exprType));
33259            const targetType = getTypeFromTypeNode(type);
33260            if (!isErrorType(targetType)) {
33261                addLazyDiagnostic(() => {
33262                    const widenedType = getWidenedType(exprType);
33263                    if (!isTypeComparableTo(targetType, widenedType)) {
33264                        checkTypeComparableTo(exprType, targetType, errNode,
33265                            Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first);
33266                    }
33267                });
33268            }
33269            return targetType;
33270        }
33271
33272        function checkNonNullChain(node: NonNullChain) {
33273            const leftType = checkExpression(node.expression);
33274            const nonOptionalType = getOptionalExpressionType(leftType, node.expression);
33275            return propagateOptionalTypeMarker(getNonNullableType(nonOptionalType), node, nonOptionalType !== leftType);
33276        }
33277
33278        function checkNonNullAssertion(node: NonNullExpression) {
33279            return node.flags & NodeFlags.OptionalChain ? checkNonNullChain(node as NonNullChain) :
33280                getNonNullableType(checkExpression(node.expression));
33281        }
33282
33283        function checkExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) {
33284            checkGrammarExpressionWithTypeArguments(node);
33285            const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) :
33286                isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) :
33287                checkExpression(node.exprName);
33288            const typeArguments = node.typeArguments;
33289            if (exprType === silentNeverType || isErrorType(exprType) || !some(typeArguments)) {
33290                return exprType;
33291            }
33292            let hasSomeApplicableSignature = false;
33293            let nonApplicableType: Type | undefined;
33294            const result = getInstantiatedType(exprType);
33295            const errorType = hasSomeApplicableSignature ? nonApplicableType : exprType;
33296            if (errorType) {
33297                diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Type_0_has_no_signatures_for_which_the_type_argument_list_is_applicable, typeToString(errorType)));
33298            }
33299            return result;
33300
33301            function getInstantiatedType(type: Type): Type {
33302                let hasSignatures = false;
33303                let hasApplicableSignature = false;
33304                const result = getInstantiatedTypePart(type);
33305                hasSomeApplicableSignature ||= hasApplicableSignature;
33306                if (hasSignatures && !hasApplicableSignature) {
33307                    nonApplicableType ??= type;
33308                }
33309                return result;
33310
33311                function getInstantiatedTypePart(type: Type): Type {
33312                    if (type.flags & TypeFlags.Object) {
33313                        const resolved = resolveStructuredTypeMembers(type as ObjectType);
33314                        const callSignatures = getInstantiatedSignatures(resolved.callSignatures);
33315                        const constructSignatures = getInstantiatedSignatures(resolved.constructSignatures);
33316                        hasSignatures ||= resolved.callSignatures.length !== 0 || resolved.constructSignatures.length !== 0;
33317                        hasApplicableSignature ||= callSignatures.length !== 0 || constructSignatures.length !== 0;
33318                        if (callSignatures !== resolved.callSignatures || constructSignatures !== resolved.constructSignatures) {
33319                            const result = createAnonymousType(undefined, resolved.members, callSignatures, constructSignatures, resolved.indexInfos) as ResolvedType & InstantiationExpressionType;
33320                            result.objectFlags |= ObjectFlags.InstantiationExpressionType;
33321                            result.node = node;
33322                            return result;
33323                        }
33324                    }
33325                    else if (type.flags & TypeFlags.InstantiableNonPrimitive) {
33326                        const constraint = getBaseConstraintOfType(type);
33327                        if (constraint) {
33328                            const instantiated = getInstantiatedTypePart(constraint);
33329                            if (instantiated !== constraint) {
33330                                return instantiated;
33331                            }
33332                        }
33333                    }
33334                    else if (type.flags & TypeFlags.Union) {
33335                        return mapType(type, getInstantiatedType);
33336                    }
33337                    else if (type.flags & TypeFlags.Intersection) {
33338                        return getIntersectionType(sameMap((type as IntersectionType).types, getInstantiatedTypePart));
33339                    }
33340                    return type;
33341                }
33342            }
33343
33344            function getInstantiatedSignatures(signatures: readonly Signature[]) {
33345                const applicableSignatures = filter(signatures, sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments));
33346                return sameMap(applicableSignatures, sig => {
33347                    const typeArgumentTypes = checkTypeArguments(sig, typeArguments!, /*reportErrors*/ true);
33348                    return typeArgumentTypes ? getSignatureInstantiation(sig, typeArgumentTypes, isInJSFile(sig.declaration)) : sig;
33349                });
33350            }
33351        }
33352
33353        function checkSatisfiesExpression(node: SatisfiesExpression) {
33354            checkSourceElement(node.type);
33355            const exprType = checkExpression(node.expression);
33356
33357            const targetType = getTypeFromTypeNode(node.type);
33358            if (isErrorType(targetType)) {
33359                return targetType;
33360            }
33361
33362            checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, node.type, node.expression, Diagnostics.Type_0_does_not_satisfy_the_expected_type_1);
33363
33364            return exprType;
33365        }
33366
33367        function checkMetaProperty(node: MetaProperty): Type {
33368            checkGrammarMetaProperty(node);
33369
33370            if (node.keywordToken === SyntaxKind.NewKeyword) {
33371                return checkNewTargetMetaProperty(node);
33372            }
33373
33374            if (node.keywordToken === SyntaxKind.ImportKeyword) {
33375                return checkImportMetaProperty(node);
33376            }
33377
33378            return Debug.assertNever(node.keywordToken);
33379        }
33380
33381        function checkMetaPropertyKeyword(node: MetaProperty): Type {
33382            switch (node.keywordToken) {
33383                case SyntaxKind.ImportKeyword:
33384                    return getGlobalImportMetaExpressionType();
33385                case SyntaxKind.NewKeyword:
33386                    const type = checkNewTargetMetaProperty(node);
33387                    return isErrorType(type) ? errorType : createNewTargetExpressionType(type);
33388                default:
33389                    Debug.assertNever(node.keywordToken);
33390            }
33391        }
33392
33393        function checkNewTargetMetaProperty(node: MetaProperty) {
33394            const container = getNewTargetContainer(node);
33395            if (!container) {
33396                error(node, Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target");
33397                return errorType;
33398            }
33399            else if (container.kind === SyntaxKind.Constructor) {
33400                const symbol = getSymbolOfNode(container.parent as ClassLikeDeclaration);
33401                return getTypeOfSymbol(symbol);
33402            }
33403            else {
33404                const symbol = getSymbolOfNode(container)!;
33405                return getTypeOfSymbol(symbol);
33406            }
33407        }
33408
33409        function checkImportMetaProperty(node: MetaProperty) {
33410            if (moduleKind === ModuleKind.Node16 || moduleKind === ModuleKind.NodeNext) {
33411                if (getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.ESNext) {
33412                    error(node, Diagnostics.The_import_meta_meta_property_is_not_allowed_in_files_which_will_build_into_CommonJS_output);
33413                }
33414            }
33415            else if (moduleKind < ModuleKind.ES2020 && moduleKind !== ModuleKind.System) {
33416                error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_or_nodenext);
33417            }
33418            const file = getSourceFileOfNode(node);
33419            Debug.assert(!!(file.flags & NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag.");
33420            return node.name.escapedText === "meta" ? getGlobalImportMetaType() : errorType;
33421        }
33422
33423        function getTypeOfParameter(symbol: Symbol) {
33424            const type = getTypeOfSymbol(symbol);
33425            if (strictNullChecks) {
33426                const declaration = symbol.valueDeclaration;
33427                if (declaration && hasInitializer(declaration)) {
33428                    return getOptionalType(type);
33429                }
33430            }
33431            return type;
33432        }
33433
33434        function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
33435            Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
33436            return d.name.escapedText;
33437        }
33438
33439        function getParameterNameAtPosition(signature: Signature, pos: number, overrideRestType?: Type) {
33440            const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
33441            if (pos < paramCount) {
33442                return signature.parameters[pos].escapedName;
33443            }
33444            const restParameter = signature.parameters[paramCount] || unknownSymbol;
33445            const restType = overrideRestType || getTypeOfSymbol(restParameter);
33446            if (isTupleType(restType)) {
33447                const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
33448                const index = pos - paramCount;
33449                return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as __String;
33450            }
33451            return restParameter.escapedName;
33452        }
33453
33454        function getParameterIdentifierNameAtPosition(signature: Signature, pos: number): [parameterName: __String, isRestParameter: boolean] | undefined {
33455            if (signature.declaration?.kind === SyntaxKind.JSDocFunctionType) {
33456                return undefined;
33457            }
33458            const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
33459            if (pos < paramCount) {
33460                const param = signature.parameters[pos];
33461                return isParameterDeclarationWithIdentifierName(param) ? [param.escapedName, false] : undefined;
33462            }
33463
33464            const restParameter = signature.parameters[paramCount] || unknownSymbol;
33465            if (!isParameterDeclarationWithIdentifierName(restParameter)) {
33466                return undefined;
33467            }
33468
33469            const restType = getTypeOfSymbol(restParameter);
33470            if (isTupleType(restType)) {
33471                const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
33472                const index = pos - paramCount;
33473                const associatedName = associatedNames?.[index];
33474                const isRestTupleElement = !!associatedName?.dotDotDotToken;
33475                return associatedName ? [
33476                    getTupleElementLabel(associatedName),
33477                    isRestTupleElement
33478                ] : undefined;
33479            }
33480
33481            if (pos === paramCount) {
33482                return [restParameter.escapedName, true];
33483            }
33484            return undefined;
33485        }
33486
33487        function isParameterDeclarationWithIdentifierName(symbol: Symbol) {
33488            return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) && isIdentifier(symbol.valueDeclaration.name);
33489        }
33490        function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier }) {
33491            return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && d.name && isIdentifier(d.name));
33492        }
33493
33494        function getNameableDeclarationAtPosition(signature: Signature, pos: number) {
33495            const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
33496            if (pos < paramCount) {
33497                const decl = signature.parameters[pos].valueDeclaration;
33498                return decl && isValidDeclarationForTupleLabel(decl) ? decl : undefined;
33499            }
33500            const restParameter = signature.parameters[paramCount] || unknownSymbol;
33501            const restType = getTypeOfSymbol(restParameter);
33502            if (isTupleType(restType)) {
33503                const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations;
33504                const index = pos - paramCount;
33505                return associatedNames && associatedNames[index];
33506            }
33507            return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) ? restParameter.valueDeclaration : undefined;
33508        }
33509
33510        function getTypeAtPosition(signature: Signature, pos: number): Type {
33511            return tryGetTypeAtPosition(signature, pos) || anyType;
33512        }
33513
33514        function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
33515            const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
33516            if (pos < paramCount) {
33517                return getTypeOfParameter(signature.parameters[pos]);
33518            }
33519            if (signatureHasRestParameter(signature)) {
33520                // We want to return the value undefined for an out of bounds parameter position,
33521                // so we need to check bounds here before calling getIndexedAccessType (which
33522                // otherwise would return the type 'undefined').
33523                const restType = getTypeOfSymbol(signature.parameters[paramCount]);
33524                const index = pos - paramCount;
33525                if (!isTupleType(restType) || restType.target.hasRestElement || index < restType.target.fixedLength) {
33526                    return getIndexedAccessType(restType, getNumberLiteralType(index));
33527                }
33528            }
33529            return undefined;
33530        }
33531
33532        function getRestTypeAtPosition(source: Signature, pos: number): Type {
33533            const parameterCount = getParameterCount(source);
33534            const minArgumentCount = getMinArgumentCount(source);
33535            const restType = getEffectiveRestType(source);
33536            if (restType && pos >= parameterCount - 1) {
33537                return pos === parameterCount - 1 ? restType : createArrayType(getIndexedAccessType(restType, numberType));
33538            }
33539            const types = [];
33540            const flags = [];
33541            const names = [];
33542            for (let i = pos; i < parameterCount; i++) {
33543                if (!restType || i < parameterCount - 1) {
33544                    types.push(getTypeAtPosition(source, i));
33545                    flags.push(i < minArgumentCount ? ElementFlags.Required : ElementFlags.Optional);
33546                }
33547                else {
33548                    types.push(restType);
33549                    flags.push(ElementFlags.Variadic);
33550                }
33551                const name = getNameableDeclarationAtPosition(source, i);
33552                if (name) {
33553                    names.push(name);
33554                }
33555            }
33556            return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined);
33557        }
33558
33559        // Return the number of parameters in a signature. The rest parameter, if present, counts as one
33560        // parameter. For example, the parameter count of (x: number, y: number, ...z: string[]) is 3 and
33561        // the parameter count of (x: number, ...args: [number, ...string[], boolean])) is also 3. In the
33562        // latter example, the effective rest type is [...string[], boolean].
33563        function getParameterCount(signature: Signature) {
33564            const length = signature.parameters.length;
33565            if (signatureHasRestParameter(signature)) {
33566                const restType = getTypeOfSymbol(signature.parameters[length - 1]);
33567                if (isTupleType(restType)) {
33568                    return length + restType.target.fixedLength - (restType.target.hasRestElement ? 0 : 1);
33569                }
33570            }
33571            return length;
33572        }
33573
33574        function getMinArgumentCount(signature: Signature, flags?: MinArgumentCountFlags) {
33575            const strongArityForUntypedJS = flags! & MinArgumentCountFlags.StrongArityForUntypedJS;
33576            const voidIsNonOptional = flags! & MinArgumentCountFlags.VoidIsNonOptional;
33577            if (voidIsNonOptional || signature.resolvedMinArgumentCount === undefined) {
33578                let minArgumentCount: number | undefined;
33579                if (signatureHasRestParameter(signature)) {
33580                    const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
33581                    if (isTupleType(restType)) {
33582                        const firstOptionalIndex = findIndex(restType.target.elementFlags, f => !(f & ElementFlags.Required));
33583                        const requiredCount = firstOptionalIndex < 0 ? restType.target.fixedLength : firstOptionalIndex;
33584                        if (requiredCount > 0) {
33585                            minArgumentCount = signature.parameters.length - 1 + requiredCount;
33586                        }
33587                    }
33588                }
33589                if (minArgumentCount === undefined) {
33590                    if (!strongArityForUntypedJS && signature.flags & SignatureFlags.IsUntypedSignatureInJSFile) {
33591                        return 0;
33592                    }
33593                    minArgumentCount = signature.minArgumentCount;
33594                }
33595                if (voidIsNonOptional) {
33596                    return minArgumentCount;
33597                }
33598                for (let i = minArgumentCount - 1; i >= 0; i--) {
33599                    const type = getTypeAtPosition(signature, i);
33600                    if (filterType(type, acceptsVoid).flags & TypeFlags.Never) {
33601                        break;
33602                    }
33603                    minArgumentCount = i;
33604                }
33605                signature.resolvedMinArgumentCount = minArgumentCount;
33606            }
33607            return signature.resolvedMinArgumentCount;
33608        }
33609
33610        function hasEffectiveRestParameter(signature: Signature) {
33611            if (signatureHasRestParameter(signature)) {
33612                const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
33613                return !isTupleType(restType) || restType.target.hasRestElement;
33614            }
33615            return false;
33616        }
33617
33618        function getEffectiveRestType(signature: Signature) {
33619            if (signatureHasRestParameter(signature)) {
33620                const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
33621                if (!isTupleType(restType)) {
33622                    return restType;
33623                }
33624                if (restType.target.hasRestElement) {
33625                    return sliceTupleType(restType, restType.target.fixedLength);
33626                }
33627            }
33628            return undefined;
33629        }
33630
33631        function getNonArrayRestType(signature: Signature) {
33632            const restType = getEffectiveRestType(signature);
33633            return restType && !isArrayType(restType) && !isTypeAny(restType) && (getReducedType(restType).flags & TypeFlags.Never) === 0 ? restType : undefined;
33634        }
33635
33636        function getTypeOfFirstParameterOfSignature(signature: Signature) {
33637            return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType);
33638        }
33639
33640        function getTypeOfFirstParameterOfSignatureWithFallback(signature: Signature, fallbackType: Type) {
33641            return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : fallbackType;
33642        }
33643
33644        function inferFromAnnotatedParameters(signature: Signature, context: Signature, inferenceContext: InferenceContext) {
33645            const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
33646            for (let i = 0; i < len; i++) {
33647                const declaration = signature.parameters[i].valueDeclaration as ParameterDeclaration;
33648                if (declaration.type) {
33649                    const typeNode = getEffectiveTypeAnnotationNode(declaration);
33650                    if (typeNode) {
33651                        inferTypes(inferenceContext.inferences, getTypeFromTypeNode(typeNode), getTypeAtPosition(context, i));
33652                    }
33653                }
33654            }
33655        }
33656
33657        function assignContextualParameterTypes(signature: Signature, context: Signature) {
33658            if (context.typeParameters) {
33659                if (!signature.typeParameters) {
33660                    signature.typeParameters = context.typeParameters;
33661                }
33662                else {
33663                    return; // This signature has already has a contextual inference performed and cached on it!
33664                }
33665            }
33666            if (context.thisParameter) {
33667                const parameter = signature.thisParameter;
33668                if (!parameter || parameter.valueDeclaration && !(parameter.valueDeclaration as ParameterDeclaration).type) {
33669                    if (!parameter) {
33670                        signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined);
33671                    }
33672                    assignParameterType(signature.thisParameter!, getTypeOfSymbol(context.thisParameter));
33673                }
33674            }
33675            const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
33676            for (let i = 0; i < len; i++) {
33677                const parameter = signature.parameters[i];
33678                if (!getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration)) {
33679                    const contextualParameterType = tryGetTypeAtPosition(context, i);
33680                    assignParameterType(parameter, contextualParameterType);
33681                }
33682            }
33683            if (signatureHasRestParameter(signature)) {
33684                // parameter might be a transient symbol generated by use of `arguments` in the function body.
33685                const parameter = last(signature.parameters);
33686                if (parameter.valueDeclaration
33687                    ? !getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration)
33688                    // a declarationless parameter may still have a `.type` already set by its construction logic
33689                    // (which may pull a type from a jsdoc) - only allow fixing on `DeferredType` parameters with a fallback type
33690                    : !!(getCheckFlags(parameter) & CheckFlags.DeferredType)
33691                ) {
33692                    const contextualParameterType = getRestTypeAtPosition(context, len);
33693                    assignParameterType(parameter, contextualParameterType);
33694                }
33695            }
33696        }
33697
33698        function assignNonContextualParameterTypes(signature: Signature) {
33699            if (signature.thisParameter) {
33700                assignParameterType(signature.thisParameter);
33701            }
33702            for (const parameter of signature.parameters) {
33703                assignParameterType(parameter);
33704            }
33705        }
33706
33707        function assignParameterType(parameter: Symbol, type?: Type) {
33708            const links = getSymbolLinks(parameter);
33709            if (!links.type) {
33710                const declaration = parameter.valueDeclaration as ParameterDeclaration | undefined;
33711                links.type = type || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) : getTypeOfSymbol(parameter));
33712                if (declaration && declaration.name.kind !== SyntaxKind.Identifier) {
33713                    // if inference didn't come up with anything but unknown, fall back to the binding pattern if present.
33714                    if (links.type === unknownType) {
33715                        links.type = getTypeFromBindingPattern(declaration.name);
33716                    }
33717                    assignBindingElementTypes(declaration.name, links.type);
33718                }
33719            }
33720            else if (type) {
33721                Debug.assertEqual(links.type, type, "Parameter symbol already has a cached type which differs from newly assigned type");
33722            }
33723        }
33724
33725        // When contextual typing assigns a type to a parameter that contains a binding pattern, we also need to push
33726        // the destructured type into the contained binding elements.
33727        function assignBindingElementTypes(pattern: BindingPattern, parentType: Type) {
33728            for (const element of pattern.elements) {
33729                if (!isOmittedExpression(element)) {
33730                    const type = getBindingElementTypeFromParentType(element, parentType);
33731                    if (element.name.kind === SyntaxKind.Identifier) {
33732                        getSymbolLinks(getSymbolOfNode(element)).type = type;
33733                    }
33734                    else {
33735                        assignBindingElementTypes(element.name, type);
33736                    }
33737                }
33738            }
33739        }
33740
33741        function createPromiseType(promisedType: Type): Type {
33742            // creates a `Promise<T>` type where `T` is the promisedType argument
33743            const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
33744            if (globalPromiseType !== emptyGenericType) {
33745                // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
33746                // Unwrap an `Awaited<T>` to `T` to improve inference.
33747                promisedType = getAwaitedTypeNoAlias(unwrapAwaitedType(promisedType)) || unknownType;
33748                return createTypeReference(globalPromiseType, [promisedType]);
33749            }
33750
33751            return unknownType;
33752        }
33753
33754        function createPromiseLikeType(promisedType: Type): Type {
33755            // creates a `PromiseLike<T>` type where `T` is the promisedType argument
33756            const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
33757            if (globalPromiseLikeType !== emptyGenericType) {
33758                // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
33759                // Unwrap an `Awaited<T>` to `T` to improve inference.
33760                promisedType = getAwaitedTypeNoAlias(unwrapAwaitedType(promisedType)) || unknownType;
33761                return createTypeReference(globalPromiseLikeType, [promisedType]);
33762            }
33763
33764            return unknownType;
33765        }
33766
33767        function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
33768            const promiseType = createPromiseType(promisedType);
33769            if (promiseType === unknownType) {
33770                error(func, isImportCall(func) ?
33771                    Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
33772                    Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
33773                return errorType;
33774            }
33775            else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) {
33776                error(func, isImportCall(func) ?
33777                    Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option :
33778                    Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
33779            }
33780
33781            return promiseType;
33782        }
33783
33784        function createNewTargetExpressionType(targetType: Type): Type {
33785            // Create a synthetic type `NewTargetExpression { target: TargetType; }`
33786            const symbol = createSymbol(SymbolFlags.None, "NewTargetExpression" as __String);
33787
33788            const targetPropertySymbol = createSymbol(SymbolFlags.Property, "target" as __String, CheckFlags.Readonly);
33789            targetPropertySymbol.parent = symbol;
33790            targetPropertySymbol.type = targetType;
33791
33792            const members = createSymbolTable([targetPropertySymbol]);
33793            symbol.members = members;
33794            return createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray);
33795        }
33796
33797        function getReturnTypeFromBody(func: FunctionLikeDeclaration, checkMode?: CheckMode): Type {
33798            if (!func.body) {
33799                return errorType;
33800            }
33801
33802            const functionFlags = getFunctionFlags(func);
33803            const isAsync = (functionFlags & FunctionFlags.Async) !== 0;
33804            const isGenerator = (functionFlags & FunctionFlags.Generator) !== 0;
33805
33806            let returnType: Type | undefined;
33807            let yieldType: Type | undefined;
33808            let nextType: Type | undefined;
33809            let fallbackReturnType: Type = voidType;
33810            if (func.body.kind !== SyntaxKind.Block) { // Async or normal arrow function
33811                returnType = checkExpressionCached(func.body, checkMode && checkMode & ~CheckMode.SkipGenericFunctions);
33812                if (isAsync) {
33813                    // From within an async function you can return either a non-promise value or a promise. Any
33814                    // Promise/A+ compatible implementation will always assimilate any foreign promise, so the
33815                    // return type of the body should be unwrapped to its awaited type, which we will wrap in
33816                    // the native Promise<T> type later in this function.
33817                    returnType = unwrapAwaitedType(checkAwaitedType(returnType, /*withAlias*/ false, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member));
33818                }
33819            }
33820            else if (isGenerator) { // Generator or AsyncGenerator function
33821                const returnTypes = checkAndAggregateReturnExpressionTypes(func, checkMode);
33822                if (!returnTypes) {
33823                    fallbackReturnType = neverType;
33824                }
33825                else if (returnTypes.length > 0) {
33826                    returnType = getUnionType(returnTypes, UnionReduction.Subtype);
33827                }
33828                const { yieldTypes, nextTypes } = checkAndAggregateYieldOperandTypes(func, checkMode);
33829                yieldType = some(yieldTypes) ? getUnionType(yieldTypes, UnionReduction.Subtype) : undefined;
33830                nextType = some(nextTypes) ? getIntersectionType(nextTypes) : undefined;
33831            }
33832            else { // Async or normal function
33833                const types = checkAndAggregateReturnExpressionTypes(func, checkMode);
33834                if (!types) {
33835                    // For an async function, the return type will not be never, but rather a Promise for never.
33836                    return functionFlags & FunctionFlags.Async
33837                        ? createPromiseReturnType(func, neverType) // Async function
33838                        : neverType; // Normal function
33839                }
33840                if (types.length === 0) {
33841                    // For an async function, the return type will not be void, but rather a Promise for void.
33842                    return functionFlags & FunctionFlags.Async
33843                        ? createPromiseReturnType(func, voidType) // Async function
33844                        : voidType; // Normal function
33845                }
33846
33847                // Return a union of the return expression types.
33848                returnType = getUnionType(types, UnionReduction.Subtype);
33849            }
33850
33851            if (returnType || yieldType || nextType) {
33852                if (yieldType) reportErrorsFromWidening(func, yieldType, WideningKind.GeneratorYield);
33853                if (returnType) reportErrorsFromWidening(func, returnType, WideningKind.FunctionReturn);
33854                if (nextType) reportErrorsFromWidening(func, nextType, WideningKind.GeneratorNext);
33855                if (returnType && isUnitType(returnType) ||
33856                    yieldType && isUnitType(yieldType) ||
33857                    nextType && isUnitType(nextType)) {
33858                    const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
33859                    const contextualType = !contextualSignature ? undefined :
33860                        contextualSignature === getSignatureFromDeclaration(func) ? isGenerator ? undefined : returnType :
33861                        instantiateContextualType(getReturnTypeOfSignature(contextualSignature), func, /*contextFlags*/ undefined);
33862                    if (isGenerator) {
33863                        yieldType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(yieldType, contextualType, IterationTypeKind.Yield, isAsync);
33864                        returnType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(returnType, contextualType, IterationTypeKind.Return, isAsync);
33865                        nextType = getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(nextType, contextualType, IterationTypeKind.Next, isAsync);
33866                    }
33867                    else {
33868                        returnType = getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded(returnType, contextualType, isAsync);
33869                    }
33870                }
33871
33872                if (yieldType) yieldType = getWidenedType(yieldType);
33873                if (returnType) returnType = getWidenedType(returnType);
33874                if (nextType) nextType = getWidenedType(nextType);
33875            }
33876
33877            if (isGenerator) {
33878                return createGeneratorReturnType(
33879                    yieldType || neverType,
33880                    returnType || fallbackReturnType,
33881                    nextType || getContextualIterationType(IterationTypeKind.Next, func) || unknownType,
33882                    isAsync);
33883            }
33884            else {
33885                // From within an async function you can return either a non-promise value or a promise. Any
33886                // Promise/A+ compatible implementation will always assimilate any foreign promise, so the
33887                // return type of the body is awaited type of the body, wrapped in a native Promise<T> type.
33888                return isAsync
33889                    ? createPromiseType(returnType || fallbackReturnType)
33890                    : returnType || fallbackReturnType;
33891            }
33892        }
33893
33894        function createGeneratorReturnType(yieldType: Type, returnType: Type, nextType: Type, isAsyncGenerator: boolean) {
33895            const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver;
33896            const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false);
33897            yieldType = resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || unknownType;
33898            returnType = resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || unknownType;
33899            nextType = resolver.resolveIterationType(nextType, /*errorNode*/ undefined) || unknownType;
33900            if (globalGeneratorType === emptyGenericType) {
33901                // Fall back to the global IterableIterator if returnType is assignable to the expected return iteration
33902                // type of IterableIterator, and the expected next iteration type of IterableIterator is assignable to
33903                // nextType.
33904                const globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false);
33905                const iterationTypes = globalType !== emptyGenericType ? getIterationTypesOfGlobalIterableType(globalType, resolver) : undefined;
33906                const iterableIteratorReturnType = iterationTypes ? iterationTypes.returnType : anyType;
33907                const iterableIteratorNextType = iterationTypes ? iterationTypes.nextType : undefinedType;
33908                if (isTypeAssignableTo(returnType, iterableIteratorReturnType) &&
33909                    isTypeAssignableTo(iterableIteratorNextType, nextType)) {
33910                    if (globalType !== emptyGenericType) {
33911                        return createTypeFromGenericGlobalType(globalType, [yieldType]);
33912                    }
33913
33914                    // The global IterableIterator type doesn't exist, so report an error
33915                    resolver.getGlobalIterableIteratorType(/*reportErrors*/ true);
33916                    return emptyObjectType;
33917                }
33918
33919                // The global Generator type doesn't exist, so report an error
33920                resolver.getGlobalGeneratorType(/*reportErrors*/ true);
33921                return emptyObjectType;
33922            }
33923
33924            return createTypeFromGenericGlobalType(globalGeneratorType, [yieldType, returnType, nextType]);
33925        }
33926
33927        function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined) {
33928            const yieldTypes: Type[] = [];
33929            const nextTypes: Type[] = [];
33930            const isAsync = (getFunctionFlags(func) & FunctionFlags.Async) !== 0;
33931            forEachYieldExpression(func.body as Block, yieldExpression => {
33932                const yieldExpressionType = yieldExpression.expression ? checkExpression(yieldExpression.expression, checkMode) : undefinedWideningType;
33933                pushIfUnique(yieldTypes, getYieldedTypeOfYieldExpression(yieldExpression, yieldExpressionType, anyType, isAsync));
33934                let nextType: Type | undefined;
33935                if (yieldExpression.asteriskToken) {
33936                    const iterationTypes = getIterationTypesOfIterable(
33937                        yieldExpressionType,
33938                        isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar,
33939                        yieldExpression.expression);
33940                    nextType = iterationTypes && iterationTypes.nextType;
33941                }
33942                else {
33943                    nextType = getContextualType(yieldExpression, /*contextFlags*/ undefined);
33944                }
33945                if (nextType) pushIfUnique(nextTypes, nextType);
33946            });
33947            return { yieldTypes, nextTypes };
33948        }
33949
33950        function getYieldedTypeOfYieldExpression(node: YieldExpression, expressionType: Type, sentType: Type, isAsync: boolean): Type | undefined {
33951            const errorNode = node.expression || node;
33952            // A `yield*` expression effectively yields everything that its operand yields
33953            const yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar, expressionType, sentType, errorNode) : expressionType;
33954            return !isAsync ? yieldedType : getAwaitedType(yieldedType, errorNode, node.asteriskToken
33955                ? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member
33956                : Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
33957        }
33958
33959        // Return the combined not-equal type facts for all cases except those between the start and end indices.
33960        function getNotEqualFactsFromTypeofSwitch(start: number, end: number, witnesses: (string | undefined)[]): TypeFacts {
33961            let facts: TypeFacts = TypeFacts.None;
33962            for (let i = 0; i < witnesses.length; i++) {
33963                const witness = i < start || i >= end ? witnesses[i] : undefined;
33964                facts |= witness !== undefined ? typeofNEFacts.get(witness) || TypeFacts.TypeofNEHostObject : 0;
33965            }
33966            return facts;
33967        }
33968
33969        function isExhaustiveSwitchStatement(node: SwitchStatement): boolean {
33970            const links = getNodeLinks(node);
33971            if (links.isExhaustive === undefined) {
33972                links.isExhaustive = 0;  // Indicate resolution is in process
33973                const exhaustive = computeExhaustiveSwitchStatement(node);
33974                if (links.isExhaustive === 0) {
33975                    links.isExhaustive = exhaustive;
33976                }
33977            }
33978            else if (links.isExhaustive === 0) {
33979                links.isExhaustive = false;  // Resolve circularity to false
33980            }
33981            return links.isExhaustive;
33982        }
33983
33984        function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean {
33985            if (node.expression.kind === SyntaxKind.TypeOfExpression) {
33986                const witnesses = getSwitchClauseTypeOfWitnesses(node);
33987                if (!witnesses) {
33988                    return false;
33989                }
33990                const operandConstraint = getBaseConstraintOrType(checkExpressionCached((node.expression as TypeOfExpression).expression));
33991                // Get the not-equal flags for all handled cases.
33992                const notEqualFacts = getNotEqualFactsFromTypeofSwitch(0, 0, witnesses);
33993                if (operandConstraint.flags & TypeFlags.AnyOrUnknown) {
33994                    // We special case the top types to be exhaustive when all cases are handled.
33995                    return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE;
33996                }
33997                // A missing not-equal flag indicates that the type wasn't handled by some case.
33998                return !someType(operandConstraint, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts);
33999            }
34000            const type = checkExpressionCached(node.expression);
34001            if (!isLiteralType(type)) {
34002                return false;
34003            }
34004            const switchTypes = getSwitchClauseTypes(node);
34005            if (!switchTypes.length || some(switchTypes, isNeitherUnitTypeNorNever)) {
34006                return false;
34007            }
34008            return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes);
34009        }
34010
34011        function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
34012            return func.endFlowNode && isReachableFlowNode(func.endFlowNode);
34013        }
34014
34015        /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */
34016        function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined): Type[] | undefined {
34017            const functionFlags = getFunctionFlags(func);
34018            const aggregatedTypes: Type[] = [];
34019            let hasReturnWithNoExpression = functionHasImplicitReturn(func);
34020            let hasReturnOfTypeNever = false;
34021            forEachReturnStatement(func.body as Block, returnStatement => {
34022                const expr = returnStatement.expression;
34023                if (expr) {
34024                    let type = checkExpressionCached(expr, checkMode && checkMode & ~CheckMode.SkipGenericFunctions);
34025                    if (functionFlags & FunctionFlags.Async) {
34026                        // From within an async function you can return either a non-promise value or a promise. Any
34027                        // Promise/A+ compatible implementation will always assimilate any foreign promise, so the
34028                        // return type of the body should be unwrapped to its awaited type, which should be wrapped in
34029                        // the native Promise<T> type by the caller.
34030                        type = unwrapAwaitedType(checkAwaitedType(type, /*withAlias*/ false, func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member));
34031                    }
34032                    if (type.flags & TypeFlags.Never) {
34033                        hasReturnOfTypeNever = true;
34034                    }
34035                    pushIfUnique(aggregatedTypes, type);
34036                }
34037                else {
34038                    hasReturnWithNoExpression = true;
34039                }
34040            });
34041            if (aggregatedTypes.length === 0 && !hasReturnWithNoExpression && (hasReturnOfTypeNever || mayReturnNever(func))) {
34042                return undefined;
34043            }
34044            if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression &&
34045                !(isJSConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol))) {
34046                // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined
34047                pushIfUnique(aggregatedTypes, undefinedType);
34048            }
34049            return aggregatedTypes;
34050        }
34051        function mayReturnNever(func: FunctionLikeDeclaration): boolean {
34052            switch (func.kind) {
34053                case SyntaxKind.FunctionExpression:
34054                case SyntaxKind.ArrowFunction:
34055                    return true;
34056                case SyntaxKind.MethodDeclaration:
34057                    return func.parent.kind === SyntaxKind.ObjectLiteralExpression;
34058                default:
34059                    return false;
34060            }
34061        }
34062
34063        /**
34064         * TypeScript Specification 1.0 (6.3) - July 2014
34065         *   An explicitly typed function whose return type isn't the Void type,
34066         *   the Any type, or a union type containing the Void or Any type as a constituent
34067         *   must have at least one return statement somewhere in its body.
34068         *   An exception to this rule is if the function implementation consists of a single 'throw' statement.
34069         *
34070         * @param returnType - return type of the function, can be undefined if return type is not explicitly specified
34071         */
34072        function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration | MethodSignature, returnType: Type | undefined) {
34073            addLazyDiagnostic(checkAllCodePathsInNonVoidFunctionReturnOrThrowDiagnostics);
34074            return;
34075
34076            function checkAllCodePathsInNonVoidFunctionReturnOrThrowDiagnostics(): void {
34077                const functionFlags = getFunctionFlags(func);
34078                const type = returnType && unwrapReturnType(returnType, functionFlags);
34079
34080                // Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
34081                if (type && maybeTypeOfKind(type, TypeFlags.Any | TypeFlags.Void)) {
34082                    return;
34083                }
34084
34085                if (isFunctionDeclaration(func) && func.illegalDecorators && returnType) {
34086                    const extendNames = getEtsExtendDecoratorsComponentNames(func.illegalDecorators, compilerOptions);
34087                    if (extendNames.length !== 0) {
34088                        let returnTypeReferenceName;
34089                        compilerOptions.ets?.extend.components.forEach(({ name, type }) => {
34090                            if (name === last(extendNames)) {
34091                                returnTypeReferenceName = type;
34092                            }
34093                        });
34094                        if (returnType?.symbol?.escapedName === returnTypeReferenceName) {
34095                            return;
34096                        }
34097                        else {
34098                            error(getEffectiveReturnTypeNode(func), Diagnostics.Should_not_add_return_type_to_the_function_that_is_annotated_by_Extend);
34099                            return;
34100                        }
34101                    }
34102
34103                    const stylesNames = getEtsStylesDecoratorComponentNames(func.illegalDecorators, compilerOptions);
34104                    if (stylesNames.length > 0) {
34105                        return judgeReturnTypeOfStyles();
34106                    }
34107                }
34108
34109                if (isMethodDeclaration(func) && func.modifiers && func.modifiers.length && returnType) {
34110                    const stylesNames = getEtsStylesDecoratorComponentNames(func.modifiers as NodeArray<Decorator>, compilerOptions);
34111                    if (stylesNames.length > 0) {
34112                        return judgeReturnTypeOfStyles();
34113                    }
34114                }
34115
34116                // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
34117                // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
34118                if (func.kind === SyntaxKind.MethodSignature || nodeIsMissing(func.body) || func.body!.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func)) {
34119                    return;
34120                }
34121
34122                const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
34123                const errorNode = getEffectiveReturnTypeNode(func) || func;
34124
34125                if (type && type.flags & TypeFlags.Never) {
34126                    error(errorNode, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
34127                }
34128                else if (type && !hasExplicitReturn) {
34129                    // minimal check: function has syntactic return type annotation and no explicit return statements in the body
34130                    // this function does not conform to the specification.
34131                    error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
34132                }
34133                else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) {
34134                    error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined);
34135                }
34136                else if (compilerOptions.noImplicitReturns) {
34137                    if (!type) {
34138                        // If return type annotation is omitted check if function has any explicit return statements.
34139                        // If it does not have any - its inferred return type is void - don't do any checks.
34140                        // Otherwise get inferred return type from function body and report error only if it is not void / anytype
34141                        if (!hasExplicitReturn) {
34142                            return;
34143                        }
34144                        const inferredReturnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func));
34145                        if (isUnwrappedReturnTypeVoidOrAny(func, inferredReturnType)) {
34146                            return;
34147                        }
34148                    }
34149                    error(errorNode, Diagnostics.Not_all_code_paths_return_a_value);
34150                }
34151
34152                function judgeReturnTypeOfStyles(): void {
34153                    const returnTypeReferenceName = compilerOptions.ets?.styles.component.type;
34154                    if (returnType?.symbol?.escapedName === returnTypeReferenceName) {
34155                        return;
34156                    }
34157                    else {
34158                        error(getEffectiveReturnTypeNode(func), Diagnostics.Should_not_add_return_type_to_the_function_that_is_annotated_by_Styles);
34159                        return;
34160                    }
34161                }
34162            }
34163        }
34164
34165        function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode): Type {
34166            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
34167            checkNodeDeferred(node);
34168
34169            if (isFunctionExpression(node)) {
34170                checkCollisionsForDeclarationName(node, node.name);
34171            }
34172
34173            // The identityMapper object is used to indicate that function expressions are wildcards
34174            if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) {
34175                // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
34176                if (!getEffectiveReturnTypeNode(node) && !hasContextSensitiveParameters(node)) {
34177                    // Return plain anyFunctionType if there is no possibility we'll make inferences from the return type
34178                    const contextualSignature = getContextualSignature(node);
34179                    if (contextualSignature && couldContainTypeVariables(getReturnTypeOfSignature(contextualSignature))) {
34180                        const links = getNodeLinks(node);
34181                        if (links.contextFreeType) {
34182                            return links.contextFreeType;
34183                        }
34184                        const returnType = getReturnTypeFromBody(node, checkMode);
34185                        const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
34186                        const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, emptyArray);
34187                        returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType;
34188                        return links.contextFreeType = returnOnlyType;
34189                    }
34190                }
34191                return anyFunctionType;
34192            }
34193
34194            // Grammar checking
34195            const hasGrammarError = checkGrammarFunctionLikeDeclaration(node);
34196            if (!hasGrammarError && node.kind === SyntaxKind.FunctionExpression) {
34197                checkGrammarForGenerator(node);
34198            }
34199
34200            contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node, checkMode);
34201
34202            return getTypeOfSymbol(getSymbolOfNode(node));
34203        }
34204
34205        function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode) {
34206            const links = getNodeLinks(node);
34207            // Check if function expression is contextually typed and assign parameter types if so.
34208            if (!(links.flags & NodeCheckFlags.ContextChecked)) {
34209                const contextualSignature = getContextualSignature(node);
34210                // If a type check is started at a function expression that is an argument of a function call, obtaining the
34211                // contextual type may recursively get back to here during overload resolution of the call. If so, we will have
34212                // already assigned contextual types.
34213                if (!(links.flags & NodeCheckFlags.ContextChecked)) {
34214                    links.flags |= NodeCheckFlags.ContextChecked;
34215                    const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfNode(node)), SignatureKind.Call));
34216                    if (!signature) {
34217                        return;
34218                    }
34219                    if (isContextSensitive(node)) {
34220                        if (contextualSignature) {
34221                            const inferenceContext = getInferenceContext(node);
34222                            let instantiatedContextualSignature: Signature | undefined;
34223                            if (checkMode && checkMode & CheckMode.Inferential) {
34224                                inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!);
34225                                const restType = getEffectiveRestType(contextualSignature);
34226                                if (restType && restType.flags & TypeFlags.TypeParameter) {
34227                                    instantiatedContextualSignature = instantiateSignature(contextualSignature, inferenceContext!.nonFixingMapper);
34228                                }
34229                            }
34230                            instantiatedContextualSignature ||= inferenceContext ?
34231                                instantiateSignature(contextualSignature, inferenceContext.mapper) : contextualSignature;
34232                            assignContextualParameterTypes(signature, instantiatedContextualSignature);
34233                        }
34234                        else {
34235                            // Force resolution of all parameter types such that the absence of a contextual type is consistently reflected.
34236                            assignNonContextualParameterTypes(signature);
34237                        }
34238                    }
34239                    if (contextualSignature && !getReturnTypeFromAnnotation(node) && !signature.resolvedReturnType) {
34240                        const returnType = getReturnTypeFromBody(node, checkMode);
34241                        if (!signature.resolvedReturnType) {
34242                            signature.resolvedReturnType = returnType;
34243                        }
34244                    }
34245                    checkSignatureDeclaration(node);
34246                }
34247            }
34248        }
34249
34250        function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
34251            Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
34252
34253            const functionFlags = getFunctionFlags(node);
34254            const returnType = getReturnTypeFromAnnotation(node);
34255            checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType);
34256
34257            if (node.body) {
34258                if (!getEffectiveReturnTypeNode(node)) {
34259                    // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors
34260                    // we need. An example is the noImplicitAny errors resulting from widening the return expression
34261                    // of a function. Because checking of function expression bodies is deferred, there was never an
34262                    // appropriate time to do this during the main walk of the file (see the comment at the top of
34263                    // checkFunctionExpressionBodies). So it must be done now.
34264                    getReturnTypeOfSignature(getSignatureFromDeclaration(node));
34265                }
34266
34267                if (node.body.kind === SyntaxKind.Block) {
34268                    checkSourceElement(node.body);
34269                }
34270                else {
34271                    // From within an async function you can return either a non-promise value or a promise. Any
34272                    // Promise/A+ compatible implementation will always assimilate any foreign promise, so we
34273                    // should not be checking assignability of a promise to the return type. Instead, we need to
34274                    // check assignability of the awaited type of the expression body against the promised type of
34275                    // its return type annotation.
34276                    const exprType = checkExpression(node.body);
34277                    const returnOrPromisedType = returnType && unwrapReturnType(returnType, functionFlags);
34278                    if (returnOrPromisedType) {
34279                        if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function
34280                            const awaitedType = checkAwaitedType(exprType, /*withAlias*/ false, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
34281                            checkTypeAssignableToAndOptionallyElaborate(awaitedType, returnOrPromisedType, node.body, node.body);
34282                        }
34283                        else { // Normal function
34284                            checkTypeAssignableToAndOptionallyElaborate(exprType, returnOrPromisedType, node.body, node.body);
34285                        }
34286                    }
34287                }
34288            }
34289        }
34290
34291        function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage, isAwaitValid = false): boolean {
34292            if (!isTypeAssignableTo(type, numberOrBigIntType)) {
34293                const awaitedType = isAwaitValid && getAwaitedTypeOfPromise(type);
34294                errorAndMaybeSuggestAwait(
34295                    operand,
34296                    !!awaitedType && isTypeAssignableTo(awaitedType, numberOrBigIntType),
34297                    diagnostic);
34298                return false;
34299            }
34300            return true;
34301        }
34302
34303        function isReadonlyAssignmentDeclaration(d: Declaration) {
34304            if (!isCallExpression(d)) {
34305                return false;
34306            }
34307            if (!isBindableObjectDefinePropertyCall(d)) {
34308                return false;
34309            }
34310            const objectLitType = checkExpressionCached(d.arguments[2]);
34311            const valueType = getTypeOfPropertyOfType(objectLitType, "value" as __String);
34312            if (valueType) {
34313                const writableProp = getPropertyOfType(objectLitType, "writable" as __String);
34314                const writableType = writableProp && getTypeOfSymbol(writableProp);
34315                if (!writableType || writableType === falseType || writableType === regularFalseType) {
34316                    return true;
34317                }
34318                // We include this definition whereupon we walk back and check the type at the declaration because
34319                // The usual definition of `Object.defineProperty` will _not_ cause literal types to be preserved in the
34320                // argument types, should the type be contextualized by the call itself.
34321                if (writableProp && writableProp.valueDeclaration && isPropertyAssignment(writableProp.valueDeclaration)) {
34322                    const initializer = writableProp.valueDeclaration.initializer;
34323                    const rawOriginalType = checkExpression(initializer);
34324                    if (rawOriginalType === falseType || rawOriginalType === regularFalseType) {
34325                        return true;
34326                    }
34327                }
34328                return false;
34329            }
34330            const setProp = getPropertyOfType(objectLitType, "set" as __String);
34331            return !setProp;
34332        }
34333
34334        function isReadonlySymbol(symbol: Symbol): boolean {
34335            // The following symbols are considered read-only:
34336            // Properties with a 'readonly' modifier
34337            // Variables declared with 'const'
34338            // Get accessors without matching set accessors
34339            // Enum members
34340            // Object.defineProperty assignments with writable false or no setter
34341            // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation)
34342            return !!(getCheckFlags(symbol) & CheckFlags.Readonly ||
34343                symbol.flags & SymbolFlags.Property && getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly ||
34344                symbol.flags & SymbolFlags.Variable && getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const ||
34345                symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) ||
34346                symbol.flags & SymbolFlags.EnumMember ||
34347                some(symbol.declarations, isReadonlyAssignmentDeclaration)
34348            );
34349        }
34350
34351        function isAssignmentToReadonlyEntity(expr: Expression, symbol: Symbol, assignmentKind: AssignmentKind) {
34352            if (assignmentKind === AssignmentKind.None) {
34353                // no assigment means it doesn't matter whether the entity is readonly
34354                return false;
34355            }
34356            if (isReadonlySymbol(symbol)) {
34357                // Allow assignments to readonly properties within constructors of the same class declaration.
34358                if (symbol.flags & SymbolFlags.Property &&
34359                    isAccessExpression(expr) &&
34360                    expr.expression.kind === SyntaxKind.ThisKeyword) {
34361                    // Look for if this is the constructor for the class that `symbol` is a property of.
34362                    const ctor = getContainingFunction(expr);
34363                    if (!(ctor && (ctor.kind === SyntaxKind.Constructor || isJSConstructor(ctor)))) {
34364                        return true;
34365                    }
34366                    if (symbol.valueDeclaration) {
34367                        const isAssignmentDeclaration = isBinaryExpression(symbol.valueDeclaration);
34368                        const isLocalPropertyDeclaration = ctor.parent === symbol.valueDeclaration.parent;
34369                        const isLocalParameterProperty = ctor === symbol.valueDeclaration.parent;
34370                        const isLocalThisPropertyAssignment = isAssignmentDeclaration && symbol.parent?.valueDeclaration === ctor.parent;
34371                        const isLocalThisPropertyAssignmentConstructorFunction = isAssignmentDeclaration && symbol.parent?.valueDeclaration === ctor;
34372                        const isWriteableSymbol =
34373                            isLocalPropertyDeclaration
34374                            || isLocalParameterProperty
34375                            || isLocalThisPropertyAssignment
34376                            || isLocalThisPropertyAssignmentConstructorFunction;
34377                        return !isWriteableSymbol;
34378                    }
34379                }
34380                return true;
34381            }
34382            if (isAccessExpression(expr)) {
34383                // references through namespace import should be readonly
34384                const node = skipParentheses(expr.expression);
34385                if (node.kind === SyntaxKind.Identifier) {
34386                    const symbol = getNodeLinks(node).resolvedSymbol!;
34387                    if (symbol.flags & SymbolFlags.Alias) {
34388                        const declaration = getDeclarationOfAliasSymbol(symbol);
34389                        return !!declaration && declaration.kind === SyntaxKind.NamespaceImport;
34390                    }
34391                }
34392            }
34393            return false;
34394        }
34395
34396        function checkReferenceExpression(expr: Expression, invalidReferenceMessage: DiagnosticMessage, invalidOptionalChainMessage: DiagnosticMessage): boolean {
34397            // References are combinations of identifiers, parentheses, and property accesses.
34398            const node = skipOuterExpressions(expr, OuterExpressionKinds.Assertions | OuterExpressionKinds.Parentheses);
34399            if (node.kind !== SyntaxKind.Identifier && !isAccessExpression(node)) {
34400                error(expr, invalidReferenceMessage);
34401                return false;
34402            }
34403            if (node.flags & NodeFlags.OptionalChain) {
34404                error(expr, invalidOptionalChainMessage);
34405                return false;
34406            }
34407            return true;
34408        }
34409
34410        function checkDeleteExpression(node: DeleteExpression): Type {
34411            checkExpression(node.expression);
34412            const expr = skipParentheses(node.expression);
34413            if (!isAccessExpression(expr)) {
34414                error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference);
34415                return booleanType;
34416            }
34417            if (isPropertyAccessExpression(expr) && isPrivateIdentifier(expr.name)) {
34418                error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_identifier);
34419            }
34420            const links = getNodeLinks(expr);
34421            const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol);
34422            if (symbol) {
34423                if (isReadonlySymbol(symbol)) {
34424                    error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property);
34425                }
34426                checkDeleteExpressionMustBeOptional(expr, symbol);
34427            }
34428            return booleanType;
34429        }
34430
34431        function checkDeleteExpressionMustBeOptional(expr: AccessExpression, symbol: Symbol) {
34432            const type = getTypeOfSymbol(symbol);
34433            if (strictNullChecks &&
34434                !(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) &&
34435                !(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getTypeFacts(type) & TypeFacts.IsUndefined)) {
34436                error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional);
34437            }
34438        }
34439
34440        function checkTypeOfExpression(node: TypeOfExpression): Type {
34441            checkExpression(node.expression);
34442            return typeofType;
34443        }
34444
34445        function checkVoidExpression(node: VoidExpression): Type {
34446            checkExpression(node.expression);
34447            return undefinedWideningType;
34448        }
34449
34450        function checkAwaitExpressionGrammar(node: AwaitExpression): void {
34451            // Grammar checking
34452            const container = getContainingFunctionOrClassStaticBlock(node);
34453            if (container && isClassStaticBlockDeclaration(container)) {
34454                error(node, Diagnostics.Await_expression_cannot_be_used_inside_a_class_static_block);
34455            }
34456            else if (!(node.flags & NodeFlags.AwaitContext)) {
34457                if (isInTopLevelContext(node)) {
34458                    const sourceFile = getSourceFileOfNode(node);
34459                    if (!hasParseDiagnostics(sourceFile)) {
34460                        let span: TextSpan | undefined;
34461                        if (!isEffectiveExternalModule(sourceFile, compilerOptions)) {
34462                            span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
34463                            const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length,
34464                                Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module);
34465                            diagnostics.add(diagnostic);
34466                        }
34467                        switch (moduleKind) {
34468                            case ModuleKind.Node16:
34469                            case ModuleKind.NodeNext:
34470                                if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) {
34471                                    span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
34472                                    diagnostics.add(
34473                                        createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level)
34474                                    );
34475                                    break;
34476                                }
34477                                // fallthrough
34478                            case ModuleKind.ES2022:
34479                            case ModuleKind.ESNext:
34480                            case ModuleKind.System:
34481                                if (languageVersion >= ScriptTarget.ES2017) {
34482                                    break;
34483                                }
34484                                // fallthrough
34485                            default:
34486                                span ??= getSpanOfTokenAtPosition(sourceFile, node.pos);
34487                                diagnostics.add(
34488                                    createFileDiagnostic(sourceFile, span.start, span.length,
34489                                        Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher
34490                                    )
34491                                );
34492                                break;
34493                        }
34494                    }
34495                }
34496                else {
34497                    // use of 'await' in non-async function
34498                    const sourceFile = getSourceFileOfNode(node);
34499                    if (!hasParseDiagnostics(sourceFile)) {
34500                        const span = getSpanOfTokenAtPosition(sourceFile, node.pos);
34501                        const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules);
34502                        if (container && container.kind !== SyntaxKind.Constructor && (getFunctionFlags(container) & FunctionFlags.Async) === 0) {
34503                            const relatedInfo = createDiagnosticForNode(container, Diagnostics.Did_you_mean_to_mark_this_function_as_async);
34504                            addRelatedInfo(diagnostic, relatedInfo);
34505                        }
34506                        diagnostics.add(diagnostic);
34507                    }
34508                }
34509            }
34510
34511            if (isInParameterInitializerBeforeContainingFunction(node)) {
34512                error(node, Diagnostics.await_expressions_cannot_be_used_in_a_parameter_initializer);
34513            }
34514        }
34515
34516        function checkAwaitExpression(node: AwaitExpression): Type {
34517            addLazyDiagnostic(() => checkAwaitExpressionGrammar(node));
34518
34519            const operandType = checkExpression(node.expression);
34520            const awaitedType = checkAwaitedType(operandType, /*withAlias*/ true, node, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
34521            if (awaitedType === operandType && !isErrorType(awaitedType) && !(operandType.flags & TypeFlags.AnyOrUnknown)) {
34522                addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.await_has_no_effect_on_the_type_of_this_expression));
34523            }
34524            return awaitedType;
34525        }
34526
34527        function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
34528            const operandType = checkExpression(node.operand);
34529            if (operandType === silentNeverType) {
34530                return silentNeverType;
34531            }
34532            switch (node.operand.kind) {
34533                case SyntaxKind.NumericLiteral:
34534                    switch (node.operator) {
34535                        case SyntaxKind.MinusToken:
34536                            return getFreshTypeOfLiteralType(getNumberLiteralType(-(node.operand as NumericLiteral).text));
34537                        case SyntaxKind.PlusToken:
34538                            return getFreshTypeOfLiteralType(getNumberLiteralType(+(node.operand as NumericLiteral).text));
34539                    }
34540                    break;
34541                case SyntaxKind.BigIntLiteral:
34542                    if (node.operator === SyntaxKind.MinusToken) {
34543                        return getFreshTypeOfLiteralType(getBigIntLiteralType({
34544                            negative: true,
34545                            base10Value: parsePseudoBigInt((node.operand as BigIntLiteral).text)
34546                        }));
34547                    }
34548            }
34549            switch (node.operator) {
34550                case SyntaxKind.PlusToken:
34551                case SyntaxKind.MinusToken:
34552                case SyntaxKind.TildeToken:
34553                    checkNonNullType(operandType, node.operand);
34554                    if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.ESSymbolLike)) {
34555                        error(node.operand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(node.operator));
34556                    }
34557                    if (node.operator === SyntaxKind.PlusToken) {
34558                        if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.BigIntLike)) {
34559                            error(node.operand, Diagnostics.Operator_0_cannot_be_applied_to_type_1, tokenToString(node.operator), typeToString(getBaseTypeOfLiteralType(operandType)));
34560                        }
34561                        return numberType;
34562                    }
34563                    return getUnaryResultType(operandType);
34564                case SyntaxKind.ExclamationToken:
34565                    checkTruthinessExpression(node.operand);
34566                    const facts = getTypeFacts(operandType) & (TypeFacts.Truthy | TypeFacts.Falsy);
34567                    return facts === TypeFacts.Truthy ? falseType :
34568                        facts === TypeFacts.Falsy ? trueType :
34569                        booleanType;
34570                case SyntaxKind.PlusPlusToken:
34571                case SyntaxKind.MinusMinusToken:
34572                    const ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand),
34573                        Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type);
34574                    if (ok) {
34575                        // run check only if former checks succeeded to avoid reporting cascading errors
34576                        checkReferenceExpression(
34577                            node.operand,
34578                            Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access,
34579                            Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access);
34580                    }
34581                    return getUnaryResultType(operandType);
34582            }
34583        }
34584
34585        function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type {
34586            const operandType = checkExpression(node.operand);
34587            if (operandType === silentNeverType) {
34588                return silentNeverType;
34589            }
34590            const ok = checkArithmeticOperandType(
34591                node.operand,
34592                checkNonNullType(operandType, node.operand),
34593                Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type);
34594            if (ok) {
34595                // run check only if former checks succeeded to avoid reporting cascading errors
34596                checkReferenceExpression(
34597                    node.operand,
34598                    Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access,
34599                    Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access);
34600            }
34601            return getUnaryResultType(operandType);
34602        }
34603
34604        function getUnaryResultType(operandType: Type): Type {
34605            if (maybeTypeOfKind(operandType, TypeFlags.BigIntLike)) {
34606                return isTypeAssignableToKind(operandType, TypeFlags.AnyOrUnknown) || maybeTypeOfKind(operandType, TypeFlags.NumberLike)
34607                    ? numberOrBigIntType
34608                    : bigintType;
34609            }
34610            // If it's not a bigint type, implicit coercion will result in a number
34611            return numberType;
34612        }
34613
34614        function maybeTypeOfKindConsideringBaseConstraint(type: Type, kind: TypeFlags): boolean {
34615            if (maybeTypeOfKind(type, kind)) {
34616                return true;
34617            }
34618
34619            const baseConstraint = getBaseConstraintOrType(type);
34620            return !!baseConstraint && maybeTypeOfKind(baseConstraint, kind);
34621        }
34622
34623        // Return true if type might be of the given kind. A union or intersection type might be of a given
34624        // kind if at least one constituent type is of the given kind.
34625        function maybeTypeOfKind(type: Type, kind: TypeFlags): boolean {
34626            if (type.flags & kind) {
34627                return true;
34628            }
34629            if (type.flags & TypeFlags.UnionOrIntersection) {
34630                const types = (type as UnionOrIntersectionType).types;
34631                for (const t of types) {
34632                    if (maybeTypeOfKind(t, kind)) {
34633                        return true;
34634                    }
34635                }
34636            }
34637            return false;
34638        }
34639
34640        function isTypeAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean {
34641            if (source.flags & kind) {
34642                return true;
34643            }
34644            if (strict && source.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) {
34645                return false;
34646            }
34647            return !!(kind & TypeFlags.NumberLike) && isTypeAssignableTo(source, numberType) ||
34648                !!(kind & TypeFlags.BigIntLike) && isTypeAssignableTo(source, bigintType) ||
34649                !!(kind & TypeFlags.StringLike) && isTypeAssignableTo(source, stringType) ||
34650                !!(kind & TypeFlags.BooleanLike) && isTypeAssignableTo(source, booleanType) ||
34651                !!(kind & TypeFlags.Void) && isTypeAssignableTo(source, voidType) ||
34652                !!(kind & TypeFlags.Never) && isTypeAssignableTo(source, neverType) ||
34653                !!(kind & TypeFlags.Null) && isTypeAssignableTo(source, nullType) ||
34654                !!(kind & TypeFlags.Undefined) && isTypeAssignableTo(source, undefinedType) ||
34655                !!(kind & TypeFlags.ESSymbol) && isTypeAssignableTo(source, esSymbolType) ||
34656                !!(kind & TypeFlags.NonPrimitive) && isTypeAssignableTo(source, nonPrimitiveType);
34657        }
34658
34659        function allTypesAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean {
34660            return source.flags & TypeFlags.Union ?
34661                every((source as UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) :
34662                isTypeAssignableToKind(source, kind, strict);
34663        }
34664
34665        function isConstEnumObjectType(type: Type): boolean {
34666            return !!(getObjectFlags(type) & ObjectFlags.Anonymous) && !!type.symbol && isConstEnumSymbol(type.symbol);
34667        }
34668
34669        function isConstEnumSymbol(symbol: Symbol): boolean {
34670            return (symbol.flags & SymbolFlags.ConstEnum) !== 0;
34671        }
34672
34673        function checkInstanceOfExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type {
34674            if (leftType === silentNeverType || rightType === silentNeverType) {
34675                return silentNeverType;
34676            }
34677            // TypeScript 1.0 spec (April 2014): 4.15.4
34678            // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type,
34679            // and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
34680            // The result is always of the Boolean primitive type.
34681            // NOTE: do not raise error if leftType is unknown as related error was already reported
34682            if (!isTypeAny(leftType) &&
34683                allTypesAssignableToKind(leftType, TypeFlags.Primitive)) {
34684                error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
34685            }
34686            // NOTE: do not raise error if right is unknown as related error was already reported
34687            if (!(isTypeAny(rightType) || typeHasCallOrConstructSignatures(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) {
34688                error(right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
34689            }
34690            return booleanType;
34691        }
34692
34693        function hasEmptyObjectIntersection(type: Type): boolean {
34694            return someType(type, t => t === unknownEmptyObjectType || !!(t.flags & TypeFlags.Intersection) && some((t as IntersectionType).types, isEmptyAnonymousObjectType));
34695        }
34696
34697        function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type {
34698            if (leftType === silentNeverType || rightType === silentNeverType) {
34699                return silentNeverType;
34700            }
34701            if (isPrivateIdentifier(left)) {
34702                if (languageVersion < ScriptTarget.ESNext) {
34703                    checkExternalEmitHelpers(left, ExternalEmitHelpers.ClassPrivateFieldIn);
34704                }
34705                // Unlike in 'checkPrivateIdentifierExpression' we now have access to the RHS type
34706                // which provides us with the opportunity to emit more detailed errors
34707                if (!getNodeLinks(left).resolvedSymbol && getContainingClass(left)) {
34708                    const isUncheckedJS = isUncheckedJSSuggestion(left, rightType.symbol, /*excludeClasses*/ true);
34709                    reportNonexistentProperty(left, rightType, isUncheckedJS);
34710                }
34711            }
34712            else {
34713                // The type of the lef operand must be assignable to string, number, or symbol.
34714                checkTypeAssignableTo(checkNonNullType(leftType, left), stringNumberSymbolType, left);
34715            }
34716            // The type of the right operand must be assignable to 'object'.
34717            if (checkTypeAssignableTo(checkNonNullType(rightType, right), nonPrimitiveType, right)) {
34718                // The {} type is assignable to the object type, yet {} might represent a primitive type. Here we
34719                // detect and error on {} that results from narrowing the unknown type, as well as intersections
34720                // that include {} (we know that the other types in such intersections are assignable to object
34721                // since we already checked for that).
34722                if (hasEmptyObjectIntersection(rightType)) {
34723                    error(right, Diagnostics.Type_0_may_represent_a_primitive_value_which_is_not_permitted_as_the_right_operand_of_the_in_operator, typeToString(rightType));
34724                }
34725            }
34726            // The result is always of the Boolean primitive type.
34727            return booleanType;
34728        }
34729
34730        function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, rightIsThis?: boolean): Type {
34731            const properties = node.properties;
34732            if (strictNullChecks && properties.length === 0) {
34733                return checkNonNullType(sourceType, node);
34734            }
34735            for (let i = 0; i < properties.length; i++) {
34736                checkObjectLiteralDestructuringPropertyAssignment(node, sourceType, i, properties, rightIsThis);
34737            }
34738            return sourceType;
34739        }
34740
34741        /** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */
34742        function checkObjectLiteralDestructuringPropertyAssignment(node: ObjectLiteralExpression, objectLiteralType: Type, propertyIndex: number, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
34743            const properties = node.properties;
34744            const property = properties[propertyIndex];
34745            if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
34746                const name = property.name;
34747                const exprType = getLiteralTypeFromPropertyName(name);
34748                if (isTypeUsableAsPropertyName(exprType)) {
34749                    const text = getPropertyNameFromType(exprType);
34750                    const prop = getPropertyOfType(objectLiteralType, text);
34751                    if (prop) {
34752                        markPropertyAsReferenced(prop, property, rightIsThis);
34753                        checkPropertyAccessibility(property, /*isSuper*/ false, /*writing*/ true, objectLiteralType, prop);
34754                    }
34755                }
34756                const elementType = getIndexedAccessType(objectLiteralType, exprType, AccessFlags.ExpressionPosition, name);
34757                const type = getFlowTypeOfDestructuring(property, elementType);
34758                return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
34759            }
34760            else if (property.kind === SyntaxKind.SpreadAssignment) {
34761                if (propertyIndex < properties.length - 1) {
34762                    error(property, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
34763                }
34764                else {
34765                    if (languageVersion < ScriptTarget.ESNext) {
34766                        checkExternalEmitHelpers(property, ExternalEmitHelpers.Rest);
34767                    }
34768                    const nonRestNames: PropertyName[] = [];
34769                    if (allProperties) {
34770                        for (const otherProperty of allProperties) {
34771                            if (!isSpreadAssignment(otherProperty)) {
34772                                nonRestNames.push(otherProperty.name);
34773                            }
34774                        }
34775                    }
34776                    const type = getRestType(objectLiteralType, nonRestNames, objectLiteralType.symbol);
34777                    checkGrammarForDisallowedTrailingComma(allProperties, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
34778                    return checkDestructuringAssignment(property.expression, type);
34779                }
34780            }
34781            else {
34782                error(property, Diagnostics.Property_assignment_expected);
34783            }
34784        }
34785
34786        function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type {
34787            const elements = node.elements;
34788            if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
34789                checkExternalEmitHelpers(node, ExternalEmitHelpers.Read);
34790            }
34791            // This elementType will be used if the specific property corresponding to this index is not
34792            // present (aka the tuple element property). This call also checks that the parentType is in
34793            // fact an iterable or array (depending on target language).
34794            const possiblyOutOfBoundsType = checkIteratedTypeOrElementType(IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, sourceType, undefinedType, node) || errorType;
34795            let inBoundsType: Type | undefined = compilerOptions.noUncheckedIndexedAccess ? undefined: possiblyOutOfBoundsType;
34796            for (let i = 0; i < elements.length; i++) {
34797                let type = possiblyOutOfBoundsType;
34798                if (node.elements[i].kind === SyntaxKind.SpreadElement) {
34799                    type = inBoundsType = inBoundsType ?? (checkIteratedTypeOrElementType(IterationUse.Destructuring, sourceType, undefinedType, node) || errorType);
34800                }
34801                checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, type, checkMode);
34802            }
34803            return sourceType;
34804        }
34805
34806        function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type,
34807            elementIndex: number, elementType: Type, checkMode?: CheckMode) {
34808            const elements = node.elements;
34809            const element = elements[elementIndex];
34810            if (element.kind !== SyntaxKind.OmittedExpression) {
34811                if (element.kind !== SyntaxKind.SpreadElement) {
34812                    const indexType = getNumberLiteralType(elementIndex);
34813                    if (isArrayLikeType(sourceType)) {
34814                        // We create a synthetic expression so that getIndexedAccessType doesn't get confused
34815                        // when the element is a SyntaxKind.ElementAccessExpression.
34816                        const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0);
34817                        const elementType = getIndexedAccessTypeOrUndefined(sourceType, indexType, accessFlags, createSyntheticExpression(element, indexType)) || errorType;
34818                        const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) : elementType;
34819                        const type = getFlowTypeOfDestructuring(element, assignedType);
34820                        return checkDestructuringAssignment(element, type, checkMode);
34821                    }
34822                    return checkDestructuringAssignment(element, elementType, checkMode);
34823                }
34824                if (elementIndex < elements.length - 1) {
34825                    error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
34826                }
34827                else {
34828                    const restExpression = (element as SpreadElement).expression;
34829                    if (restExpression.kind === SyntaxKind.BinaryExpression && (restExpression as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
34830                        error((restExpression as BinaryExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
34831                    }
34832                    else {
34833                        checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
34834                        const type = everyType(sourceType, isTupleType) ?
34835                            mapType(sourceType, t => sliceTupleType(t as TupleTypeReference, elementIndex)) :
34836                            createArrayType(elementType);
34837                        return checkDestructuringAssignment(restExpression, type, checkMode);
34838                    }
34839                }
34840            }
34841            return undefined;
34842        }
34843
34844        function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode, rightIsThis?: boolean): Type {
34845            let target: Expression;
34846            if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) {
34847                const prop = exprOrAssignment as ShorthandPropertyAssignment;
34848                if (prop.objectAssignmentInitializer) {
34849                    // In strict null checking mode, if a default value of a non-undefined type is specified, remove
34850                    // undefined from the final type.
34851                    if (strictNullChecks &&
34852                        !(getTypeFacts(checkExpression(prop.objectAssignmentInitializer)) & TypeFacts.IsUndefined)) {
34853                        sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined);
34854                    }
34855                    checkBinaryLikeExpression(prop.name, prop.equalsToken!, prop.objectAssignmentInitializer, checkMode);
34856                }
34857                target = (exprOrAssignment as ShorthandPropertyAssignment).name;
34858            }
34859            else {
34860                target = exprOrAssignment;
34861            }
34862
34863            if (target.kind === SyntaxKind.BinaryExpression && (target as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
34864                checkBinaryExpression(target as BinaryExpression, checkMode);
34865                target = (target as BinaryExpression).left;
34866                // A default value is specified, so remove undefined from the final type.
34867                if (strictNullChecks) {
34868                    sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined);
34869                }
34870            }
34871            if (target.kind === SyntaxKind.ObjectLiteralExpression) {
34872                return checkObjectLiteralAssignment(target as ObjectLiteralExpression, sourceType, rightIsThis);
34873            }
34874            if (target.kind === SyntaxKind.ArrayLiteralExpression) {
34875                return checkArrayLiteralAssignment(target as ArrayLiteralExpression, sourceType, checkMode);
34876            }
34877            return checkReferenceAssignment(target, sourceType, checkMode);
34878        }
34879
34880        function checkReferenceAssignment(target: Expression, sourceType: Type, checkMode?: CheckMode): Type {
34881            const targetType = checkExpression(target, checkMode);
34882            const error = target.parent.kind === SyntaxKind.SpreadAssignment ?
34883                Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access :
34884                Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access;
34885            const optionalError = target.parent.kind === SyntaxKind.SpreadAssignment ?
34886                Diagnostics.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access :
34887                Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access;
34888            if (checkReferenceExpression(target, error, optionalError)) {
34889                checkTypeAssignableToAndOptionallyElaborate(sourceType, targetType, target, target);
34890            }
34891            if (isPrivateIdentifierPropertyAccessExpression(target)) {
34892                checkExternalEmitHelpers(target.parent, ExternalEmitHelpers.ClassPrivateFieldSet);
34893            }
34894            return sourceType;
34895        }
34896
34897        /**
34898         * This is a *shallow* check: An expression is side-effect-free if the
34899         * evaluation of the expression *itself* cannot produce side effects.
34900         * For example, x++ / 3 is side-effect free because the / operator
34901         * does not have side effects.
34902         * The intent is to "smell test" an expression for correctness in positions where
34903         * its value is discarded (e.g. the left side of the comma operator).
34904         */
34905        function isSideEffectFree(node: Node): boolean {
34906            node = skipParentheses(node);
34907            switch (node.kind) {
34908                case SyntaxKind.Identifier:
34909                case SyntaxKind.StringLiteral:
34910                case SyntaxKind.RegularExpressionLiteral:
34911                case SyntaxKind.TaggedTemplateExpression:
34912                case SyntaxKind.TemplateExpression:
34913                case SyntaxKind.NoSubstitutionTemplateLiteral:
34914                case SyntaxKind.NumericLiteral:
34915                case SyntaxKind.BigIntLiteral:
34916                case SyntaxKind.TrueKeyword:
34917                case SyntaxKind.FalseKeyword:
34918                case SyntaxKind.NullKeyword:
34919                case SyntaxKind.UndefinedKeyword:
34920                case SyntaxKind.FunctionExpression:
34921                case SyntaxKind.ClassExpression:
34922                case SyntaxKind.ArrowFunction:
34923                case SyntaxKind.ArrayLiteralExpression:
34924                case SyntaxKind.ObjectLiteralExpression:
34925                case SyntaxKind.TypeOfExpression:
34926                case SyntaxKind.NonNullExpression:
34927                case SyntaxKind.JsxSelfClosingElement:
34928                case SyntaxKind.JsxElement:
34929                    return true;
34930
34931                case SyntaxKind.ConditionalExpression:
34932                    return isSideEffectFree((node as ConditionalExpression).whenTrue) &&
34933                        isSideEffectFree((node as ConditionalExpression).whenFalse);
34934
34935                case SyntaxKind.BinaryExpression:
34936                    if (isAssignmentOperator((node as BinaryExpression).operatorToken.kind)) {
34937                        return false;
34938                    }
34939                    return isSideEffectFree((node as BinaryExpression).left) &&
34940                            isSideEffectFree((node as BinaryExpression).right);
34941
34942                case SyntaxKind.PrefixUnaryExpression:
34943                case SyntaxKind.PostfixUnaryExpression:
34944                    // Unary operators ~, !, +, and - have no side effects.
34945                    // The rest do.
34946                    switch ((node as PrefixUnaryExpression).operator) {
34947                        case SyntaxKind.ExclamationToken:
34948                        case SyntaxKind.PlusToken:
34949                        case SyntaxKind.MinusToken:
34950                        case SyntaxKind.TildeToken:
34951                            return true;
34952                    }
34953                    return false;
34954
34955                // Some forms listed here for clarity
34956                case SyntaxKind.VoidExpression: // Explicit opt-out
34957                case SyntaxKind.TypeAssertionExpression: // Not SEF, but can produce useful type warnings
34958                case SyntaxKind.AsExpression: // Not SEF, but can produce useful type warnings
34959                default:
34960                    return false;
34961            }
34962        }
34963
34964        function isTypeEqualityComparableTo(source: Type, target: Type) {
34965            return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target);
34966        }
34967
34968        function createCheckBinaryExpression() {
34969            interface WorkArea {
34970                readonly checkMode: CheckMode | undefined;
34971                skip: boolean;
34972                stackIndex: number;
34973                /**
34974                 * Holds the types from the left-side of an expression from [0..stackIndex].
34975                 * Holds the type of the result at stackIndex+1. This allows us to reuse existing stack entries
34976                 * and avoid storing an extra property on the object (i.e., `lastResult`).
34977                 */
34978                typeStack: (Type | undefined)[];
34979            }
34980
34981            const trampoline = createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, foldState);
34982
34983            return (node: BinaryExpression, checkMode: CheckMode | undefined) => {
34984                const result = trampoline(node, checkMode);
34985                Debug.assertIsDefined(result);
34986                return result;
34987            };
34988
34989            function onEnter(node: BinaryExpression, state: WorkArea | undefined, checkMode: CheckMode | undefined) {
34990                if (state) {
34991                    state.stackIndex++;
34992                    state.skip = false;
34993                    setLeftType(state, /*type*/ undefined);
34994                    setLastResult(state, /*type*/ undefined);
34995                }
34996                else {
34997                    state = {
34998                        checkMode,
34999                        skip: false,
35000                        stackIndex: 0,
35001                        typeStack: [undefined, undefined],
35002                    };
35003                }
35004
35005                if (isInJSFile(node) && getAssignedExpandoInitializer(node)) {
35006                    state.skip = true;
35007                    setLastResult(state, checkExpression(node.right, checkMode));
35008                    return state;
35009                }
35010
35011                checkGrammarNullishCoalesceWithLogicalExpression(node);
35012
35013                const operator = node.operatorToken.kind;
35014                if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
35015                    state.skip = true;
35016                    setLastResult(state, checkDestructuringAssignment(node.left, checkExpression(node.right, checkMode), checkMode, node.right.kind === SyntaxKind.ThisKeyword));
35017                    return state;
35018                }
35019
35020                return state;
35021            }
35022
35023            function onLeft(left: Expression, state: WorkArea, _node: BinaryExpression) {
35024                if (!state.skip) {
35025                    return maybeCheckExpression(state, left);
35026                }
35027            }
35028
35029            function onOperator(operatorToken: BinaryOperatorToken, state: WorkArea, node: BinaryExpression) {
35030                if (!state.skip) {
35031                    const leftType = getLastResult(state);
35032                    Debug.assertIsDefined(leftType);
35033                    setLeftType(state, leftType);
35034                    setLastResult(state, /*type*/ undefined);
35035                    const operator = operatorToken.kind;
35036                    if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
35037                        if (operator === SyntaxKind.AmpersandAmpersandToken) {
35038                            let parent = node.parent;
35039                            while (parent.kind === SyntaxKind.ParenthesizedExpression
35040                                || isBinaryExpression(parent) && (parent.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === SyntaxKind.BarBarToken)) {
35041                                parent = parent.parent;
35042                            }
35043                            checkTestingKnownTruthyCallableOrAwaitableType(node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined);
35044                        }
35045                        checkTruthinessOfType(leftType, node.left);
35046                    }
35047                }
35048            }
35049
35050            function onRight(right: Expression, state: WorkArea, _node: BinaryExpression) {
35051                if (!state.skip) {
35052                    return maybeCheckExpression(state, right);
35053                }
35054            }
35055
35056            function onExit(node: BinaryExpression, state: WorkArea): Type | undefined {
35057                let result: Type | undefined;
35058                if (state.skip) {
35059                    result = getLastResult(state);
35060                }
35061                else {
35062                    const leftType = getLeftType(state);
35063                    Debug.assertIsDefined(leftType);
35064
35065                    const rightType = getLastResult(state);
35066                    Debug.assertIsDefined(rightType);
35067
35068                    result = checkBinaryLikeExpressionWorker(node.left, node.operatorToken, node.right, leftType, rightType, node);
35069                }
35070
35071                state.skip = false;
35072                setLeftType(state, /*type*/ undefined);
35073                setLastResult(state, /*type*/ undefined);
35074                state.stackIndex--;
35075                return result;
35076            }
35077
35078            function foldState(state: WorkArea, result: Type | undefined, _side: "left" | "right") {
35079                setLastResult(state, result);
35080                return state;
35081            }
35082
35083            function maybeCheckExpression(state: WorkArea, node: Expression): BinaryExpression | undefined {
35084                if (isBinaryExpression(node)) {
35085                    return node;
35086                }
35087                setLastResult(state, checkExpression(node, state.checkMode));
35088            }
35089
35090            function getLeftType(state: WorkArea) {
35091                return state.typeStack[state.stackIndex];
35092            }
35093
35094            function setLeftType(state: WorkArea, type: Type | undefined) {
35095                state.typeStack[state.stackIndex] = type;
35096            }
35097
35098            function getLastResult(state: WorkArea) {
35099                return state.typeStack[state.stackIndex + 1];
35100            }
35101
35102            function setLastResult(state: WorkArea, type: Type | undefined) {
35103                // To reduce overhead, reuse the next stack entry to store the
35104                // last result. This avoids the overhead of an additional property
35105                // on `WorkArea` and reuses empty stack entries as we walk back up
35106                // the stack.
35107                state.typeStack[state.stackIndex + 1] = type;
35108            }
35109        }
35110
35111        function checkGrammarNullishCoalesceWithLogicalExpression(node: BinaryExpression) {
35112            const { left, operatorToken, right } = node;
35113            if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) {
35114                if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) {
35115                    grammarErrorOnNode(left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind));
35116                }
35117                if (isBinaryExpression(right) && (right.operatorToken.kind === SyntaxKind.BarBarToken || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) {
35118                    grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind));
35119                }
35120            }
35121        }
35122
35123        // Note that this and `checkBinaryExpression` above should behave mostly the same, except this elides some
35124        // expression-wide checks and does not use a work stack to fold nested binary expressions into the same callstack frame
35125        function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node): Type {
35126            const operator = operatorToken.kind;
35127            if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) {
35128                return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === SyntaxKind.ThisKeyword);
35129            }
35130            let leftType: Type;
35131            if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
35132                leftType = checkTruthinessExpression(left, checkMode);
35133            }
35134            else {
35135                leftType = checkExpression(left, checkMode);
35136            }
35137
35138            const rightType = checkExpression(right, checkMode);
35139            return checkBinaryLikeExpressionWorker(left, operatorToken, right, leftType, rightType, errorNode);
35140        }
35141
35142        function checkBinaryLikeExpressionWorker(
35143            left: Expression,
35144            operatorToken: Node,
35145            right: Expression,
35146            leftType: Type,
35147            rightType: Type,
35148            errorNode?: Node
35149        ): Type {
35150            const operator = operatorToken.kind;
35151            switch (operator) {
35152                case SyntaxKind.AsteriskToken:
35153                case SyntaxKind.AsteriskAsteriskToken:
35154                case SyntaxKind.AsteriskEqualsToken:
35155                case SyntaxKind.AsteriskAsteriskEqualsToken:
35156                case SyntaxKind.SlashToken:
35157                case SyntaxKind.SlashEqualsToken:
35158                case SyntaxKind.PercentToken:
35159                case SyntaxKind.PercentEqualsToken:
35160                case SyntaxKind.MinusToken:
35161                case SyntaxKind.MinusEqualsToken:
35162                case SyntaxKind.LessThanLessThanToken:
35163                case SyntaxKind.LessThanLessThanEqualsToken:
35164                case SyntaxKind.GreaterThanGreaterThanToken:
35165                case SyntaxKind.GreaterThanGreaterThanEqualsToken:
35166                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
35167                case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
35168                case SyntaxKind.BarToken:
35169                case SyntaxKind.BarEqualsToken:
35170                case SyntaxKind.CaretToken:
35171                case SyntaxKind.CaretEqualsToken:
35172                case SyntaxKind.AmpersandToken:
35173                case SyntaxKind.AmpersandEqualsToken:
35174                    if (leftType === silentNeverType || rightType === silentNeverType) {
35175                        return silentNeverType;
35176                    }
35177
35178                    leftType = checkNonNullType(leftType, left);
35179                    rightType = checkNonNullType(rightType, right);
35180
35181                    let suggestedOperator: SyntaxKind | undefined;
35182                    // if a user tries to apply a bitwise operator to 2 boolean operands
35183                    // try and return them a helpful suggestion
35184                    if ((leftType.flags & TypeFlags.BooleanLike) &&
35185                        (rightType.flags & TypeFlags.BooleanLike) &&
35186                        (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined) {
35187                        error(errorNode || operatorToken, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(operatorToken.kind), tokenToString(suggestedOperator));
35188                        return numberType;
35189                    }
35190                    else {
35191                        // otherwise just check each operand separately and report errors as normal
35192                        const leftOk = checkArithmeticOperandType(left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true);
35193                        const rightOk = checkArithmeticOperandType(right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true);
35194                        let resultType: Type;
35195                        // If both are any or unknown, allow operation; assume it will resolve to number
35196                        if ((isTypeAssignableToKind(leftType, TypeFlags.AnyOrUnknown) && isTypeAssignableToKind(rightType, TypeFlags.AnyOrUnknown)) ||
35197                            // Or, if neither could be bigint, implicit coercion results in a number result
35198                            !(maybeTypeOfKind(leftType, TypeFlags.BigIntLike) || maybeTypeOfKind(rightType, TypeFlags.BigIntLike))
35199                        ) {
35200                            resultType = numberType;
35201                        }
35202                        // At least one is assignable to bigint, so check that both are
35203                        else if (bothAreBigIntLike(leftType, rightType)) {
35204                            switch (operator) {
35205                                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
35206                                case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
35207                                    reportOperatorError();
35208                                    break;
35209                                case SyntaxKind.AsteriskAsteriskToken:
35210                                case SyntaxKind.AsteriskAsteriskEqualsToken:
35211                                    if (languageVersion < ScriptTarget.ES2016) {
35212                                        error(errorNode, Diagnostics.Exponentiation_cannot_be_performed_on_bigint_values_unless_the_target_option_is_set_to_es2016_or_later);
35213                                    }
35214                            }
35215                            resultType = bigintType;
35216                        }
35217                        // Exactly one of leftType/rightType is assignable to bigint
35218                        else {
35219                            reportOperatorError(bothAreBigIntLike);
35220                            resultType = errorType;
35221                        }
35222                        if (leftOk && rightOk) {
35223                            checkAssignmentOperator(resultType);
35224                        }
35225                        return resultType;
35226                    }
35227                case SyntaxKind.PlusToken:
35228                case SyntaxKind.PlusEqualsToken:
35229                    if (leftType === silentNeverType || rightType === silentNeverType) {
35230                        return silentNeverType;
35231                    }
35232
35233                    if (!isTypeAssignableToKind(leftType, TypeFlags.StringLike) && !isTypeAssignableToKind(rightType, TypeFlags.StringLike)) {
35234                        leftType = checkNonNullType(leftType, left);
35235                        rightType = checkNonNullType(rightType, right);
35236                    }
35237
35238                    let resultType: Type | undefined;
35239                    if (isTypeAssignableToKind(leftType, TypeFlags.NumberLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.NumberLike, /*strict*/ true)) {
35240                        // Operands of an enum type are treated as having the primitive type Number.
35241                        // If both operands are of the Number primitive type, the result is of the Number primitive type.
35242                        resultType = numberType;
35243                    }
35244                    else if (isTypeAssignableToKind(leftType, TypeFlags.BigIntLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.BigIntLike, /*strict*/ true)) {
35245                        // If both operands are of the BigInt primitive type, the result is of the BigInt primitive type.
35246                        resultType = bigintType;
35247                    }
35248                    else if (isTypeAssignableToKind(leftType, TypeFlags.StringLike, /*strict*/ true) || isTypeAssignableToKind(rightType, TypeFlags.StringLike, /*strict*/ true)) {
35249                        // If one or both operands are of the String primitive type, the result is of the String primitive type.
35250                        resultType = stringType;
35251                    }
35252                    else if (isTypeAny(leftType) || isTypeAny(rightType)) {
35253                        // Otherwise, the result is of type Any.
35254                        // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
35255                        resultType = isErrorType(leftType) || isErrorType(rightType) ? errorType : anyType;
35256                    }
35257
35258                    // Symbols are not allowed at all in arithmetic expressions
35259                    if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
35260                        return resultType;
35261                    }
35262
35263                    if (!resultType) {
35264                        // Types that have a reasonably good chance of being a valid operand type.
35265                        // If both types have an awaited type of one of these, we'll assume the user
35266                        // might be missing an await without doing an exhaustive check that inserting
35267                        // await(s) will actually be a completely valid binary expression.
35268                        const closeEnoughKind = TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.AnyOrUnknown;
35269                        reportOperatorError((left, right) =>
35270                            isTypeAssignableToKind(left, closeEnoughKind) &&
35271                            isTypeAssignableToKind(right, closeEnoughKind));
35272                        return anyType;
35273                    }
35274
35275                    if (operator === SyntaxKind.PlusEqualsToken) {
35276                        checkAssignmentOperator(resultType);
35277                    }
35278                    return resultType;
35279                case SyntaxKind.LessThanToken:
35280                case SyntaxKind.GreaterThanToken:
35281                case SyntaxKind.LessThanEqualsToken:
35282                case SyntaxKind.GreaterThanEqualsToken:
35283                    if (checkForDisallowedESSymbolOperand(operator)) {
35284                        leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left));
35285                        rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right));
35286                        reportOperatorErrorUnless((left, right) =>
35287                            isTypeComparableTo(left, right) || isTypeComparableTo(right, left) || (
35288                                isTypeAssignableTo(left, numberOrBigIntType) && isTypeAssignableTo(right, numberOrBigIntType)));
35289                    }
35290                    return booleanType;
35291                case SyntaxKind.EqualsEqualsToken:
35292                case SyntaxKind.ExclamationEqualsToken:
35293                case SyntaxKind.EqualsEqualsEqualsToken:
35294                case SyntaxKind.ExclamationEqualsEqualsToken:
35295                    if (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) {
35296                        const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
35297                        error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true");
35298                    }
35299                    checkNaNEquality(errorNode, operator, left, right);
35300                    reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left));
35301                    return booleanType;
35302
35303                case SyntaxKind.InstanceOfKeyword:
35304                    return checkInstanceOfExpression(left, right, leftType, rightType);
35305                case SyntaxKind.InKeyword:
35306                    return checkInExpression(left, right, leftType, rightType);
35307                case SyntaxKind.AmpersandAmpersandToken:
35308                case SyntaxKind.AmpersandAmpersandEqualsToken: {
35309                    const resultType = getTypeFacts(leftType) & TypeFacts.Truthy ?
35310                        getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) :
35311                        leftType;
35312                    if (operator === SyntaxKind.AmpersandAmpersandEqualsToken) {
35313                        checkAssignmentOperator(rightType);
35314                    }
35315                    return resultType;
35316                }
35317                case SyntaxKind.BarBarToken:
35318                case SyntaxKind.BarBarEqualsToken: {
35319                    const resultType = getTypeFacts(leftType) & TypeFacts.Falsy ?
35320                        getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], UnionReduction.Subtype) :
35321                        leftType;
35322                    if (operator === SyntaxKind.BarBarEqualsToken) {
35323                        checkAssignmentOperator(rightType);
35324                    }
35325                    return resultType;
35326                }
35327                case SyntaxKind.QuestionQuestionToken:
35328                case SyntaxKind.QuestionQuestionEqualsToken: {
35329                    const resultType = getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ?
35330                        getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) :
35331                        leftType;
35332                    if (operator === SyntaxKind.QuestionQuestionEqualsToken) {
35333                        checkAssignmentOperator(rightType);
35334                    }
35335                    return resultType;
35336                }
35337                case SyntaxKind.EqualsToken:
35338                    const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) : AssignmentDeclarationKind.None;
35339                    checkAssignmentDeclaration(declKind, rightType);
35340                    if (isAssignmentDeclaration(declKind)) {
35341                        if (!(rightType.flags & TypeFlags.Object) ||
35342                            declKind !== AssignmentDeclarationKind.ModuleExports &&
35343                            declKind !== AssignmentDeclarationKind.Prototype &&
35344                            !isEmptyObjectType(rightType) &&
35345                            !isFunctionObjectType(rightType as ObjectType) &&
35346                            !(getObjectFlags(rightType) & ObjectFlags.Class)) {
35347                            // don't check assignability of module.exports=, C.prototype=, or expando types because they will necessarily be incomplete
35348                            checkAssignmentOperator(rightType);
35349                        }
35350                        return leftType;
35351                    }
35352                    else {
35353                        checkAssignmentOperator(rightType);
35354                        return getRegularTypeOfObjectLiteral(rightType);
35355                    }
35356                case SyntaxKind.CommaToken:
35357                    if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) {
35358                        const sf = getSourceFileOfNode(left);
35359                        const sourceText = sf.text;
35360                        const start = skipTrivia(sourceText, left.pos);
35361                        const isInDiag2657 = sf.parseDiagnostics.some(diag => {
35362                            if (diag.code !== Diagnostics.JSX_expressions_must_have_one_parent_element.code) return false;
35363                            return textSpanContainsPosition(diag, start);
35364                        });
35365                        if (!isInDiag2657) error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects);
35366                    }
35367                    return rightType;
35368
35369                default:
35370                    return Debug.fail();
35371            }
35372
35373            function bothAreBigIntLike(left: Type, right: Type): boolean {
35374                return isTypeAssignableToKind(left, TypeFlags.BigIntLike) && isTypeAssignableToKind(right, TypeFlags.BigIntLike);
35375            }
35376
35377            function checkAssignmentDeclaration(kind: AssignmentDeclarationKind, rightType: Type) {
35378                if (kind === AssignmentDeclarationKind.ModuleExports) {
35379                    for (const prop of getPropertiesOfObjectType(rightType)) {
35380                        const propType = getTypeOfSymbol(prop);
35381                        if (propType.symbol && propType.symbol.flags & SymbolFlags.Class) {
35382                            const name = prop.escapedName;
35383                            const symbol = resolveName(prop.valueDeclaration, name, SymbolFlags.Type, undefined, name, /*isUse*/ false);
35384                            if (symbol?.declarations && symbol.declarations.some(isJSDocTypedefTag)) {
35385                                addDuplicateDeclarationErrorsForSymbols(symbol, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name), prop);
35386                                addDuplicateDeclarationErrorsForSymbols(prop, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name), symbol);
35387                            }
35388                        }
35389                    }
35390                }
35391            }
35392
35393            function isEvalNode(node: Expression) {
35394                return node.kind === SyntaxKind.Identifier && (node as Identifier).escapedText === "eval";
35395            }
35396
35397            // Return true if there was no error, false if there was an error.
35398            function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean {
35399                const offendingSymbolOperand =
35400                    maybeTypeOfKindConsideringBaseConstraint(leftType, TypeFlags.ESSymbolLike) ? left :
35401                    maybeTypeOfKindConsideringBaseConstraint(rightType, TypeFlags.ESSymbolLike) ? right :
35402                    undefined;
35403
35404                if (offendingSymbolOperand) {
35405                    error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator));
35406                    return false;
35407                }
35408
35409                return true;
35410            }
35411
35412            function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind | undefined {
35413                switch (operator) {
35414                    case SyntaxKind.BarToken:
35415                    case SyntaxKind.BarEqualsToken:
35416                        return SyntaxKind.BarBarToken;
35417                    case SyntaxKind.CaretToken:
35418                    case SyntaxKind.CaretEqualsToken:
35419                        return SyntaxKind.ExclamationEqualsEqualsToken;
35420                    case SyntaxKind.AmpersandToken:
35421                    case SyntaxKind.AmpersandEqualsToken:
35422                        return SyntaxKind.AmpersandAmpersandToken;
35423                    default:
35424                        return undefined;
35425                }
35426            }
35427
35428            function checkAssignmentOperator(valueType: Type): void {
35429                if (isAssignmentOperator(operator)) {
35430                    addLazyDiagnostic(checkAssignmentOperatorWorker);
35431                }
35432
35433                function checkAssignmentOperatorWorker() {
35434                    // TypeScript 1.0 spec (April 2014): 4.17
35435                    // An assignment of the form
35436                    //    VarExpr = ValueExpr
35437                    // requires VarExpr to be classified as a reference
35438                    // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1)
35439                    // and the type of the non-compound operation to be assignable to the type of VarExpr.
35440
35441                    if (checkReferenceExpression(left,
35442                        Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access,
35443                        Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access)
35444                        && (!isIdentifier(left) || unescapeLeadingUnderscores(left.escapedText) !== "exports")) {
35445
35446                        let headMessage: DiagnosticMessage | undefined;
35447                        if (exactOptionalPropertyTypes && isPropertyAccessExpression(left) && maybeTypeOfKind(valueType, TypeFlags.Undefined)) {
35448                            const target = getTypeOfPropertyOfType(getTypeOfExpression(left.expression), left.name.escapedText);
35449                            if (isExactOptionalPropertyMismatch(valueType, target)) {
35450                                headMessage = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target;
35451                            }
35452                        }
35453                        // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
35454                        checkTypeAssignableToAndOptionallyElaborate(valueType, leftType, left, right, headMessage);
35455                    }
35456                }
35457            }
35458
35459            function isAssignmentDeclaration(kind: AssignmentDeclarationKind) {
35460                switch (kind) {
35461                    case AssignmentDeclarationKind.ModuleExports:
35462                        return true;
35463                    case AssignmentDeclarationKind.ExportsProperty:
35464                    case AssignmentDeclarationKind.Property:
35465                    case AssignmentDeclarationKind.Prototype:
35466                    case AssignmentDeclarationKind.PrototypeProperty:
35467                    case AssignmentDeclarationKind.ThisProperty:
35468                        const symbol = getSymbolOfNode(left);
35469                        const init = getAssignedExpandoInitializer(right);
35470                        return !!init && isObjectLiteralExpression(init) &&
35471                            !!symbol?.exports?.size;
35472                    default:
35473                        return false;
35474                }
35475            }
35476
35477            /**
35478             * Returns true if an error is reported
35479             */
35480            function reportOperatorErrorUnless(typesAreCompatible: (left: Type, right: Type) => boolean): boolean {
35481                if (!typesAreCompatible(leftType, rightType)) {
35482                    reportOperatorError(typesAreCompatible);
35483                    return true;
35484                }
35485                return false;
35486            }
35487
35488            function reportOperatorError(isRelated?: (left: Type, right: Type) => boolean) {
35489                let wouldWorkWithAwait = false;
35490                const errNode = errorNode || operatorToken;
35491                if (isRelated) {
35492                    const awaitedLeftType = getAwaitedTypeNoAlias(leftType);
35493                    const awaitedRightType = getAwaitedTypeNoAlias(rightType);
35494                    wouldWorkWithAwait = !(awaitedLeftType === leftType && awaitedRightType === rightType)
35495                        && !!(awaitedLeftType && awaitedRightType)
35496                        && isRelated(awaitedLeftType, awaitedRightType);
35497                }
35498
35499                let effectiveLeft = leftType;
35500                let effectiveRight = rightType;
35501                if (!wouldWorkWithAwait && isRelated) {
35502                    [effectiveLeft, effectiveRight] = getBaseTypesIfUnrelated(leftType, rightType, isRelated);
35503                }
35504                const [leftStr, rightStr] = getTypeNamesForErrorDisplay(effectiveLeft, effectiveRight);
35505                if (!tryGiveBetterPrimaryError(errNode, wouldWorkWithAwait, leftStr, rightStr)) {
35506                    errorAndMaybeSuggestAwait(
35507                        errNode,
35508                        wouldWorkWithAwait,
35509                        Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2,
35510                        tokenToString(operatorToken.kind),
35511                        leftStr,
35512                        rightStr,
35513                    );
35514                }
35515            }
35516
35517            function tryGiveBetterPrimaryError(errNode: Node, maybeMissingAwait: boolean, leftStr: string, rightStr: string) {
35518                switch (operatorToken.kind) {
35519                    case SyntaxKind.EqualsEqualsEqualsToken:
35520                    case SyntaxKind.EqualsEqualsToken:
35521                    case SyntaxKind.ExclamationEqualsEqualsToken:
35522                    case SyntaxKind.ExclamationEqualsToken:
35523                        return errorAndMaybeSuggestAwait(
35524                            errNode,
35525                            maybeMissingAwait,
35526                            Diagnostics.This_comparison_appears_to_be_unintentional_because_the_types_0_and_1_have_no_overlap,
35527                            leftStr, rightStr);
35528                    default:
35529                        return undefined;
35530                }
35531            }
35532
35533            function checkNaNEquality(errorNode: Node | undefined, operator: SyntaxKind, left: Expression, right: Expression) {
35534                const isLeftNaN = isGlobalNaN(skipParentheses(left));
35535                const isRightNaN = isGlobalNaN(skipParentheses(right));
35536                if (isLeftNaN || isRightNaN) {
35537                    const err = error(errorNode, Diagnostics.This_condition_will_always_return_0,
35538                        tokenToString(operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.EqualsEqualsToken ? SyntaxKind.FalseKeyword : SyntaxKind.TrueKeyword));
35539                    if (isLeftNaN && isRightNaN) return;
35540                    const operatorString = operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) : "";
35541                    const location = isLeftNaN ? right : left;
35542                    const expression = skipParentheses(location);
35543                    addRelatedInfo(err, createDiagnosticForNode(location, Diagnostics.Did_you_mean_0,
35544                        `${operatorString}Number.isNaN(${isEntityNameExpression(expression) ? entityNameToString(expression) : "..."})`));
35545                }
35546            }
35547
35548            function isGlobalNaN(expr: Expression): boolean {
35549                if (isIdentifier(expr) && expr.escapedText === "NaN") {
35550                    const globalNaNSymbol = getGlobalNaNSymbol();
35551                    return !!globalNaNSymbol && globalNaNSymbol === getResolvedSymbol(expr);
35552                }
35553                return false;
35554            }
35555        }
35556
35557        function getBaseTypesIfUnrelated(leftType: Type, rightType: Type, isRelated: (left: Type, right: Type) => boolean): [Type, Type] {
35558            let effectiveLeft = leftType;
35559            let effectiveRight = rightType;
35560            const leftBase = getBaseTypeOfLiteralType(leftType);
35561            const rightBase = getBaseTypeOfLiteralType(rightType);
35562            if (!isRelated(leftBase, rightBase)) {
35563                effectiveLeft = leftBase;
35564                effectiveRight = rightBase;
35565            }
35566            return [ effectiveLeft, effectiveRight ];
35567        }
35568
35569        function checkYieldExpression(node: YieldExpression): Type {
35570            addLazyDiagnostic(checkYieldExpressionGrammar);
35571
35572            const func = getContainingFunction(node);
35573            if (!func) return anyType;
35574            const functionFlags = getFunctionFlags(func);
35575
35576            if (!(functionFlags & FunctionFlags.Generator)) {
35577                // If the user's code is syntactically correct, the func should always have a star. After all, we are in a yield context.
35578                return anyType;
35579            }
35580
35581            const isAsync = (functionFlags & FunctionFlags.Async) !== 0;
35582            if (node.asteriskToken) {
35583                // Async generator functions prior to ESNext require the __await, __asyncDelegator,
35584                // and __asyncValues helpers
35585                if (isAsync && languageVersion < ScriptTarget.ESNext) {
35586                    checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegatorIncludes);
35587                }
35588
35589                // Generator functions prior to ES2015 require the __values helper
35590                if (!isAsync && languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
35591                    checkExternalEmitHelpers(node, ExternalEmitHelpers.Values);
35592                }
35593            }
35594
35595            // There is no point in doing an assignability check if the function
35596            // has no explicit return type because the return type is directly computed
35597            // from the yield expressions.
35598            const returnType = getReturnTypeFromAnnotation(func);
35599            const iterationTypes = returnType && getIterationTypesOfGeneratorFunctionReturnType(returnType, isAsync);
35600            const signatureYieldType = iterationTypes && iterationTypes.yieldType || anyType;
35601            const signatureNextType = iterationTypes && iterationTypes.nextType || anyType;
35602            const resolvedSignatureNextType = isAsync ? getAwaitedType(signatureNextType) || anyType : signatureNextType;
35603            const yieldExpressionType = node.expression ? checkExpression(node.expression) : undefinedWideningType;
35604            const yieldedType = getYieldedTypeOfYieldExpression(node, yieldExpressionType, resolvedSignatureNextType, isAsync);
35605            if (returnType && yieldedType) {
35606                checkTypeAssignableToAndOptionallyElaborate(yieldedType, signatureYieldType, node.expression || node, node.expression);
35607            }
35608
35609            if (node.asteriskToken) {
35610                const use = isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar;
35611                return getIterationTypeOfIterable(use, IterationTypeKind.Return, yieldExpressionType, node.expression)
35612                    || anyType;
35613            }
35614            else if (returnType) {
35615                return getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, isAsync)
35616                    || anyType;
35617            }
35618            let type = getContextualIterationType(IterationTypeKind.Next, func);
35619            if (!type) {
35620                type = anyType;
35621                addLazyDiagnostic(() => {
35622                    if (noImplicitAny && !expressionResultIsUnused(node)) {
35623                        const contextualType = getContextualType(node, /*contextFlags*/ undefined);
35624                        if (!contextualType || isTypeAny(contextualType)) {
35625                            error(node, Diagnostics.yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_type_annotation);
35626                        }
35627                    }
35628                });
35629            }
35630            return type;
35631
35632            function checkYieldExpressionGrammar() {
35633                if (!(node.flags & NodeFlags.YieldContext)) {
35634                    grammarErrorOnFirstToken(node, Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body);
35635                }
35636
35637                if (isInParameterInitializerBeforeContainingFunction(node)) {
35638                    error(node, Diagnostics.yield_expressions_cannot_be_used_in_a_parameter_initializer);
35639                }
35640            }
35641        }
35642
35643        function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
35644            const type = checkTruthinessExpression(node.condition);
35645            checkTestingKnownTruthyCallableOrAwaitableType(node.condition, type, node.whenTrue);
35646            const type1 = checkExpression(node.whenTrue, checkMode);
35647            const type2 = checkExpression(node.whenFalse, checkMode);
35648            return getUnionType([type1, type2], UnionReduction.Subtype);
35649        }
35650
35651        function isTemplateLiteralContext(node: Node): boolean {
35652            const parent = node.parent;
35653            return isParenthesizedExpression(parent) && isTemplateLiteralContext(parent) ||
35654                isElementAccessExpression(parent) && parent.argumentExpression === node;
35655        }
35656
35657        function checkTemplateExpression(node: TemplateExpression): Type {
35658            const texts = [node.head.text];
35659            const types = [];
35660            for (const span of node.templateSpans) {
35661                const type = checkExpression(span.expression);
35662                if (maybeTypeOfKindConsideringBaseConstraint(type, TypeFlags.ESSymbolLike)) {
35663                    error(span.expression, Diagnostics.Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String);
35664                }
35665                texts.push(span.literal.text);
35666                types.push(isTypeAssignableTo(type, templateConstraintType) ? type : stringType);
35667            }
35668            return isConstContext(node) || isTemplateLiteralContext(node) || someType(getContextualType(node, /*contextFlags*/ undefined) || unknownType, isTemplateLiteralContextualType) ? getTemplateLiteralType(texts, types) : stringType;
35669        }
35670
35671        function isTemplateLiteralContextualType(type: Type): boolean {
35672            return !!(type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral) ||
35673                type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.StringLike));
35674        }
35675
35676        function getContextNode(node: Expression): Node {
35677            if (node.kind === SyntaxKind.JsxAttributes && !isJsxSelfClosingElement(node.parent)) {
35678                return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes)
35679            }
35680            return node;
35681        }
35682
35683        function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type {
35684            const context = getContextNode(node);
35685            const saveContextualType = context.contextualType;
35686            const saveInferenceContext = context.inferenceContext;
35687            try {
35688                context.contextualType = contextualType;
35689                context.inferenceContext = inferenceContext;
35690                const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0));
35691                // In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type
35692                // parameters. This information is no longer needed after the call to checkExpression.
35693                if (inferenceContext && inferenceContext.intraExpressionInferenceSites) {
35694                    inferenceContext.intraExpressionInferenceSites = undefined;
35695                }
35696                // We strip literal freshness when an appropriate contextual type is present such that contextually typed
35697                // literals always preserve their literal types (otherwise they might widen during type inference). An alternative
35698                // here would be to not mark contextually typed literals as fresh in the first place.
35699                const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node, /*contextFlags*/ undefined)) ?
35700                    getRegularTypeOfLiteralType(type) : type;
35701                return result;
35702            }
35703            finally {
35704                // In the event our operation is canceled or some other exception occurs, reset the contextual type
35705                // so that we do not accidentally hold onto an instance of the checker, as a Type created in the services layer
35706                // may hold onto the checker that created it.
35707                context.contextualType = saveContextualType;
35708                context.inferenceContext = saveInferenceContext;
35709            }
35710        }
35711
35712        function checkExpressionCached(node: Expression | QualifiedName, checkMode?: CheckMode): Type {
35713            if (checkMode && checkMode !== CheckMode.Normal) {
35714                return checkExpression(node, checkMode);
35715            }
35716            const links = getNodeLinks(node);
35717            if (!links.resolvedType) {
35718                // When computing a type that we're going to cache, we need to ignore any ongoing control flow
35719                // analysis because variables may have transient types in indeterminable states. Moving flowLoopStart
35720                // to the top of the stack ensures all transient types are computed from a known point.
35721                const saveFlowLoopStart = flowLoopStart;
35722                const saveFlowTypeCache = flowTypeCache;
35723                flowLoopStart = flowLoopCount;
35724                flowTypeCache = undefined;
35725                links.resolvedType = checkExpression(node, checkMode);
35726                flowTypeCache = saveFlowTypeCache;
35727                flowLoopStart = saveFlowLoopStart;
35728            }
35729            return links.resolvedType;
35730        }
35731
35732        function isTypeAssertion(node: Expression) {
35733            node = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
35734            return node.kind === SyntaxKind.TypeAssertionExpression ||
35735                node.kind === SyntaxKind.AsExpression ||
35736                isJSDocTypeAssertion(node);
35737        }
35738
35739        function checkDeclarationInitializer(
35740            declaration: HasExpressionInitializer,
35741            checkMode: CheckMode,
35742            contextualType?: Type | undefined
35743        ) {
35744            const initializer = getEffectiveInitializer(declaration)!;
35745            const type = getQuickTypeOfExpression(initializer) ||
35746                (contextualType ?
35747                    checkExpressionWithContextualType(initializer, contextualType, /*inferenceContext*/ undefined, checkMode || CheckMode.Normal)
35748                    : checkExpressionCached(initializer, checkMode));
35749            return isParameter(declaration) && declaration.name.kind === SyntaxKind.ArrayBindingPattern &&
35750                isTupleType(type) && !type.target.hasRestElement && getTypeReferenceArity(type) < declaration.name.elements.length ?
35751                padTupleType(type, declaration.name) : type;
35752        }
35753
35754        function padTupleType(type: TupleTypeReference, pattern: ArrayBindingPattern) {
35755            const patternElements = pattern.elements;
35756            const elementTypes = getTypeArguments(type).slice();
35757            const elementFlags = type.target.elementFlags.slice();
35758            for (let i = getTypeReferenceArity(type); i < patternElements.length; i++) {
35759                const e = patternElements[i];
35760                if (i < patternElements.length - 1 || !(e.kind === SyntaxKind.BindingElement && e.dotDotDotToken)) {
35761                    elementTypes.push(!isOmittedExpression(e) && hasDefaultValue(e) ? getTypeFromBindingElement(e, /*includePatternInType*/ false, /*reportErrors*/ false) : anyType);
35762                    elementFlags.push(ElementFlags.Optional);
35763                    if (!isOmittedExpression(e) && !hasDefaultValue(e)) {
35764                        reportImplicitAny(e, anyType);
35765                    }
35766                }
35767            }
35768            return createTupleType(elementTypes, elementFlags, type.target.readonly);
35769        }
35770
35771        function widenTypeInferredFromInitializer(declaration: HasExpressionInitializer, type: Type) {
35772            const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const || isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type);
35773            if (isInJSFile(declaration)) {
35774                if (isEmptyLiteralType(widened)) {
35775                    reportImplicitAny(declaration, anyType);
35776                    return anyType;
35777                }
35778                else if (isEmptyArrayLiteralType(widened)) {
35779                    reportImplicitAny(declaration, anyArrayType);
35780                    return anyArrayType;
35781                }
35782            }
35783            return widened;
35784        }
35785
35786        function isLiteralOfContextualType(candidateType: Type, contextualType: Type | undefined): boolean {
35787            if (contextualType) {
35788                if (contextualType.flags & TypeFlags.UnionOrIntersection) {
35789                    const types = (contextualType as UnionType).types;
35790                    return some(types, t => isLiteralOfContextualType(candidateType, t));
35791                }
35792                if (contextualType.flags & TypeFlags.InstantiableNonPrimitive) {
35793                    // If the contextual type is a type variable constrained to a primitive type, consider
35794                    // this a literal context for literals of that primitive type. For example, given a
35795                    // type parameter 'T extends string', infer string literal types for T.
35796                    const constraint = getBaseConstraintOfType(contextualType) || unknownType;
35797                    return maybeTypeOfKind(constraint, TypeFlags.String) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) ||
35798                        maybeTypeOfKind(constraint, TypeFlags.Number) && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) ||
35799                        maybeTypeOfKind(constraint, TypeFlags.BigInt) && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) ||
35800                        maybeTypeOfKind(constraint, TypeFlags.ESSymbol) && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol) ||
35801                        isLiteralOfContextualType(candidateType, constraint);
35802                }
35803                // If the contextual type is a literal of a particular primitive type, we consider this a
35804                // literal context for all literals of that primitive type.
35805                return !!(contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) ||
35806                    contextualType.flags & TypeFlags.NumberLiteral && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) ||
35807                    contextualType.flags & TypeFlags.BigIntLiteral && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) ||
35808                    contextualType.flags & TypeFlags.BooleanLiteral && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) ||
35809                    contextualType.flags & TypeFlags.UniqueESSymbol && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol));
35810            }
35811            return false;
35812        }
35813
35814        function isConstContext(node: Expression): boolean {
35815            const parent = node.parent;
35816            return isAssertionExpression(parent) && isConstTypeReference(parent.type) ||
35817                isJSDocTypeAssertion(parent) && isConstTypeReference(getJSDocTypeAssertionType(parent)) ||
35818                (isParenthesizedExpression(parent) || isArrayLiteralExpression(parent) || isSpreadElement(parent)) && isConstContext(parent) ||
35819                (isPropertyAssignment(parent) || isShorthandPropertyAssignment(parent) || isTemplateSpan(parent)) && isConstContext(parent.parent);
35820        }
35821
35822        function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type, forceTuple?: boolean): Type {
35823            const type = checkExpression(node, checkMode, forceTuple);
35824            return isConstContext(node) || isCommonJsExportedExpression(node) ? getRegularTypeOfLiteralType(type) :
35825                isTypeAssertion(node) ? type :
35826                getWidenedLiteralLikeTypeForContextualType(type, instantiateContextualType(arguments.length === 2 ? getContextualType(node, /*contextFlags*/ undefined) : contextualType, node, /*contextFlags*/ undefined));
35827        }
35828
35829        function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {
35830            // Do not use hasDynamicName here, because that returns false for well known symbols.
35831            // We want to perform checkComputedPropertyName for all computed properties, including
35832            // well known symbols.
35833            if (node.name.kind === SyntaxKind.ComputedPropertyName) {
35834                checkComputedPropertyName(node.name);
35835            }
35836
35837            return checkExpressionForMutableLocation(node.initializer, checkMode);
35838        }
35839
35840        function checkObjectLiteralMethod(node: MethodDeclaration, checkMode?: CheckMode): Type {
35841            // Grammar checking
35842            checkGrammarMethod(node);
35843
35844            // Do not use hasDynamicName here, because that returns false for well known symbols.
35845            // We want to perform checkComputedPropertyName for all computed properties, including
35846            // well known symbols.
35847            if (node.name.kind === SyntaxKind.ComputedPropertyName) {
35848                checkComputedPropertyName(node.name);
35849            }
35850
35851            const uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, checkMode);
35852            return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
35853        }
35854
35855        function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) {
35856            if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) {
35857                const callSignature = getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ true);
35858                const constructSignature = getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ true);
35859                const signature = callSignature || constructSignature;
35860                if (signature && signature.typeParameters) {
35861                    const contextualType = getApparentTypeOfContextualType(node as Expression, ContextFlags.NoConstraints);
35862                    if (contextualType) {
35863                        const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembers*/ false);
35864                        if (contextualSignature && !contextualSignature.typeParameters) {
35865                            if (checkMode & CheckMode.SkipGenericFunctions) {
35866                                skippedGenericFunction(node, checkMode);
35867                                return anyFunctionType;
35868                            }
35869                            const context = getInferenceContext(node)!;
35870                            // We have an expression that is an argument of a generic function for which we are performing
35871                            // type argument inference. The expression is of a function type with a single generic call
35872                            // signature and a contextual function type with a single non-generic call signature. Now check
35873                            // if the outer function returns a function type with a single non-generic call signature and
35874                            // if some of the outer function type parameters have no inferences so far. If so, we can
35875                            // potentially add inferred type parameters to the outer function return type.
35876                            const returnType = context.signature && getReturnTypeOfSignature(context.signature);
35877                            const returnSignature = returnType && getSingleCallOrConstructSignature(returnType);
35878                            if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) {
35879                                // Instantiate the signature with its own type parameters as type arguments, possibly
35880                                // renaming the type parameters to ensure they have unique names.
35881                                const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters);
35882                                const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters);
35883                                // Infer from the parameters of the instantiated signature to the parameters of the
35884                                // contextual signature starting with an empty set of inference candidates.
35885                                const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter));
35886                                applyToParameterTypes(instantiatedSignature, contextualSignature, (source, target) => {
35887                                    inferTypes(inferences, source, target, /*priority*/ 0, /*contravariant*/ true);
35888                                });
35889                                if (some(inferences, hasInferenceCandidates)) {
35890                                    // We have inference candidates, indicating that one or more type parameters are referenced
35891                                    // in the parameter types of the contextual signature. Now also infer from the return type.
35892                                    applyToReturnTypes(instantiatedSignature, contextualSignature, (source, target) => {
35893                                        inferTypes(inferences, source, target);
35894                                    });
35895                                    // If the type parameters for which we produced candidates do not have any inferences yet,
35896                                    // we adopt the new inference candidates and add the type parameters of the expression type
35897                                    // to the set of inferred type parameters for the outer function return type.
35898                                    if (!hasOverlappingInferences(context.inferences, inferences)) {
35899                                        mergeInferences(context.inferences, inferences);
35900                                        context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters);
35901                                        return getOrCreateTypeFromSignature(instantiatedSignature);
35902                                    }
35903                                }
35904                            }
35905                            return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, context));
35906                        }
35907                    }
35908                }
35909            }
35910            return type;
35911        }
35912
35913        function skippedGenericFunction(node: Node, checkMode: CheckMode) {
35914            if (checkMode & CheckMode.Inferential) {
35915                // We have skipped a generic function during inferential typing. Obtain the inference context and
35916                // indicate this has occurred such that we know a second pass of inference is be needed.
35917                const context = getInferenceContext(node)!;
35918                context.flags |= InferenceFlags.SkippedGenericFunction;
35919            }
35920        }
35921
35922        function hasInferenceCandidates(info: InferenceInfo) {
35923            return !!(info.candidates || info.contraCandidates);
35924        }
35925
35926        function hasInferenceCandidatesOrDefault(info: InferenceInfo) {
35927            return !!(info.candidates || info.contraCandidates || hasTypeParameterDefault(info.typeParameter));
35928        }
35929
35930        function hasOverlappingInferences(a: InferenceInfo[], b: InferenceInfo[]) {
35931            for (let i = 0; i < a.length; i++) {
35932                if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) {
35933                    return true;
35934                }
35935            }
35936            return false;
35937        }
35938
35939        function mergeInferences(target: InferenceInfo[], source: InferenceInfo[]) {
35940            for (let i = 0; i < target.length; i++) {
35941                if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) {
35942                    target[i] = source[i];
35943                }
35944            }
35945        }
35946
35947        function getUniqueTypeParameters(context: InferenceContext, typeParameters: readonly TypeParameter[]): readonly TypeParameter[] {
35948            const result: TypeParameter[] = [];
35949            let oldTypeParameters: TypeParameter[] | undefined;
35950            let newTypeParameters: TypeParameter[] | undefined;
35951            for (const tp of typeParameters) {
35952                const name = tp.symbol.escapedName;
35953                if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) {
35954                    const newName = getUniqueTypeParameterName(concatenate(context.inferredTypeParameters, result), name);
35955                    const symbol = createSymbol(SymbolFlags.TypeParameter, newName);
35956                    const newTypeParameter = createTypeParameter(symbol);
35957                    newTypeParameter.target = tp;
35958                    oldTypeParameters = append(oldTypeParameters, tp);
35959                    newTypeParameters = append(newTypeParameters, newTypeParameter);
35960                    result.push(newTypeParameter);
35961                }
35962                else {
35963                    result.push(tp);
35964                }
35965            }
35966            if (newTypeParameters) {
35967                const mapper = createTypeMapper(oldTypeParameters!, newTypeParameters);
35968                for (const tp of newTypeParameters) {
35969                    tp.mapper = mapper;
35970                }
35971            }
35972            return result;
35973        }
35974
35975        function hasTypeParameterByName(typeParameters: readonly TypeParameter[] | undefined, name: __String) {
35976            return some(typeParameters, tp => tp.symbol.escapedName === name);
35977        }
35978
35979        function getUniqueTypeParameterName(typeParameters: readonly TypeParameter[], baseName: __String) {
35980            let len = (baseName as string).length;
35981            while (len > 1 && (baseName as string).charCodeAt(len - 1) >= CharacterCodes._0 && (baseName as string).charCodeAt(len - 1) <= CharacterCodes._9) len--;
35982            const s = (baseName as string).slice(0, len);
35983            for (let index = 1; true; index++) {
35984                const augmentedName = (s + index as __String);
35985                if (!hasTypeParameterByName(typeParameters, augmentedName)) {
35986                    return augmentedName;
35987                }
35988            }
35989        }
35990
35991        function getReturnTypeOfSingleNonGenericCallSignature(funcType: Type) {
35992            const signature = getSingleCallSignature(funcType);
35993            if (signature && !signature.typeParameters) {
35994                return getReturnTypeOfSignature(signature);
35995            }
35996        }
35997
35998        function getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr: CallChain) {
35999            const funcType = checkExpression(expr.expression);
36000            const nonOptionalType = getOptionalExpressionType(funcType, expr.expression);
36001            const returnType = getReturnTypeOfSingleNonGenericCallSignature(funcType);
36002            return returnType && propagateOptionalTypeMarker(returnType, expr, nonOptionalType !== funcType);
36003        }
36004
36005        /**
36006         * Returns the type of an expression. Unlike checkExpression, this function is simply concerned
36007         * with computing the type and may not fully check all contained sub-expressions for errors.
36008         */
36009        function getTypeOfExpression(node: Expression, checkMode?: CheckMode) {
36010            // Don't bother caching types that require no flow analysis and are quick to compute.
36011            const quickType = getQuickTypeOfExpression(node);
36012            if (quickType) {
36013                return quickType;
36014            }
36015            // If a type has been cached for the node, return it.
36016            if (node.flags & NodeFlags.TypeCached && flowTypeCache) {
36017                const cachedType = flowTypeCache[getNodeId(node)];
36018                if (cachedType) {
36019                    return cachedType;
36020                }
36021            }
36022            const startInvocationCount = flowInvocationCount;
36023            const type = checkExpression(node, checkMode);
36024            // If control flow analysis was required to determine the type, it is worth caching.
36025            if (flowInvocationCount !== startInvocationCount) {
36026                const cache = flowTypeCache || (flowTypeCache = []);
36027                cache[getNodeId(node)] = type;
36028                setNodeFlags(node, node.flags | NodeFlags.TypeCached);
36029            }
36030            return type;
36031        }
36032
36033        function getQuickTypeOfExpression(node: Expression) {
36034            let expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true);
36035            if (isJSDocTypeAssertion(expr)) {
36036                const type = getJSDocTypeAssertionType(expr);
36037                if (!isConstTypeReference(type)) {
36038                    return getTypeFromTypeNode(type);
36039                }
36040            }
36041            expr = skipParentheses(node);
36042            // Optimize for the common case of a call to a function with a single non-generic call
36043            // signature where we can just fetch the return type without checking the arguments.
36044            if (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) {
36045                const type = isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) :
36046                    getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression, CheckMode.SkipEtsComponentBody));
36047                if (type) {
36048                    return type;
36049                }
36050            }
36051            else if (isEtsComponentExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) {
36052                const type = isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) :
36053                    getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression, CheckMode.SkipEtsComponentBody));
36054                if (type) {
36055                    return type;
36056                }
36057            }
36058            else if (isAssertionExpression(expr) && !isConstTypeReference(expr.type)) {
36059                return getTypeFromTypeNode((expr as TypeAssertion).type);
36060            }
36061            else if (node.kind === SyntaxKind.NumericLiteral || node.kind === SyntaxKind.StringLiteral ||
36062                node.kind === SyntaxKind.TrueKeyword || node.kind === SyntaxKind.FalseKeyword) {
36063                return checkExpression(node);
36064            }
36065            return undefined;
36066        }
36067
36068        /**
36069         * Returns the type of an expression. Unlike checkExpression, this function is simply concerned
36070         * with computing the type and may not fully check all contained sub-expressions for errors.
36071         * It is intended for uses where you know there is no contextual type,
36072         * and requesting the contextual type might cause a circularity or other bad behaviour.
36073         * It sets the contextual type of the node to any before calling getTypeOfExpression.
36074         */
36075        function getContextFreeTypeOfExpression(node: Expression) {
36076            const links = getNodeLinks(node);
36077            if (links.contextFreeType) {
36078                return links.contextFreeType;
36079            }
36080            const saveContextualType = node.contextualType;
36081            node.contextualType = anyType;
36082            try {
36083                const type = links.contextFreeType = checkExpression(node, CheckMode.SkipContextSensitive);
36084                return type;
36085            }
36086            finally {
36087                // In the event our operation is canceled or some other exception occurs, reset the contextual type
36088                // so that we do not accidentally hold onto an instance of the checker, as a Type created in the services layer
36089                // may hold onto the checker that created it.
36090                node.contextualType = saveContextualType;
36091            }
36092        }
36093
36094        function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type {
36095            tracing?.push(tracing.Phase.Check, "checkExpression", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath });
36096            const saveCurrentNode = currentNode;
36097            currentNode = node;
36098            instantiationCount = 0;
36099            const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple);
36100            const type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode);
36101            if (isConstEnumObjectType(type)) {
36102                checkConstEnumAccess(node, type);
36103            }
36104            currentNode = saveCurrentNode;
36105            tracing?.pop();
36106            return type;
36107        }
36108
36109        function checkConstEnumAccess(node: Expression | QualifiedName, type: Type) {
36110            // enum object type for const enums are only permitted in:
36111            // - 'left' in property access
36112            // - 'object' in indexed access
36113            // - target in rhs of import statement
36114            const ok =
36115                (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent as PropertyAccessExpression).expression === node) ||
36116                (node.parent.kind === SyntaxKind.ElementAccessExpression && (node.parent as ElementAccessExpression).expression === node) ||
36117                ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(node as Identifier) ||
36118                    (node.parent.kind === SyntaxKind.TypeQuery && (node.parent as TypeQueryNode).exprName === node)) ||
36119                (node.parent.kind === SyntaxKind.ExportSpecifier); // We allow reexporting const enums
36120
36121            if (!ok) {
36122                error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query);
36123            }
36124
36125            if (compilerOptions.isolatedModules) {
36126                Debug.assert(!!(type.symbol.flags & SymbolFlags.ConstEnum));
36127                const constEnumDeclaration = type.symbol.valueDeclaration as EnumDeclaration;
36128                if (constEnumDeclaration.flags & NodeFlags.Ambient) {
36129                    error(node, Diagnostics.Cannot_access_ambient_const_enums_when_the_isolatedModules_flag_is_provided);
36130                }
36131            }
36132        }
36133
36134        function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {
36135            if (hasJSDocNodes(node) && isJSDocTypeAssertion(node)) {
36136                const type = getJSDocTypeAssertionType(node);
36137                return checkAssertionWorker(type, type, node.expression, checkMode);
36138            }
36139            return checkExpression(node.expression, checkMode);
36140        }
36141
36142        function checkExpressionWorker(node: Expression | QualifiedName, checkMode: CheckMode | undefined, forceTuple?: boolean): Type {
36143            const kind = node.kind;
36144            if (cancellationToken) {
36145                // Only bother checking on a few construct kinds.  We don't want to be excessively
36146                // hitting the cancellation token on every node we check.
36147                switch (kind) {
36148                    case SyntaxKind.ClassExpression:
36149                    case SyntaxKind.FunctionExpression:
36150                    case SyntaxKind.ArrowFunction:
36151                        cancellationToken.throwIfCancellationRequested();
36152                }
36153            }
36154            switch (kind) {
36155                case SyntaxKind.Identifier:
36156                    return checkIdentifier(node as Identifier, checkMode);
36157                case SyntaxKind.PrivateIdentifier:
36158                    return checkPrivateIdentifierExpression(node as PrivateIdentifier);
36159                case SyntaxKind.ThisKeyword:
36160                    return checkThisExpression(node);
36161                case SyntaxKind.SuperKeyword:
36162                    return checkSuperExpression(node);
36163                case SyntaxKind.NullKeyword:
36164                    return nullWideningType;
36165                case SyntaxKind.NoSubstitutionTemplateLiteral:
36166                case SyntaxKind.StringLiteral:
36167                    return getFreshTypeOfLiteralType(getStringLiteralType((node as StringLiteralLike).text));
36168                case SyntaxKind.NumericLiteral:
36169                    checkGrammarNumericLiteral(node as NumericLiteral);
36170                    return getFreshTypeOfLiteralType(getNumberLiteralType(+(node as NumericLiteral).text));
36171                case SyntaxKind.BigIntLiteral:
36172                    checkGrammarBigIntLiteral(node as BigIntLiteral);
36173                    return getFreshTypeOfLiteralType(getBigIntLiteralType({
36174                        negative: false,
36175                        base10Value: parsePseudoBigInt((node as BigIntLiteral).text)
36176                    }));
36177                case SyntaxKind.TrueKeyword:
36178                    return trueType;
36179                case SyntaxKind.FalseKeyword:
36180                    return falseType;
36181                case SyntaxKind.TemplateExpression:
36182                    return checkTemplateExpression(node as TemplateExpression);
36183                case SyntaxKind.RegularExpressionLiteral:
36184                    return globalRegExpType;
36185                case SyntaxKind.ArrayLiteralExpression:
36186                    return checkArrayLiteral(node as ArrayLiteralExpression, checkMode, forceTuple);
36187                case SyntaxKind.ObjectLiteralExpression:
36188                    return checkObjectLiteral(node as ObjectLiteralExpression, checkMode);
36189                case SyntaxKind.PropertyAccessExpression:
36190                    return checkPropertyAccessExpression(node as PropertyAccessExpression, checkMode);
36191                case SyntaxKind.QualifiedName:
36192                    return checkQualifiedName(node as QualifiedName, checkMode);
36193                case SyntaxKind.ElementAccessExpression:
36194                    return checkIndexedAccess(node as ElementAccessExpression, checkMode);
36195                case SyntaxKind.CallExpression:
36196                    if ((node as CallExpression).expression.kind === SyntaxKind.ImportKeyword) {
36197                        return checkImportCallExpression(node as ImportCall);
36198                    }
36199                    // falls through
36200                case SyntaxKind.NewExpression:
36201                    return checkCallExpression(node as CallExpression, checkMode);
36202                case SyntaxKind.EtsComponentExpression:
36203                    const newNode = <EtsComponentExpression>node;
36204                    if (newNode.body && newNode.body.statements.length) {
36205                        traverseEtsComponentStatements(newNode.body.statements, checkMode);
36206                    }
36207                    return checkCallExpression(node as EtsComponentExpression, checkMode);
36208                case SyntaxKind.TaggedTemplateExpression:
36209                    return checkTaggedTemplateExpression(node as TaggedTemplateExpression);
36210                case SyntaxKind.ParenthesizedExpression:
36211                    return checkParenthesizedExpression(node as ParenthesizedExpression, checkMode);
36212                case SyntaxKind.ClassExpression:
36213                    return checkClassExpression(node as ClassExpression);
36214                case SyntaxKind.FunctionExpression:
36215                case SyntaxKind.ArrowFunction:
36216                    return checkFunctionExpressionOrObjectLiteralMethod(node as FunctionExpression | ArrowFunction, checkMode);
36217                case SyntaxKind.TypeOfExpression:
36218                    return checkTypeOfExpression(node as TypeOfExpression);
36219                case SyntaxKind.TypeAssertionExpression:
36220                case SyntaxKind.AsExpression:
36221                    return checkAssertion(node as AssertionExpression);
36222                case SyntaxKind.NonNullExpression:
36223                    return checkNonNullAssertion(node as NonNullExpression);
36224                case SyntaxKind.ExpressionWithTypeArguments:
36225                    return checkExpressionWithTypeArguments(node as ExpressionWithTypeArguments);
36226                case SyntaxKind.SatisfiesExpression:
36227                    return checkSatisfiesExpression(node as SatisfiesExpression);
36228                case SyntaxKind.MetaProperty:
36229                    return checkMetaProperty(node as MetaProperty);
36230                case SyntaxKind.DeleteExpression:
36231                    return checkDeleteExpression(node as DeleteExpression);
36232                case SyntaxKind.VoidExpression:
36233                    return checkVoidExpression(node as VoidExpression);
36234                case SyntaxKind.AwaitExpression:
36235                    return checkAwaitExpression(node as AwaitExpression);
36236                case SyntaxKind.PrefixUnaryExpression:
36237                    return checkPrefixUnaryExpression(node as PrefixUnaryExpression);
36238                case SyntaxKind.PostfixUnaryExpression:
36239                    return checkPostfixUnaryExpression(node as PostfixUnaryExpression);
36240                case SyntaxKind.BinaryExpression:
36241                    return checkBinaryExpression(node as BinaryExpression, checkMode);
36242                case SyntaxKind.ConditionalExpression:
36243                    return checkConditionalExpression(node as ConditionalExpression, checkMode);
36244                case SyntaxKind.SpreadElement:
36245                    return checkSpreadExpression(node as SpreadElement, checkMode);
36246                case SyntaxKind.OmittedExpression:
36247                    return undefinedWideningType;
36248                case SyntaxKind.YieldExpression:
36249                    return checkYieldExpression(node as YieldExpression);
36250                case SyntaxKind.SyntheticExpression:
36251                    return checkSyntheticExpression(node as SyntheticExpression);
36252                case SyntaxKind.JsxExpression:
36253                    return checkJsxExpression(node as JsxExpression, checkMode);
36254                case SyntaxKind.JsxElement:
36255                    return checkJsxElement(node as JsxElement, checkMode);
36256                case SyntaxKind.JsxSelfClosingElement:
36257                    return checkJsxSelfClosingElement(node as JsxSelfClosingElement, checkMode);
36258                case SyntaxKind.JsxFragment:
36259                    return checkJsxFragment(node as JsxFragment);
36260                case SyntaxKind.JsxAttributes:
36261                    return checkJsxAttributes(node as JsxAttributes, checkMode);
36262                case SyntaxKind.JsxOpeningElement:
36263                    Debug.fail("Shouldn't ever directly check a JsxOpeningElement");
36264            }
36265            return errorType;
36266        }
36267
36268        // Traverse Ets Component
36269        function checkIfEtsComponent(node: IfStatement, checkMode: CheckMode | undefined): void {
36270            checkIfChildComponent(node, checkMode);
36271            if (node.thenStatement && isBlock(node.thenStatement) && node.thenStatement.statements) {
36272                traverseEtsComponentStatements(node.thenStatement.statements, checkMode);
36273            }
36274            if (node.elseStatement) {
36275                if (isIfStatement(node.elseStatement)) {
36276                    checkIfEtsComponent(node.elseStatement, checkMode);
36277                }
36278                if (isBlock(node.elseStatement) && node.elseStatement.statements) {
36279                    traverseEtsComponentStatements(node.elseStatement.statements, checkMode);
36280                }
36281            }
36282        }
36283        function checkIfChildComponent(node: Node, checkMode: CheckMode | undefined): void {
36284            if ((<ExpressionStatement>node).expression) {
36285                checkExpressionWorker((<ExpressionStatement>node).expression, checkMode);
36286            }
36287            // @ts-ignore
36288            node.getChildren().forEach((item: Node) => checkIfChildComponent(item, checkMode));
36289        }
36290        function traverseEtsComponentStatements(statements: NodeArray<Statement>, checkMode: CheckMode | undefined): void {
36291            if (statements.length) {
36292                statements.forEach(item => {
36293                    if (isIfStatement(item)) {
36294                        checkIfEtsComponent(item, checkMode);
36295                    }
36296                    else if ((<ExpressionStatement>item).expression) {
36297                        checkExpressionWorker((<ExpressionStatement>item).expression, checkMode);
36298                    }
36299                });
36300            }
36301        }
36302
36303        // DECLARATION AND STATEMENT TYPE CHECKING
36304
36305        function checkTypeParameter(node: TypeParameterDeclaration) {
36306            // Grammar Checking
36307            checkGrammarModifiers(node);
36308            if (node.expression) {
36309                grammarErrorOnFirstToken(node.expression, Diagnostics.Type_expected);
36310            }
36311
36312            checkSourceElement(node.constraint);
36313            checkSourceElement(node.default);
36314            const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
36315            // Resolve base constraint to reveal circularity errors
36316            getBaseConstraintOfType(typeParameter);
36317            if (!hasNonCircularTypeParameterDefault(typeParameter)) {
36318                error(node.default, Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter));
36319            }
36320            const constraintType = getConstraintOfTypeParameter(typeParameter);
36321            const defaultType = getDefaultFromTypeParameter(typeParameter);
36322            if (constraintType && defaultType) {
36323                checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
36324            }
36325            checkNodeDeferred(node);
36326            addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0));
36327        }
36328
36329        function checkTypeParameterDeferred(node: TypeParameterDeclaration) {
36330            if (isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent)) {
36331                const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node));
36332                const modifiers = getVarianceModifiers(typeParameter);
36333                if (modifiers) {
36334                    const symbol = getSymbolOfNode(node.parent);
36335                    if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) {
36336                        error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types);
36337                    }
36338                    else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) {
36339                        tracing?.push(tracing.Phase.CheckTypes, "checkTypeParameterDeferred", { parent: getTypeId(getDeclaredTypeOfSymbol(symbol)), id: getTypeId(typeParameter) });
36340                        const source = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSubTypeForCheck : markerSuperTypeForCheck);
36341                        const target = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSuperTypeForCheck : markerSubTypeForCheck);
36342                        const saveVarianceTypeParameter = typeParameter;
36343                        varianceTypeParameter = typeParameter;
36344                        checkTypeAssignableTo(source, target, node, Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation);
36345                        varianceTypeParameter = saveVarianceTypeParameter;
36346                        tracing?.pop();
36347                    }
36348                }
36349            }
36350        }
36351
36352        function checkParameter(node: ParameterDeclaration) {
36353            // Grammar checking
36354            // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
36355            // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
36356            // or if its FunctionBody is strict code(11.1.5).
36357            checkGrammarDecoratorsAndModifiers(node);
36358
36359            checkVariableLikeDeclaration(node);
36360            const func = getContainingFunction(node)!;
36361            if (hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) {
36362                if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
36363                    error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
36364                }
36365                if (func.kind === SyntaxKind.Constructor && isIdentifier(node.name) && node.name.escapedText === "constructor") {
36366                    error(node.name, Diagnostics.constructor_cannot_be_used_as_a_parameter_property_name);
36367                }
36368            }
36369            if ((node.questionToken || isJSDocOptionalParameter(node)) && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) {
36370                error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
36371            }
36372            if (node.name && isIdentifier(node.name) && (node.name.escapedText === "this" || node.name.escapedText === "new")) {
36373                if (func.parameters.indexOf(node) !== 0) {
36374                    error(node, Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText as string);
36375                }
36376                if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature || func.kind === SyntaxKind.ConstructorType) {
36377                    error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter);
36378                }
36379                if (func.kind === SyntaxKind.ArrowFunction) {
36380                    error(node, Diagnostics.An_arrow_function_cannot_have_a_this_parameter);
36381                }
36382                if (func.kind === SyntaxKind.GetAccessor || func.kind === SyntaxKind.SetAccessor) {
36383                    error(node, Diagnostics.get_and_set_accessors_cannot_declare_this_parameters);
36384                }
36385            }
36386
36387            // Only check rest parameter type if it's not a binding pattern. Since binding patterns are
36388            // not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
36389            if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getReducedType(getTypeOfSymbol(node.symbol)), anyReadonlyArrayType)) {
36390                error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
36391            }
36392        }
36393
36394        function checkTypePredicate(node: TypePredicateNode): void {
36395            const parent = getTypePredicateParent(node);
36396            if (!parent) {
36397                // The parent must not be valid.
36398                error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
36399                return;
36400            }
36401
36402            const signature = getSignatureFromDeclaration(parent);
36403            const typePredicate = getTypePredicateOfSignature(signature);
36404            if (!typePredicate) {
36405                return;
36406            }
36407
36408            checkSourceElement(node.type);
36409
36410            const { parameterName } = node;
36411            if (typePredicate.kind === TypePredicateKind.This || typePredicate.kind === TypePredicateKind.AssertsThis) {
36412                getTypeFromThisTypeNode(parameterName as ThisTypeNode);
36413            }
36414            else {
36415                if (typePredicate.parameterIndex >= 0) {
36416                    if (signatureHasRestParameter(signature) && typePredicate.parameterIndex === signature.parameters.length - 1) {
36417                        error(parameterName, Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
36418                    }
36419                    else {
36420                        if (typePredicate.type) {
36421                            const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type);
36422                            checkTypeAssignableTo(typePredicate.type,
36423                                getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]),
36424                                node.type,
36425                                /*headMessage*/ undefined,
36426                                leadingError);
36427                        }
36428                    }
36429                }
36430                else if (parameterName) {
36431                    let hasReportedError = false;
36432                    for (const { name } of parent.parameters) {
36433                        if (isBindingPattern(name) &&
36434                                checkIfTypePredicateVariableIsDeclaredInBindingPattern(name, parameterName, typePredicate.parameterName)) {
36435                            hasReportedError = true;
36436                            break;
36437                        }
36438                    }
36439                    if (!hasReportedError) {
36440                        error(node.parameterName, Diagnostics.Cannot_find_parameter_0, typePredicate.parameterName);
36441                    }
36442                }
36443            }
36444        }
36445
36446        function getTypePredicateParent(node: Node): SignatureDeclaration | undefined {
36447            switch (node.parent.kind) {
36448                case SyntaxKind.ArrowFunction:
36449                case SyntaxKind.CallSignature:
36450                case SyntaxKind.FunctionDeclaration:
36451                case SyntaxKind.FunctionExpression:
36452                case SyntaxKind.FunctionType:
36453                case SyntaxKind.MethodDeclaration:
36454                case SyntaxKind.MethodSignature:
36455                    const parent = node.parent as SignatureDeclaration;
36456                    if (node === parent.type) {
36457                        return parent;
36458                    }
36459            }
36460        }
36461
36462        function checkIfTypePredicateVariableIsDeclaredInBindingPattern(
36463            pattern: BindingPattern,
36464            predicateVariableNode: Node,
36465            predicateVariableName: string) {
36466            for (const element of pattern.elements) {
36467                if (isOmittedExpression(element)) {
36468                    continue;
36469                }
36470
36471                const name = element.name;
36472                if (name.kind === SyntaxKind.Identifier && name.escapedText === predicateVariableName) {
36473                    error(predicateVariableNode,
36474                        Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
36475                        predicateVariableName);
36476                    return true;
36477                }
36478                else if (name.kind === SyntaxKind.ArrayBindingPattern || name.kind === SyntaxKind.ObjectBindingPattern) {
36479                    if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(
36480                        name,
36481                        predicateVariableNode,
36482                        predicateVariableName)) {
36483                        return true;
36484                    }
36485                }
36486            }
36487        }
36488
36489        function checkSignatureDeclaration(node: SignatureDeclaration) {
36490            // Grammar checking
36491            if (node.kind === SyntaxKind.IndexSignature) {
36492                checkGrammarIndexSignature(node);
36493            }
36494            // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled
36495            else if (node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.ConstructorType ||
36496                node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor ||
36497                node.kind === SyntaxKind.ConstructSignature) {
36498                checkGrammarFunctionLikeDeclaration(node as FunctionLikeDeclaration);
36499            }
36500
36501            const functionFlags = getFunctionFlags(node as FunctionLikeDeclaration);
36502            if (!(functionFlags & FunctionFlags.Invalid)) {
36503                // Async generators prior to ESNext require the __await and __asyncGenerator helpers
36504                if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator && languageVersion < ScriptTarget.ESNext) {
36505                    checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncGeneratorIncludes);
36506                }
36507
36508                // Async functions prior to ES2017 require the __awaiter helper
36509                if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async && languageVersion < ScriptTarget.ES2017) {
36510                    checkExternalEmitHelpers(node, ExternalEmitHelpers.Awaiter);
36511                }
36512
36513                // Generator functions, Async functions, and Async Generator functions prior to
36514                // ES2015 require the __generator helper
36515                if ((functionFlags & FunctionFlags.AsyncGenerator) !== FunctionFlags.Normal && languageVersion < ScriptTarget.ES2015) {
36516                    checkExternalEmitHelpers(node, ExternalEmitHelpers.Generator);
36517                }
36518            }
36519
36520            checkTypeParameters(getEffectiveTypeParameterDeclarations(node));
36521            checkUnmatchedJSDocParameters(node);
36522
36523            forEach(node.parameters, checkParameter);
36524
36525            // TODO(rbuckton): Should we start checking JSDoc types?
36526            if (node.type) {
36527                checkSourceElement(node.type);
36528            }
36529
36530            addLazyDiagnostic(checkSignatureDeclarationDiagnostics);
36531
36532            function checkSignatureDeclarationDiagnostics() {
36533                checkCollisionWithArgumentsInGeneratedCode(node);
36534                const returnTypeNode = getEffectiveReturnTypeNode(node);
36535                if (noImplicitAny && !returnTypeNode) {
36536                    switch (node.kind) {
36537                        case SyntaxKind.ConstructSignature:
36538                            error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
36539                            break;
36540                        case SyntaxKind.CallSignature:
36541                            error(node, Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
36542                            break;
36543                    }
36544                }
36545
36546                if (returnTypeNode) {
36547                    const functionFlags = getFunctionFlags(node as FunctionDeclaration);
36548                    if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Generator)) === FunctionFlags.Generator) {
36549                        const returnType = getTypeFromTypeNode(returnTypeNode);
36550                        if (returnType === voidType) {
36551                            error(returnTypeNode, Diagnostics.A_generator_cannot_have_a_void_type_annotation);
36552                        }
36553                        else {
36554                            // Naively, one could check that Generator<any, any, any> is assignable to the return type annotation.
36555                            // However, that would not catch the error in the following case.
36556                            //
36557                            //    interface BadGenerator extends Iterable<number>, Iterator<string> { }
36558                            //    function* g(): BadGenerator { } // Iterable and Iterator have different types!
36559                            //
36560                            const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType;
36561                            const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, (functionFlags & FunctionFlags.Async) !== 0) || generatorYieldType;
36562                            const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, (functionFlags & FunctionFlags.Async) !== 0) || unknownType;
36563                            const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async));
36564                            checkTypeAssignableTo(generatorInstantiation, returnType, returnTypeNode);
36565                        }
36566                    }
36567                    else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) {
36568                        checkAsyncFunctionReturnType(node as FunctionLikeDeclaration, returnTypeNode);
36569                    }
36570                }
36571                if (node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.JSDocFunctionType) {
36572                    registerForUnusedIdentifiersCheck(node);
36573                }
36574            }
36575        }
36576
36577        function checkClassForDuplicateDeclarations(node: ClassLikeDeclaration | AnnotationDeclaration) {
36578            const instanceNames = new Map<__String, DeclarationMeaning>();
36579            const staticNames = new Map<__String, DeclarationMeaning>();
36580            // instance and static private identifiers share the same scope
36581            const privateIdentifiers = new Map<__String, DeclarationMeaning>();
36582            for (const member of node.members) {
36583                if (member.kind === SyntaxKind.Constructor) {
36584                    for (const param of (member as ConstructorDeclaration).parameters) {
36585                        if (isParameterPropertyDeclaration(param, member) && !isBindingPattern(param.name)) {
36586                            addName(instanceNames, param.name, param.name.escapedText, DeclarationMeaning.GetOrSetAccessor);
36587                        }
36588                    }
36589                }
36590                else {
36591                    const isStaticMember = isStatic(member);
36592                    const name = member.name;
36593                    if (!name) {
36594                        continue;
36595                    }
36596                    const isPrivate = isPrivateIdentifier(name);
36597                    const privateStaticFlags = isPrivate && isStaticMember ? DeclarationMeaning.PrivateStatic : 0;
36598                    const names =
36599                        isPrivate ? privateIdentifiers :
36600                        isStaticMember ? staticNames :
36601                        instanceNames;
36602
36603                    const memberName = name && getPropertyNameForPropertyNameNode(name);
36604                    if (memberName) {
36605                        switch (member.kind) {
36606                            case SyntaxKind.GetAccessor:
36607                                addName(names, name, memberName, DeclarationMeaning.GetAccessor | privateStaticFlags);
36608                                break;
36609
36610                            case SyntaxKind.SetAccessor:
36611                                addName(names, name, memberName, DeclarationMeaning.SetAccessor | privateStaticFlags);
36612                                break;
36613
36614                            case SyntaxKind.PropertyDeclaration:
36615                                addName(names, name, memberName, DeclarationMeaning.GetOrSetAccessor | privateStaticFlags);
36616                                break;
36617
36618                            case SyntaxKind.AnnotationPropertyDeclaration:
36619                                addName(names, name, memberName, DeclarationMeaning.GetOrSetAccessor | privateStaticFlags);
36620                                break;
36621
36622                            case SyntaxKind.MethodDeclaration:
36623                                addName(names, name, memberName, DeclarationMeaning.Method | privateStaticFlags);
36624                                break;
36625                        }
36626                    }
36627                }
36628            }
36629
36630            function addName(names: UnderscoreEscapedMap<DeclarationMeaning>, location: Node, name: __String, meaning: DeclarationMeaning) {
36631                const prev = names.get(name);
36632                if (prev) {
36633                    // For private identifiers, do not allow mixing of static and instance members with the same name
36634                    if ((prev & DeclarationMeaning.PrivateStatic) !== (meaning & DeclarationMeaning.PrivateStatic)) {
36635                        error(location, Diagnostics.Duplicate_identifier_0_Static_and_instance_elements_cannot_share_the_same_private_name, getTextOfNode(location));
36636                    }
36637                    else {
36638                        const prevIsMethod = !!(prev & DeclarationMeaning.Method);
36639                        const isMethod = !!(meaning & DeclarationMeaning.Method);
36640                        if (prevIsMethod || isMethod) {
36641                            if (prevIsMethod !== isMethod) {
36642                                error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location));
36643                            }
36644                            // If this is a method/method duplication is might be an overload, so this will be handled when overloads are considered
36645                        }
36646                        else if (prev & meaning & ~DeclarationMeaning.PrivateStatic) {
36647                            error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location));
36648                        }
36649                        else {
36650                            names.set(name, prev | meaning);
36651                        }
36652                    }
36653                }
36654                else {
36655                    names.set(name, meaning);
36656                }
36657            }
36658        }
36659
36660        /**
36661         * Static members being set on a constructor function may conflict with built-in properties
36662         * of Function. Esp. in ECMAScript 5 there are non-configurable and non-writable
36663         * built-in properties. This check issues a transpile error when a class has a static
36664         * member with the same name as a non-writable built-in property.
36665         *
36666         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3
36667         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5
36668         * @see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor
36669         * @see http://www.ecma-international.org/ecma-262/6.0/#sec-function-instances
36670         */
36671        function checkClassForStaticPropertyNameConflicts(node: ClassLikeDeclaration) {
36672            for (const member of node.members) {
36673                const memberNameNode = member.name;
36674                const isStaticMember = isStatic(member);
36675                if (isStaticMember && memberNameNode) {
36676                    const memberName = getPropertyNameForPropertyNameNode(memberNameNode);
36677                    switch (memberName) {
36678                        case "name":
36679                        case "length":
36680                        case "caller":
36681                        case "arguments":
36682                        case "prototype":
36683                            const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1;
36684                            const className = getNameOfSymbolAsWritten(getSymbolOfNode(node));
36685                            error(memberNameNode, message, memberName, className);
36686                            break;
36687                    }
36688                }
36689            }
36690        }
36691
36692        function checkObjectTypeForDuplicateDeclarations(node: TypeLiteralNode | InterfaceDeclaration) {
36693            const names = new Map<string, boolean>();
36694            for (const member of node.members) {
36695                if (member.kind === SyntaxKind.PropertySignature) {
36696                    let memberName: string;
36697                    const name = member.name!;
36698                    switch (name.kind) {
36699                        case SyntaxKind.StringLiteral:
36700                        case SyntaxKind.NumericLiteral:
36701                            memberName = name.text;
36702                            break;
36703                        case SyntaxKind.Identifier:
36704                            memberName = idText(name);
36705                            break;
36706                        default:
36707                            continue;
36708                    }
36709
36710                    if (names.get(memberName)) {
36711                        error(getNameOfDeclaration(member.symbol.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName);
36712                        error(member.name, Diagnostics.Duplicate_identifier_0, memberName);
36713                    }
36714                    else {
36715                        names.set(memberName, true);
36716                    }
36717                }
36718            }
36719        }
36720
36721        function checkTypeForDuplicateIndexSignatures(node: Node) {
36722            if (node.kind === SyntaxKind.InterfaceDeclaration) {
36723                const nodeSymbol = getSymbolOfNode(node as InterfaceDeclaration);
36724                // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration
36725                // to prevent this run check only for the first declaration of a given kind
36726                if (nodeSymbol.declarations && nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) {
36727                    return;
36728                }
36729            }
36730
36731            // TypeScript 1.0 spec (April 2014)
36732            // 3.7.4: An object type can contain at most one string index signature and one numeric index signature.
36733            // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration
36734            const indexSymbol = getIndexSymbol(getSymbolOfNode(node)!);
36735            if (indexSymbol?.declarations) {
36736                const indexSignatureMap = new Map<TypeId, { type: Type, declarations: IndexSignatureDeclaration[] }>();
36737                for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) {
36738                    if (declaration.parameters.length === 1 && declaration.parameters[0].type) {
36739                        forEachType(getTypeFromTypeNode(declaration.parameters[0].type), type => {
36740                            const entry = indexSignatureMap.get(getTypeId(type));
36741                            if (entry) {
36742                                entry.declarations.push(declaration);
36743                            }
36744                            else {
36745                                indexSignatureMap.set(getTypeId(type), { type, declarations: [declaration] });
36746                            }
36747                        });
36748                    }
36749                }
36750                indexSignatureMap.forEach(entry => {
36751                    if (entry.declarations.length > 1) {
36752                        for (const declaration of entry.declarations) {
36753                            error(declaration, Diagnostics.Duplicate_index_signature_for_type_0, typeToString(entry.type));
36754                        }
36755                    }
36756                });
36757            }
36758        }
36759
36760        function isAllowedAnnotationPropertyEnumType(type: Type): boolean {
36761            // Non-constant enums are prohibited
36762            if (!type.symbol || !isConstEnumSymbol(type.symbol)) {
36763                return false;
36764            }
36765            // Mixing of numbers and strings is prohibited
36766            if (type.symbol.declarations) {
36767                for (const decl of type.symbol.declarations) {
36768                    if (decl.kind === SyntaxKind.EnumDeclaration) {
36769                        const members = (decl as EnumDeclaration).members;
36770                        for (let i = 0; i < members.length; ++i) {
36771                            if (i > 1 && typeof getConstantValue(members[i - 1]) !== typeof getConstantValue(members[i])) {
36772                                return false;
36773                            }
36774                        }
36775                    }
36776                }
36777            }
36778            return true;
36779        }
36780
36781        function isAllowedAnnotationPropertyType(type: Type): boolean {
36782            if (type === numberType ||
36783                type === booleanType ||
36784                type === stringType ||
36785                isAllowedAnnotationPropertyEnumType(type)) {
36786                return true;
36787            }
36788            else if (isArrayType(type)) {
36789                const elemType = getElementTypeOfArrayType(type);
36790                if (!elemType) {
36791                    return false;
36792                }
36793                return isAllowedAnnotationPropertyType(elemType);
36794            }
36795            return false;
36796        }
36797
36798        function annotationEvaluatedValueToExpr(initVal: AnnotationConstantExpressionType, initValType: Type): Expression | undefined {
36799            if (initVal === undefined || initValType === errorType)  {
36800                return undefined;
36801            }
36802            if (isArrayType(initValType) && !Array.isArray(initVal)) {
36803                return undefined;
36804            }
36805            if (typeof initVal === "number") {
36806                return factory.createNumericLiteral(initVal);
36807            }
36808            else if (typeof initVal === "string") {
36809                return factory.createStringLiteral(initVal);
36810            }
36811            else if (initValType === booleanType && typeof initVal === "boolean") {
36812                return (initVal) ? factory.createTrue() : factory.createFalse();
36813            }
36814            else if (isArrayType(initValType)) {
36815                Debug.assert(Array.isArray(initVal));
36816                const elemType = (initValType as GenericType).resolvedTypeArguments![0];
36817                // It is a special case since we need to store information about array element type,
36818                // when array literal is empty. For example,
36819                // '[]' -- have no information about element type
36820                // 'new Array<T>()' -- is valid expression with explicit type annotation and the same semantics with '[]'
36821                if (initVal.length === 0) {
36822                    if (isArrayType(elemType)) {
36823                        return factory.createArrayLiteralExpression([annotationEvaluatedValueToExpr(initVal, elemType)!]);
36824                    }
36825                    const args = new Array<Expression>();
36826                    // We add the argument '1' just for indicating that enum has numeric members
36827                    // '3' - string members
36828                    if (elemType.symbol && isConstEnumSymbol(elemType.symbol)) {
36829                        const enumMembers = (elemType.symbol.declarations![0] as EnumDeclaration).members;
36830                        if (enumMembers.length === 0 || typeof getConstantValue(enumMembers[0]) === "number") {
36831                            args.push(factory.createNumericLiteral(1));
36832                        }
36833                        else {
36834                            args.push(factory.createNumericLiteral(3));
36835                        }
36836                    }
36837                    return factory.createNewExpression(
36838                        factory.createIdentifier("Array"),
36839                        [nodeBuilder.typeToTypeNode(elemType) as TypeNode],
36840                        args);
36841                }
36842                const result = new Array<Expression>(initVal.length);
36843                for (let i = 0; i < initVal.length; ++i) {
36844                    result[i] = annotationEvaluatedValueToExpr(initVal[i], elemType)!;
36845                    if (result[i] === undefined){
36846                        return undefined;
36847                    }
36848                }
36849                return factory.createArrayLiteralExpression(result);
36850            }
36851        }
36852
36853        function evaluateAnnotationPropertyConstantExpression(expr: Expression): AnnotationConstantExpressionType | undefined {
36854            switch (expr.kind) {
36855                case SyntaxKind.PrefixUnaryExpression:
36856                    const value = evaluateAnnotationPropertyConstantExpression((expr as PrefixUnaryExpression).operand);
36857                    if (typeof value === "number" || typeof value === "string" || typeof value === "boolean") {
36858                        switch ((expr as PrefixUnaryExpression).operator) {
36859                            case SyntaxKind.ExclamationToken: return !value;
36860                        }
36861                    }
36862                    if (typeof value === "number") {
36863                        switch ((expr as PrefixUnaryExpression).operator) {
36864                            case SyntaxKind.PlusToken: return value;
36865                            case SyntaxKind.MinusToken: return -value;
36866                            case SyntaxKind.TildeToken: return ~value;
36867                        }
36868                    }
36869                    break;
36870                case SyntaxKind.BinaryExpression:
36871                    const left = evaluateAnnotationPropertyConstantExpression((expr as BinaryExpression).left);
36872                    const right = evaluateAnnotationPropertyConstantExpression((expr as BinaryExpression).right);
36873                    // `number` binop `number`
36874                    // `string` binop `string`
36875                    // `boolean` binop `boolean`
36876                    if (left !== undefined && right !== undefined && typeof left === typeof right) {
36877                        switch ((expr as BinaryExpression).operatorToken.kind) {
36878                            case SyntaxKind.LessThanToken: return left < right;
36879                            case SyntaxKind.LessThanEqualsToken: return left <= right;
36880                            case SyntaxKind.GreaterThanToken: return left > right;
36881                            case SyntaxKind.GreaterThanEqualsToken: return left >= right;
36882                            case SyntaxKind.EqualsEqualsEqualsToken: return left === right;
36883                            case SyntaxKind.ExclamationEqualsEqualsToken: return left !== right;
36884                            case SyntaxKind.EqualsEqualsToken: return left == right;
36885                            case SyntaxKind.ExclamationEqualsToken: return left != right;
36886                            case SyntaxKind.AmpersandAmpersandToken: return left && right;
36887                            case SyntaxKind.BarBarToken: return left || right;
36888                        }
36889                    }
36890                    // `number` binop (`number` | `string` | `boolean`)
36891                    // `string` binop (`number` | `string` | `boolean`)
36892                    // `boolean` binop (`number` | `string` | `boolean`)
36893                    if ((typeof left === "number" || typeof left === "string" || typeof left === "boolean") &&
36894                        (typeof right === "number" || typeof right === "string" || typeof right === "boolean")) {
36895                        switch ((expr as BinaryExpression).operatorToken.kind) {
36896                            case SyntaxKind.AmpersandAmpersandToken: return left && right;
36897                            case SyntaxKind.BarBarToken: return left || right;
36898                        }
36899                    }
36900                    if (typeof left === "number" && typeof right === "number") {
36901                        switch ((expr as BinaryExpression).operatorToken.kind) {
36902                            case SyntaxKind.BarToken: return left | right;
36903                            case SyntaxKind.AmpersandToken: return left & right;
36904                            case SyntaxKind.GreaterThanGreaterThanToken: return left >> right;
36905                            case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return left >>> right;
36906                            case SyntaxKind.LessThanLessThanToken: return left << right;
36907                            case SyntaxKind.CaretToken: return left ^ right;
36908                            case SyntaxKind.AsteriskToken: return left * right;
36909                            case SyntaxKind.SlashToken: return left / right;
36910                            case SyntaxKind.PlusToken: return left + right;
36911                            case SyntaxKind.MinusToken: return left - right;
36912                            case SyntaxKind.PercentToken: return left % right;
36913                            case SyntaxKind.AsteriskAsteriskToken: return left ** right;
36914                        }
36915                    }
36916                    else if (typeof left === "string" && typeof right === "string") {
36917                        switch ((expr as BinaryExpression).operatorToken.kind) {
36918                            case SyntaxKind.PlusToken: return left + right;
36919                        }
36920                    }
36921                    break;
36922                case SyntaxKind.ArrayLiteralExpression:
36923                    const elements = (expr as ArrayLiteralExpression).elements;
36924                    const result = new Array<AnnotationConstantExpressionType>(elements.length);
36925                    for (let i = 0; i < elements.length; ++i) {
36926                        const elem = evaluateAnnotationPropertyConstantExpression(elements[i]);
36927                        if (elem === undefined) {
36928                            return undefined;
36929                        }
36930                        if (i > 0 && (typeof result[i - 1] !== typeof elem)) {
36931                            return undefined;
36932                        }
36933                        result[i] = elem;
36934                    }
36935                    return result;
36936                case SyntaxKind.TrueKeyword:
36937                    return true;
36938                case SyntaxKind.FalseKeyword:
36939                    return false;
36940                case SyntaxKind.StringLiteral:
36941                case SyntaxKind.NoSubstitutionTemplateLiteral:
36942                    return (expr as StringLiteralLike).text;
36943                case SyntaxKind.NumericLiteral:
36944                    checkGrammarNumericLiteral(expr as NumericLiteral);
36945                    return +(expr as NumericLiteral).text;
36946                case SyntaxKind.ParenthesizedExpression:
36947                    return evaluateAnnotationPropertyConstantExpression((expr as ParenthesizedExpression).expression);
36948                case SyntaxKind.Identifier:
36949                    if (isInfinityOrNaNString((expr as Identifier).escapedText)) {
36950                        return +((expr as Identifier).escapedText);
36951                    }
36952                    const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(expr as Identifier));
36953                    // Only `const a = ...` like are prohibited
36954                    if (!symbol || !isConstVariable(symbol)) {
36955                        return undefined;
36956                    }
36957                    // Initializer must be present and able to be evaluated as constant expression
36958                    if (symbol.valueDeclaration && hasOnlyExpressionInitializer(symbol.valueDeclaration) && symbol.valueDeclaration.initializer) {
36959                        return evaluateAnnotationPropertyConstantExpression(symbol.valueDeclaration.initializer);
36960                    }
36961                    break;
36962                case SyntaxKind.PropertyAccessExpression:
36963                    if (isConstantMemberAccess(expr)) {
36964                        return getConstantValue(expr);
36965                    }
36966                    break;
36967            }
36968            return undefined;
36969        }
36970
36971        function checkPropertyDeclaration(node: PropertyDeclaration | PropertySignature | AnnotationPropertyDeclaration) {
36972            // Grammar checking
36973            if (!isAnnotationPropertyDeclaration(node) && !checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name);
36974            if (isAnnotationPropertyDeclaration(node)) {
36975                if (!node.type && !node.initializer) {
36976                    error(node, Diagnostics.An_annotation_property_must_have_a_type_or_Slashand_an_initializer);
36977                }
36978            }
36979            checkVariableLikeDeclaration(node);
36980
36981            setNodeLinksForPrivateIdentifierScope(node);
36982
36983            // property signatures already report "initializer not allowed in ambient context" elsewhere
36984            if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.PropertyDeclaration && node.initializer) {
36985                error(node, Diagnostics.Property_0_cannot_have_an_initializer_because_it_is_marked_abstract, declarationNameToString(node.name));
36986            }
36987
36988            if (isAnnotationPropertyDeclaration(node)) {
36989                checkAnnotationPropertyDeclaration(node);
36990            }
36991        }
36992
36993        function checkAnnotationPropertyDeclaration(node: AnnotationPropertyDeclaration) {
36994            const propType = getTypeOfNode(node);
36995            if (!isAllowedAnnotationPropertyType(propType)) {
36996                error(node, Diagnostics.A_type_of_annotation_property_have_to_be_number_boolean_string_const_enumeration_types_or_array_of_above_types_got_Colon_0, typeToString(propType));
36997            }
36998            if (node.initializer) {
36999                const evaluated = evaluateAnnotationPropertyConstantExpression(node.initializer);
37000                if (evaluated === undefined) {
37001                    error(node, Diagnostics.Default_value_of_annotation_property_can_be_a_constant_expression_got_Colon_0, getTextOfNode(node.initializer, /*includeTrivia*/ false));
37002                }
37003                else {
37004                    const evaluatedExpr = annotationEvaluatedValueToExpr(evaluated, getTypeOfNode(node));
37005                    getNodeLinks(node).annotationPropertyEvaluatedInitializer = evaluatedExpr;
37006                }
37007            }
37008
37009            // Special cases for enums
37010            if (!node.initializer) {
37011                const initializer = addAnnotationPropertyEnumInitalizer(propType);
37012                if (initializer) {
37013                    getNodeLinks(node).annotationPropertyEvaluatedInitializer = initializer;
37014                }
37015            }
37016
37017            getNodeLinks(node).annotationPropertyInferredType = nodeBuilder.typeToTypeNode(propType);
37018        }
37019
37020        function addAnnotationPropertyEnumInitalizer(propType: Type): Expression | undefined {
37021            // Since we need to store information about type of enum members
37022            // We introduce a prohibited for users "useless" expression with explicit type annotation
37023            // For example;
37024            // const enum E {A, B}
37025            //
37026            // @interface Anno {
37027            //     a: E  -->  a: E = new Number(0) as number
37028            // }
37029            // Following expression indicates that the E is enum with numeric members
37030            if (propType.symbol && isConstEnumSymbol(propType.symbol)) {
37031                const enumMembers = (propType.symbol.declarations![0] as EnumDeclaration).members;
37032                const firstMemeberVal = getConstantValue(enumMembers[0])!;
37033                if (enumMembers.length === 0 || typeof firstMemeberVal === "number") {
37034                    return factory.createAsExpression(
37035                        factory.createNewExpression(
37036                            factory.createIdentifier(
37037                                typeToString(globalNumberType)
37038                            ),
37039                            /* typeArguments */ undefined,
37040                            [factory.createNumericLiteral(firstMemeberVal)]),
37041                        nodeBuilder.typeToTypeNode(numberType)!
37042                    );
37043                }
37044            }
37045            // @interface Anno {
37046            //     a: NumberEnum[]  -->  a: NumberEnum[] = new Array<NumberEnum>(0)
37047            // }
37048            //
37049            // or
37050            //
37051            // @interface Anno {
37052            //     a: StringEnum[]  -->  a: StringEnum[] = new Array<StringEnum>(2)
37053            // }
37054            //
37055            // or
37056            //
37057            // @interface Anno {
37058            //     a: StringEnum[][]  -->  a: StringEnum[][] = [new Array<StringEnum>(2)]
37059            // }
37060            else if (isArrayType(propType)) {
37061                return addAnnotationPropertyEnumArrayInitalizer(propType);
37062            }
37063            return undefined;
37064        }
37065
37066        function addAnnotationPropertyEnumArrayInitalizer(propType: Type): Expression | undefined {
37067            if (isArrayType(propType)) {
37068                const elemType = (propType as GenericType).resolvedTypeArguments![0];
37069                if (isArrayType(elemType)) {
37070                    const arr = addAnnotationPropertyEnumArrayInitalizer(elemType);
37071                    if (arr) {
37072                        return factory.createArrayLiteralExpression([arr]);
37073                    }
37074                }
37075                if (elemType.symbol && isConstEnumSymbol(elemType.symbol)) {
37076                    const args = new Array<Expression>();
37077                    const enumMembers = (elemType.symbol.declarations![0] as EnumDeclaration).members;
37078                    if (enumMembers.length === 0 || typeof getConstantValue(enumMembers[0]) === "number") {
37079                        args.push(factory.createNumericLiteral(0));
37080                    }
37081                    else {
37082                        args.push(factory.createNumericLiteral(2));
37083                    }
37084                    return factory.createNewExpression(
37085                        factory.createIdentifier(
37086                            typeToString(propType, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)
37087                        ),
37088                        /*typeArguments*/ undefined,
37089                        args);
37090                }
37091            }
37092            return undefined;
37093        }
37094
37095        function checkPropertySignature(node: PropertySignature) {
37096            if (isPrivateIdentifier(node.name)) {
37097                error(node, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
37098            }
37099            return checkPropertyDeclaration(node);
37100        }
37101
37102        function checkMethodDeclaration(node: MethodDeclaration | MethodSignature) {
37103            // Grammar checking
37104            if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name);
37105
37106            if (isMethodDeclaration(node) && node.asteriskToken && isIdentifier(node.name) && idText(node.name) === "constructor") {
37107                error(node.name, Diagnostics.Class_constructor_may_not_be_a_generator);
37108            }
37109
37110            // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
37111            checkFunctionOrMethodDeclaration(node);
37112
37113            // method signatures already report "implementation not allowed in ambient context" elsewhere
37114            if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration && node.body) {
37115                error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name));
37116            }
37117
37118            // Private named methods are only allowed in class declarations
37119            if (isPrivateIdentifier(node.name) && !getContainingClass(node)) {
37120                error(node, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
37121            }
37122
37123            setNodeLinksForPrivateIdentifierScope(node);
37124        }
37125
37126        function setNodeLinksForPrivateIdentifierScope(node: PropertyDeclaration | PropertySignature | AnnotationPropertyDeclaration | MethodDeclaration | MethodSignature | AccessorDeclaration) {
37127            if (isPrivateIdentifier(node.name) && languageVersion < ScriptTarget.ESNext) {
37128                for (let lexicalScope = getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = getEnclosingBlockScopeContainer(lexicalScope)) {
37129                    getNodeLinks(lexicalScope).flags |= NodeCheckFlags.ContainsClassWithPrivateIdentifiers;
37130                }
37131
37132                // If this is a private element in a class expression inside the body of a loop,
37133                // then we must use a block-scoped binding to store the additional variables required
37134                // to transform private elements.
37135                if (isClassExpression(node.parent)) {
37136                    const enclosingIterationStatement = getEnclosingIterationStatement(node.parent);
37137                    if (enclosingIterationStatement) {
37138                        getNodeLinks(node.name).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
37139                        getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding;
37140                    }
37141                }
37142            }
37143        }
37144
37145        function checkClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) {
37146            checkGrammarDecoratorsAndModifiers(node);
37147
37148            forEachChild(node, checkSourceElement);
37149        }
37150
37151        function checkConstructorDeclaration(node: ConstructorDeclaration) {
37152            // If constructor is virtual node, skip it
37153            if (node.virtual) {
37154                return;
37155            }
37156
37157            // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function.
37158            checkSignatureDeclaration(node);
37159            // Grammar check for checking only related to constructorDeclaration
37160            if (!checkGrammarConstructorTypeParameters(node)) checkGrammarConstructorTypeAnnotation(node);
37161
37162            checkSourceElement(node.body);
37163
37164            const symbol = getSymbolOfNode(node);
37165            const firstDeclaration = getDeclarationOfKind(symbol, node.kind);
37166
37167            // Only type check the symbol once
37168            if (node === firstDeclaration) {
37169                checkFunctionOrConstructorSymbol(symbol);
37170            }
37171
37172            // exit early in the case of signature - super checks are not relevant to them
37173            if (nodeIsMissing(node.body)) {
37174                return;
37175            }
37176
37177            addLazyDiagnostic(checkConstructorDeclarationDiagnostics);
37178
37179            return;
37180
37181            function isInstancePropertyWithInitializerOrPrivateIdentifierProperty(n: Node): boolean {
37182                if (isPrivateIdentifierClassElementDeclaration(n)) {
37183                    return true;
37184                }
37185                return n.kind === SyntaxKind.PropertyDeclaration &&
37186                    !isStatic(n) &&
37187                    !!(n as PropertyDeclaration).initializer;
37188            }
37189
37190            function checkConstructorDeclarationDiagnostics() {
37191                // TS 1.0 spec (April 2014): 8.3.2
37192                // Constructors of classes with no extends clause may not contain super calls, whereas
37193                // constructors of derived classes must contain at least one super call somewhere in their function body.
37194                const containingClassDecl = node.parent as ClassDeclaration;
37195                if (getClassExtendsHeritageElement(containingClassDecl)) {
37196                    captureLexicalThis(node.parent, containingClassDecl);
37197                    const classExtendsNull = classDeclarationExtendsNull(containingClassDecl);
37198                    const superCall = findFirstSuperCall(node.body!);
37199                    if (superCall) {
37200                        if (classExtendsNull) {
37201                            error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null);
37202                        }
37203
37204                        // A super call must be root-level in a constructor if both of the following are true:
37205                        // - The containing class is a derived class.
37206                        // - The constructor declares parameter properties
37207                        //   or the containing class declares instance member variables with initializers.
37208
37209                        const superCallShouldBeRootLevel =
37210                            (getEmitScriptTarget(compilerOptions) !== ScriptTarget.ESNext || !useDefineForClassFields) &&
37211                            (some((node.parent as ClassDeclaration).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) ||
37212                            some(node.parameters, p => hasSyntacticModifier(p, ModifierFlags.ParameterPropertyModifier)));
37213
37214                        if (superCallShouldBeRootLevel) {
37215                            // Until we have better flow analysis, it is an error to place the super call within any kind of block or conditional
37216                            // See GH #8277
37217                            if (!superCallIsRootLevelInConstructor(superCall, node.body!)) {
37218                                error(superCall, Diagnostics.A_super_call_must_be_a_root_level_statement_within_a_constructor_of_a_derived_class_that_contains_initialized_properties_parameter_properties_or_private_identifiers);
37219                            }
37220                            // Skip past any prologue directives to check statements for referring to 'super' or 'this' before a super call
37221                            else {
37222                                let superCallStatement: ExpressionStatement | undefined;
37223
37224                                for (const statement of node.body!.statements) {
37225                                    if (isExpressionStatement(statement) && isSuperCall(skipOuterExpressions(statement.expression))) {
37226                                        superCallStatement = statement;
37227                                        break;
37228                                    }
37229                                    if (nodeImmediatelyReferencesSuperOrThis(statement)) {
37230                                        break;
37231                                    }
37232                                }
37233
37234                                // Until we have better flow analysis, it is an error to place the super call within any kind of block or conditional
37235                                // See GH #8277
37236                                if (superCallStatement === undefined) {
37237                                    error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_to_refer_to_super_or_this_when_a_derived_class_contains_initialized_properties_parameter_properties_or_private_identifiers);
37238                                }
37239                            }
37240                        }
37241                    }
37242                    else if (!classExtendsNull) {
37243                        error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
37244                    }
37245                }
37246            }
37247        }
37248
37249        function superCallIsRootLevelInConstructor(superCall: Node, body: Block) {
37250            const superCallParent = walkUpParenthesizedExpressions(superCall.parent);
37251            return isExpressionStatement(superCallParent) && superCallParent.parent === body;
37252        }
37253
37254        function nodeImmediatelyReferencesSuperOrThis(node: Node): boolean {
37255            if (node.kind === SyntaxKind.SuperKeyword || node.kind === SyntaxKind.ThisKeyword) {
37256                return true;
37257            }
37258
37259            if (isThisContainerOrFunctionBlock(node)) {
37260                return false;
37261            }
37262
37263            return !!forEachChild(node, nodeImmediatelyReferencesSuperOrThis);
37264        }
37265
37266        function checkAccessorDeclaration(node: AccessorDeclaration) {
37267            if (isIdentifier(node.name) && idText(node.name) === "constructor") {
37268                error(node.name, Diagnostics.Class_constructor_may_not_be_an_accessor);
37269            }
37270            addLazyDiagnostic(checkAccessorDeclarationDiagnostics);
37271            checkSourceElement(node.body);
37272            setNodeLinksForPrivateIdentifierScope(node);
37273
37274            function checkAccessorDeclarationDiagnostics() {
37275                // Grammar checking accessors
37276                if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name);
37277
37278                checkDecorators(node);
37279                checkSignatureDeclaration(node);
37280                if (node.kind === SyntaxKind.GetAccessor) {
37281                    if (!(node.flags & NodeFlags.Ambient) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) {
37282                        if (!(node.flags & NodeFlags.HasExplicitReturn)) {
37283                            error(node.name, Diagnostics.A_get_accessor_must_return_a_value);
37284                        }
37285                    }
37286                }
37287                // Do not use hasDynamicName here, because that returns false for well known symbols.
37288                // We want to perform checkComputedPropertyName for all computed properties, including
37289                // well known symbols.
37290                if (node.name.kind === SyntaxKind.ComputedPropertyName) {
37291                    checkComputedPropertyName(node.name);
37292                }
37293
37294                if (hasBindableName(node)) {
37295                    // TypeScript 1.0 spec (April 2014): 8.4.3
37296                    // Accessors for the same member name must specify the same accessibility.
37297                    const symbol = getSymbolOfNode(node);
37298                    const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
37299                    const setter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.SetAccessor);
37300                    if (getter && setter && !(getNodeCheckFlags(getter) & NodeCheckFlags.TypeChecked)) {
37301                        getNodeLinks(getter).flags |= NodeCheckFlags.TypeChecked;
37302                        const getterFlags = getEffectiveModifierFlags(getter);
37303                        const setterFlags = getEffectiveModifierFlags(setter);
37304                        if ((getterFlags & ModifierFlags.Abstract) !== (setterFlags & ModifierFlags.Abstract)) {
37305                            error(getter.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract);
37306                            error(setter.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract);
37307                        }
37308                        if (((getterFlags & ModifierFlags.Protected) && !(setterFlags & (ModifierFlags.Protected | ModifierFlags.Private))) ||
37309                            ((getterFlags & ModifierFlags.Private) && !(setterFlags & ModifierFlags.Private))) {
37310                            error(getter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter);
37311                            error(setter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter);
37312                        }
37313
37314                        const getterType = getAnnotatedAccessorType(getter);
37315                        const setterType = getAnnotatedAccessorType(setter);
37316                        if (getterType && setterType) {
37317                            checkTypeAssignableTo(getterType, setterType, getter, Diagnostics.The_return_type_of_a_get_accessor_must_be_assignable_to_its_set_accessor_type);
37318                        }
37319                    }
37320                }
37321                const returnType = getTypeOfAccessors(getSymbolOfNode(node));
37322                if (node.kind === SyntaxKind.GetAccessor) {
37323                    checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType);
37324                }
37325            }
37326        }
37327
37328        function checkMissingDeclaration(node: Node) {
37329            checkDecorators(node);
37330        }
37331
37332        function getEffectiveTypeArgumentAtIndex(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[], index: number): Type {
37333            if (node.typeArguments && index < node.typeArguments.length) {
37334                return getTypeFromTypeNode(node.typeArguments[index]);
37335            }
37336            return getEffectiveTypeArguments(node, typeParameters)[index];
37337        }
37338
37339        function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[]): Type[] {
37340            return fillMissingTypeArguments(map(node.typeArguments!, getTypeFromTypeNode), typeParameters,
37341                getMinTypeArgumentCount(typeParameters), isInJSFile(node));
37342        }
37343
37344        function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[]): boolean {
37345            let typeArguments: Type[] | undefined;
37346            let mapper: TypeMapper | undefined;
37347            let result = true;
37348            for (let i = 0; i < typeParameters.length; i++) {
37349                const constraint = getConstraintOfTypeParameter(typeParameters[i]);
37350                if (constraint) {
37351                    if (!typeArguments) {
37352                        typeArguments = getEffectiveTypeArguments(node, typeParameters);
37353                        mapper = createTypeMapper(typeParameters, typeArguments);
37354                    }
37355                    result = result && checkTypeAssignableTo(
37356                        typeArguments[i],
37357                        instantiateType(constraint, mapper),
37358                        node.typeArguments![i],
37359                        Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
37360                }
37361            }
37362            return result;
37363        }
37364
37365        function getTypeParametersForTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments) {
37366            const type = getTypeFromTypeReference(node);
37367            if (!isErrorType(type)) {
37368                const symbol = getNodeLinks(node).resolvedSymbol;
37369                if (symbol) {
37370                    return symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters ||
37371                        (getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target.localTypeParameters : undefined);
37372                }
37373            }
37374            return undefined;
37375        }
37376
37377        function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) {
37378            checkGrammarTypeArguments(node, node.typeArguments);
37379            if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) {
37380                grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
37381            }
37382            forEach(node.typeArguments, checkSourceElement);
37383            const type = getTypeFromTypeReference(node);
37384            if (type.symbol && (type.symbol.flags & SymbolFlags.Annotation)) {
37385                error(node, Diagnostics.Annotation_cannot_be_used_as_a_type);
37386            }
37387            if (!isErrorType(type)) {
37388                if (node.typeArguments) {
37389                    addLazyDiagnostic(() => {
37390                        const typeParameters = getTypeParametersForTypeReference(node);
37391                        if (typeParameters) {
37392                            checkTypeArgumentConstraints(node, typeParameters);
37393                        }
37394                    });
37395                }
37396                const symbol = getNodeLinks(node).resolvedSymbol;
37397                if (symbol) {
37398                    if (some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & NodeFlags.Deprecated))) {
37399                        addDeprecatedSuggestion(
37400                            getDeprecatedSuggestionNode(node),
37401                            symbol.declarations!,
37402                            symbol.escapedName as string
37403                        );
37404                    }
37405                    if (type.flags & TypeFlags.Enum && symbol.flags & SymbolFlags.EnumMember) {
37406                        error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
37407                    }
37408                }
37409            }
37410        }
37411
37412        function getTypeArgumentConstraint(node: TypeNode): Type | undefined {
37413            const typeReferenceNode = tryCast(node.parent, isTypeReferenceType);
37414            if (!typeReferenceNode) return undefined;
37415            const typeParameters = getTypeParametersForTypeReference(typeReferenceNode);
37416            if (!typeParameters) return undefined;
37417            const constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments!.indexOf(node)]);
37418            return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters)));
37419        }
37420
37421        function checkTypeQuery(node: TypeQueryNode) {
37422            getTypeFromTypeQueryNode(node);
37423        }
37424
37425        function checkTypeLiteral(node: TypeLiteralNode) {
37426            forEach(node.members, checkSourceElement);
37427            addLazyDiagnostic(checkTypeLiteralDiagnostics);
37428
37429            function checkTypeLiteralDiagnostics() {
37430                const type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
37431                checkIndexConstraints(type, type.symbol);
37432                checkTypeForDuplicateIndexSignatures(node);
37433                checkObjectTypeForDuplicateDeclarations(node);
37434            }
37435        }
37436
37437        function checkArrayType(node: ArrayTypeNode) {
37438            checkSourceElement(node.elementType);
37439        }
37440
37441        function checkTupleType(node: TupleTypeNode) {
37442            const elementTypes = node.elements;
37443            let seenOptionalElement = false;
37444            let seenRestElement = false;
37445            const hasNamedElement = some(elementTypes, isNamedTupleMember);
37446            for (const e of elementTypes) {
37447                if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) {
37448                    grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
37449                    break;
37450                }
37451                const flags = getTupleElementFlags(e);
37452                if (flags & ElementFlags.Variadic) {
37453                    const type = getTypeFromTypeNode((e as RestTypeNode | NamedTupleMember).type);
37454                    if (!isArrayLikeType(type)) {
37455                        error(e, Diagnostics.A_rest_element_type_must_be_an_array_type);
37456                        break;
37457                    }
37458                    if (isArrayType(type) || isTupleType(type) && type.target.combinedFlags & ElementFlags.Rest) {
37459                        seenRestElement = true;
37460                    }
37461                }
37462                else if (flags & ElementFlags.Rest) {
37463                    if (seenRestElement) {
37464                        grammarErrorOnNode(e, Diagnostics.A_rest_element_cannot_follow_another_rest_element);
37465                        break;
37466                    }
37467                    seenRestElement = true;
37468                }
37469                else if (flags & ElementFlags.Optional) {
37470                    if (seenRestElement) {
37471                        grammarErrorOnNode(e, Diagnostics.An_optional_element_cannot_follow_a_rest_element);
37472                        break;
37473                    }
37474                    seenOptionalElement = true;
37475                }
37476                else if (seenOptionalElement) {
37477                    grammarErrorOnNode(e, Diagnostics.A_required_element_cannot_follow_an_optional_element);
37478                    break;
37479                }
37480            }
37481            forEach(node.elements, checkSourceElement);
37482            getTypeFromTypeNode(node);
37483        }
37484
37485        function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) {
37486            forEach(node.types, checkSourceElement);
37487            getTypeFromTypeNode(node);
37488        }
37489
37490        function checkIndexedAccessIndexType(type: Type, accessNode: IndexedAccessTypeNode | ElementAccessExpression) {
37491            if (!(type.flags & TypeFlags.IndexedAccess)) {
37492                return type;
37493            }
37494            // Check if the index type is assignable to 'keyof T' for the object type.
37495            const objectType = (type as IndexedAccessType).objectType;
37496            const indexType = (type as IndexedAccessType).indexType;
37497            if (isTypeAssignableTo(indexType, getIndexType(objectType, /*stringsOnly*/ false))) {
37498                if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
37499                    getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly) {
37500                    error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
37501                }
37502                return type;
37503            }
37504            // Check if we're indexing with a numeric type and if either object or index types
37505            // is a generic type with a constraint that has a numeric index signature.
37506            const apparentObjectType = getApparentType(objectType);
37507            if (getIndexInfoOfType(apparentObjectType, numberType) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) {
37508                return type;
37509            }
37510            if (isGenericObjectType(objectType)) {
37511                const propertyName = getPropertyNameFromIndex(indexType, accessNode);
37512                if (propertyName) {
37513                    const propertySymbol = forEachType(apparentObjectType, t => getPropertyOfType(t, propertyName));
37514                    if (propertySymbol && getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.NonPublicAccessibilityModifier) {
37515                        error(accessNode, Diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, unescapeLeadingUnderscores(propertyName));
37516                        return errorType;
37517                    }
37518                }
37519            }
37520            error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
37521            return errorType;
37522        }
37523
37524        function checkIndexedAccessType(node: IndexedAccessTypeNode) {
37525            checkSourceElement(node.objectType);
37526            checkSourceElement(node.indexType);
37527            checkIndexedAccessIndexType(getTypeFromIndexedAccessTypeNode(node), node);
37528        }
37529
37530        function checkMappedType(node: MappedTypeNode) {
37531            checkGrammarMappedType(node);
37532            checkSourceElement(node.typeParameter);
37533            checkSourceElement(node.nameType);
37534            checkSourceElement(node.type);
37535
37536            if (!node.type) {
37537                reportImplicitAny(node, anyType);
37538            }
37539
37540            const type = getTypeFromMappedTypeNode(node) as MappedType;
37541            const nameType = getNameTypeFromMappedType(type);
37542            if (nameType) {
37543                checkTypeAssignableTo(nameType, keyofConstraintType, node.nameType);
37544            }
37545            else {
37546                const constraintType = getConstraintTypeFromMappedType(type);
37547                checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter));
37548            }
37549        }
37550
37551        function checkGrammarMappedType(node: MappedTypeNode) {
37552            if (node.members?.length) {
37553                return grammarErrorOnNode(node.members[0], Diagnostics.A_mapped_type_may_not_declare_properties_or_methods);
37554            }
37555        }
37556
37557        function checkThisType(node: ThisTypeNode) {
37558            getTypeFromThisTypeNode(node);
37559        }
37560
37561        function checkTypeOperator(node: TypeOperatorNode) {
37562            checkGrammarTypeOperatorNode(node);
37563            checkSourceElement(node.type);
37564        }
37565
37566        function checkConditionalType(node: ConditionalTypeNode) {
37567            forEachChild(node, checkSourceElement);
37568        }
37569
37570        function checkInferType(node: InferTypeNode) {
37571            if (!findAncestor(node, n => n.parent && n.parent.kind === SyntaxKind.ConditionalType && (n.parent as ConditionalTypeNode).extendsType === n)) {
37572                grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type);
37573            }
37574            checkSourceElement(node.typeParameter);
37575            const symbol = getSymbolOfNode(node.typeParameter);
37576            if (symbol.declarations && symbol.declarations.length > 1) {
37577                const links = getSymbolLinks(symbol);
37578                if (!links.typeParametersChecked) {
37579                    links.typeParametersChecked = true;
37580                    const typeParameter = getDeclaredTypeOfTypeParameter(symbol);
37581                    const declarations: TypeParameterDeclaration[] = getDeclarationsOfKind(symbol, SyntaxKind.TypeParameter);
37582                    if (!areTypeParametersIdentical(declarations, [typeParameter], decl => [decl])) {
37583                        // Report an error on every conflicting declaration.
37584                        const name = symbolToString(symbol);
37585                        for (const declaration of declarations) {
37586                            error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_constraints, name);
37587                        }
37588                    }
37589                }
37590            }
37591            registerForUnusedIdentifiersCheck(node);
37592        }
37593
37594        function checkTemplateLiteralType(node: TemplateLiteralTypeNode) {
37595            for (const span of node.templateSpans) {
37596                checkSourceElement(span.type);
37597                const type = getTypeFromTypeNode(span.type);
37598                checkTypeAssignableTo(type, templateConstraintType, span.type);
37599            }
37600            getTypeFromTypeNode(node);
37601        }
37602
37603        function checkImportType(node: ImportTypeNode) {
37604            checkSourceElement(node.argument);
37605
37606            if (node.assertions) {
37607                const override = getResolutionModeOverrideForClause(node.assertions.assertClause, grammarErrorOnNode);
37608                if (override) {
37609                    if (!isNightly()) {
37610                        grammarErrorOnNode(node.assertions.assertClause, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next);
37611                    }
37612                    if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) {
37613                        grammarErrorOnNode(node.assertions.assertClause, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext);
37614                    }
37615                }
37616            }
37617
37618            getTypeFromTypeNode(node);
37619        }
37620
37621        function checkNamedTupleMember(node: NamedTupleMember) {
37622            if (node.dotDotDotToken && node.questionToken) {
37623                grammarErrorOnNode(node, Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest);
37624            }
37625            if (node.type.kind === SyntaxKind.OptionalType) {
37626                grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type);
37627            }
37628            if (node.type.kind === SyntaxKind.RestType) {
37629                grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type);
37630            }
37631            checkSourceElement(node.type);
37632            getTypeFromTypeNode(node);
37633        }
37634
37635        function isPrivateWithinAmbient(node: Node): boolean {
37636            return (hasEffectiveModifier(node, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(node)) && !!(node.flags & NodeFlags.Ambient);
37637        }
37638
37639        function getEffectiveDeclarationFlags(n: Declaration, flagsToCheck: ModifierFlags): ModifierFlags {
37640            let flags = getCombinedModifierFlags(n);
37641
37642            // children of classes (even ambient classes) should not be marked as ambient or export
37643            // because those flags have no useful semantics there.
37644            if (n.parent.kind !== SyntaxKind.InterfaceDeclaration &&
37645                n.parent.kind !== SyntaxKind.ClassDeclaration &&
37646                n.parent.kind !== SyntaxKind.ClassExpression &&
37647                n.flags & NodeFlags.Ambient) {
37648                if (!(flags & ModifierFlags.Ambient) && !(isModuleBlock(n.parent) && isModuleDeclaration(n.parent.parent) && isGlobalScopeAugmentation(n.parent.parent))) {
37649                    // It is nested in an ambient context, which means it is automatically exported
37650                    flags |= ModifierFlags.Export;
37651                }
37652                flags |= ModifierFlags.Ambient;
37653            }
37654
37655            return flags & flagsToCheck;
37656        }
37657
37658        function checkFunctionOrConstructorSymbol(symbol: Symbol): void {
37659            addLazyDiagnostic(() => checkFunctionOrConstructorSymbolWorker(symbol));
37660        }
37661
37662        function checkFunctionOrConstructorSymbolWorker(symbol: Symbol): void {
37663            function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined): Declaration {
37664                // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration
37665                // Error on all deviations from this canonical set of flags
37666                // The caveat is that if some overloads are defined in lib.d.ts, we don't want to
37667                // report the errors on those. To achieve this, we will say that the implementation is
37668                // the canonical signature only if it is in the same container as the first overload
37669                const implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
37670                return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
37671            }
37672
37673            function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void {
37674                // Error if some overloads have a flag that is not shared by all overloads. To find the
37675                // deviations, we XOR someOverloadFlags with allOverloadFlags
37676                const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
37677                if (someButNotAllOverloadFlags !== 0) {
37678                    const canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);
37679                    forEach(overloads, o => {
37680                        const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
37681                        if (deviation & ModifierFlags.Export) {
37682                            error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported);
37683                        }
37684                        else if (deviation & ModifierFlags.Ambient) {
37685                            error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
37686                        }
37687                        else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) {
37688                            error(getNameOfDeclaration(o) || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
37689                        }
37690                        else if (deviation & ModifierFlags.Abstract) {
37691                            error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract);
37692                        }
37693                    });
37694                }
37695            }
37696
37697            function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void {
37698                if (someHaveQuestionToken !== allHaveQuestionToken) {
37699                    const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation));
37700                    forEach(overloads, o => {
37701                        const deviation = hasQuestionToken(o) !== canonicalHasQuestionToken;
37702                        if (deviation) {
37703                            error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_optional_or_required);
37704                        }
37705                    });
37706                }
37707            }
37708
37709            const flagsToCheck: ModifierFlags = ModifierFlags.Export | ModifierFlags.Ambient | ModifierFlags.Private | ModifierFlags.Protected | ModifierFlags.Abstract;
37710            let someNodeFlags: ModifierFlags = ModifierFlags.None;
37711            let allNodeFlags = flagsToCheck;
37712            let someHaveQuestionToken = false;
37713            let allHaveQuestionToken = true;
37714            let hasOverloads = false;
37715            let bodyDeclaration: FunctionLikeDeclaration | undefined;
37716            let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration | undefined;
37717            let previousDeclaration: SignatureDeclaration | undefined;
37718
37719            const declarations = symbol.declarations;
37720            const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0;
37721
37722            function reportImplementationExpectedError(node: SignatureDeclaration): void {
37723                if (node.name && nodeIsMissing(node.name)) {
37724                    return;
37725                }
37726
37727                let seen = false;
37728                const subsequentNode = forEachChild(node.parent, c => {
37729                    if (seen) {
37730                        return c;
37731                    }
37732                    else {
37733                        seen = c === node;
37734                    }
37735                });
37736                // We may be here because of some extra nodes between overloads that could not be parsed into a valid node.
37737                // In this case the subsequent node is not really consecutive (.pos !== node.end), and we must ignore it here.
37738                if (subsequentNode && subsequentNode.pos === node.end) {
37739                    if (subsequentNode.kind === node.kind) {
37740                        const errorNode: Node = (subsequentNode as FunctionLikeDeclaration).name || subsequentNode;
37741                        const subsequentName = (subsequentNode as FunctionLikeDeclaration).name;
37742                        if (node.name && subsequentName && (
37743                            // both are private identifiers
37744                            isPrivateIdentifier(node.name) && isPrivateIdentifier(subsequentName) && node.name.escapedText === subsequentName.escapedText ||
37745                            // Both are computed property names
37746                            // TODO: GH#17345: These are methods, so handle computed name case. (`Always allowing computed property names is *not* the correct behavior!)
37747                            isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) ||
37748                            // Both are literal property names that are the same.
37749                            isPropertyNameLiteral(node.name) && isPropertyNameLiteral(subsequentName) &&
37750                            getEscapedTextOfIdentifierOrLiteral(node.name) === getEscapedTextOfIdentifierOrLiteral(subsequentName)
37751                        )) {
37752                            const reportError =
37753                                (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) &&
37754                                isStatic(node) !== isStatic(subsequentNode);
37755                            // we can get here in two cases
37756                            // 1. mixed static and instance class members
37757                            // 2. something with the same name was defined before the set of overloads that prevents them from merging
37758                            // here we'll report error only for the first case since for second we should already report error in binder
37759                            if (reportError) {
37760                                const diagnostic = isStatic(node) ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static;
37761                                error(errorNode, diagnostic);
37762                            }
37763                            return;
37764                        }
37765                        if (nodeIsPresent((subsequentNode as FunctionLikeDeclaration).body)) {
37766                            error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name));
37767                            return;
37768                        }
37769                    }
37770                }
37771                const errorNode: Node = node.name || node;
37772                if (isConstructor) {
37773                    error(errorNode, Diagnostics.Constructor_implementation_is_missing);
37774                }
37775                else {
37776                    // Report different errors regarding non-consecutive blocks of declarations depending on whether
37777                    // the node in question is abstract.
37778                    if (hasSyntacticModifier(node, ModifierFlags.Abstract)) {
37779                        error(errorNode, Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive);
37780                    }
37781                    else {
37782                        error(errorNode, Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration);
37783                    }
37784                }
37785            }
37786
37787            let duplicateFunctionDeclaration = false;
37788            let multipleConstructorImplementation = false;
37789            let hasNonAmbientClass = false;
37790            const functionDeclarations = [] as Declaration[];
37791            if (declarations) {
37792                for (const current of declarations) {
37793                    const node = current as SignatureDeclaration | ClassDeclaration | ClassExpression;
37794                    const inAmbientContext = node.flags & NodeFlags.Ambient;
37795                    const inAmbientContextOrInterface = node.parent && (node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral) || inAmbientContext;
37796                    if (inAmbientContextOrInterface) {
37797                        // check if declarations are consecutive only if they are non-ambient
37798                        // 1. ambient declarations can be interleaved
37799                        // i.e. this is legal
37800                        //     declare function foo();
37801                        //     declare function bar();
37802                        //     declare function foo();
37803                        // 2. mixing ambient and non-ambient declarations is a separate error that will be reported - do not want to report an extra one
37804                        previousDeclaration = undefined;
37805                    }
37806
37807                    if ((node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) && !inAmbientContext) {
37808                        hasNonAmbientClass = true;
37809                    }
37810
37811                    if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor) {
37812                        functionDeclarations.push(node);
37813                        const currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
37814                        someNodeFlags |= currentNodeFlags;
37815                        allNodeFlags &= currentNodeFlags;
37816                        someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node);
37817                        allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node);
37818                        const bodyIsPresent = nodeIsPresent((node as FunctionLikeDeclaration).body);
37819
37820                        if (bodyIsPresent && bodyDeclaration) {
37821                            if (isConstructor) {
37822                                multipleConstructorImplementation = true;
37823                            }
37824                            else {
37825                                duplicateFunctionDeclaration = true;
37826                            }
37827                        }
37828                        else if (previousDeclaration?.parent === node.parent && previousDeclaration.end !== node.pos) {
37829                            reportImplementationExpectedError(previousDeclaration);
37830                        }
37831
37832                        if (bodyIsPresent) {
37833                            if (!bodyDeclaration) {
37834                                bodyDeclaration = node as FunctionLikeDeclaration;
37835                            }
37836                        }
37837                        else {
37838                            hasOverloads = true;
37839                        }
37840
37841                        previousDeclaration = node;
37842
37843                        if (!inAmbientContextOrInterface) {
37844                            lastSeenNonAmbientDeclaration = node as FunctionLikeDeclaration;
37845                        }
37846                    }
37847                }
37848            }
37849
37850            if (multipleConstructorImplementation) {
37851                forEach(functionDeclarations, declaration => {
37852                    error(declaration, Diagnostics.Multiple_constructor_implementations_are_not_allowed);
37853                });
37854            }
37855
37856            if (duplicateFunctionDeclaration) {
37857                forEach(functionDeclarations, declaration => {
37858                    error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Duplicate_function_implementation);
37859                });
37860            }
37861
37862            if (hasNonAmbientClass && !isConstructor && symbol.flags & SymbolFlags.Function && declarations) {
37863                const relatedDiagnostics = filter(declarations, d => d.kind === SyntaxKind.ClassDeclaration)
37864                    .map(d => createDiagnosticForNode(d, Diagnostics.Consider_adding_a_declare_modifier_to_this_class));
37865
37866                forEach(declarations, declaration => {
37867                    const diagnostic = declaration.kind === SyntaxKind.ClassDeclaration
37868                            ? Diagnostics.Class_declaration_cannot_implement_overload_list_for_0
37869                            : declaration.kind === SyntaxKind.FunctionDeclaration
37870                                ? Diagnostics.Function_with_bodies_can_only_merge_with_classes_that_are_ambient
37871                                : undefined;
37872                    if (diagnostic) {
37873                        addRelatedInfo(
37874                            error(getNameOfDeclaration(declaration) || declaration, diagnostic, symbolName(symbol)),
37875                            ...relatedDiagnostics
37876                        );
37877                    }
37878                });
37879            }
37880
37881            // Abstract methods can't have an implementation -- in particular, they don't need one.
37882            if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
37883                !hasSyntacticModifier(lastSeenNonAmbientDeclaration, ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) {
37884                reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
37885            }
37886
37887            if (hasOverloads) {
37888                if (declarations) {
37889                    checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags);
37890                    checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken);
37891                }
37892
37893                if (bodyDeclaration) {
37894                    const signatures = getSignaturesOfSymbol(symbol);
37895                    const bodySignature = getSignatureFromDeclaration(bodyDeclaration);
37896                    for (const signature of signatures) {
37897                        if (!isImplementationCompatibleWithOverload(bodySignature, signature)) {
37898                            addRelatedInfo(
37899                                error(signature.declaration, Diagnostics.This_overload_signature_is_not_compatible_with_its_implementation_signature),
37900                                createDiagnosticForNode(bodyDeclaration, Diagnostics.The_implementation_signature_is_declared_here)
37901                            );
37902                            break;
37903                        }
37904                    }
37905                }
37906            }
37907        }
37908
37909        function checkExportsOnMergedDeclarations(node: Declaration): void {
37910            addLazyDiagnostic(() => checkExportsOnMergedDeclarationsWorker(node));
37911        }
37912
37913        function checkExportsOnMergedDeclarationsWorker(node: Declaration): void {
37914            // if localSymbol is defined on node then node itself is exported - check is required
37915            let symbol = node.localSymbol;
37916            if (!symbol) {
37917                // local symbol is undefined => this declaration is non-exported.
37918                // however symbol might contain other declarations that are exported
37919                symbol = getSymbolOfNode(node)!;
37920                if (!symbol.exportSymbol) {
37921                    // this is a pure local symbol (all declarations are non-exported) - no need to check anything
37922                    return;
37923                }
37924            }
37925
37926            // run the check only for the first declaration in the list
37927            if (getDeclarationOfKind(symbol, node.kind) !== node) {
37928                return;
37929            }
37930
37931            let exportedDeclarationSpaces = DeclarationSpaces.None;
37932            let nonExportedDeclarationSpaces = DeclarationSpaces.None;
37933            let defaultExportedDeclarationSpaces = DeclarationSpaces.None;
37934            for (const d of symbol.declarations!) {
37935                const declarationSpaces = getDeclarationSpaces(d);
37936                const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default);
37937
37938                if (effectiveDeclarationFlags & ModifierFlags.Export) {
37939                    if (effectiveDeclarationFlags & ModifierFlags.Default) {
37940                        defaultExportedDeclarationSpaces |= declarationSpaces;
37941                    }
37942                    else {
37943                        exportedDeclarationSpaces |= declarationSpaces;
37944                    }
37945                }
37946                else {
37947                    nonExportedDeclarationSpaces |= declarationSpaces;
37948                }
37949            }
37950
37951            // Spaces for anything not declared a 'default export'.
37952            const nonDefaultExportedDeclarationSpaces = exportedDeclarationSpaces | nonExportedDeclarationSpaces;
37953
37954            const commonDeclarationSpacesForExportsAndLocals = exportedDeclarationSpaces & nonExportedDeclarationSpaces;
37955            const commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces & nonDefaultExportedDeclarationSpaces;
37956
37957            if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) {
37958                // declaration spaces for exported and non-exported declarations intersect
37959                for (const d of symbol.declarations!) {
37960                    const declarationSpaces = getDeclarationSpaces(d);
37961
37962                    const name = getNameOfDeclaration(d);
37963                    // Only error on the declarations that contributed to the intersecting spaces.
37964                    if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) {
37965                        error(name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(name));
37966                    }
37967                    else if (declarationSpaces & commonDeclarationSpacesForExportsAndLocals) {
37968                        error(name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(name));
37969                    }
37970                }
37971            }
37972
37973            function getDeclarationSpaces(decl: Declaration): DeclarationSpaces {
37974                let d = decl as Node;
37975                switch (d.kind) {
37976                    case SyntaxKind.InterfaceDeclaration:
37977                    case SyntaxKind.TypeAliasDeclaration:
37978
37979                    // A jsdoc typedef and callback are, by definition, type aliases.
37980                    // falls through
37981                    case SyntaxKind.JSDocTypedefTag:
37982                    case SyntaxKind.JSDocCallbackTag:
37983                    case SyntaxKind.JSDocEnumTag:
37984                        return DeclarationSpaces.ExportType;
37985                    case SyntaxKind.ModuleDeclaration:
37986                        return isAmbientModule(d as ModuleDeclaration) || getModuleInstanceState(d as ModuleDeclaration) !== ModuleInstanceState.NonInstantiated
37987                            ? DeclarationSpaces.ExportNamespace | DeclarationSpaces.ExportValue
37988                            : DeclarationSpaces.ExportNamespace;
37989                    case SyntaxKind.ClassDeclaration:
37990                    case SyntaxKind.StructDeclaration:
37991                    case SyntaxKind.AnnotationDeclaration:
37992                    case SyntaxKind.EnumDeclaration:
37993                    case SyntaxKind.EnumMember:
37994                        return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue;
37995                    case SyntaxKind.SourceFile:
37996                        return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue | DeclarationSpaces.ExportNamespace;
37997                    case SyntaxKind.ExportAssignment:
37998                    case SyntaxKind.BinaryExpression:
37999                        const node = d as ExportAssignment | BinaryExpression;
38000                        const expression = isExportAssignment(node) ? node.expression : node.right;
38001                        // Export assigned entity name expressions act as aliases and should fall through, otherwise they export values
38002                        if (!isEntityNameExpression(expression)) {
38003                            return DeclarationSpaces.ExportValue;
38004                        }
38005                        d = expression;
38006
38007                    // The below options all declare an Alias, which is allowed to merge with other values within the importing module.
38008                    // falls through
38009                    case SyntaxKind.ImportEqualsDeclaration:
38010                    case SyntaxKind.NamespaceImport:
38011                    case SyntaxKind.ImportClause:
38012                        let result = DeclarationSpaces.None;
38013                        const target = resolveAlias(getSymbolOfNode(d)!);
38014                        forEach(target.declarations, d => {
38015                            result |= getDeclarationSpaces(d);
38016                        });
38017                        return result;
38018                    case SyntaxKind.VariableDeclaration:
38019                    case SyntaxKind.BindingElement:
38020                    case SyntaxKind.FunctionDeclaration:
38021                    case SyntaxKind.ImportSpecifier: // https://github.com/Microsoft/TypeScript/pull/7591
38022                    case SyntaxKind.Identifier: // https://github.com/microsoft/TypeScript/issues/36098
38023                    // Identifiers are used as declarations of assignment declarations whose parents may be
38024                    // SyntaxKind.CallExpression - `Object.defineProperty(thing, "aField", {value: 42});`
38025                    // SyntaxKind.ElementAccessExpression - `thing["aField"] = 42;` or `thing["aField"];` (with a doc comment on it)
38026                    // or SyntaxKind.PropertyAccessExpression - `thing.aField = 42;`
38027                    // all of which are pretty much always values, or at least imply a value meaning.
38028                    // It may be apprpriate to treat these as aliases in the future.
38029                        return DeclarationSpaces.ExportValue;
38030                    default:
38031                        return Debug.failBadSyntaxKind(d);
38032                }
38033            }
38034        }
38035
38036        function getAwaitedTypeOfPromise(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined {
38037            const promisedType = getPromisedTypeOfPromise(type, errorNode);
38038            return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
38039        }
38040
38041        /**
38042         * Gets the "promised type" of a promise.
38043         * @param type The type of the promise.
38044         * @remarks The "promised type" of a type is the type of the "value" parameter of the "onfulfilled" callback.
38045         */
38046        function getPromisedTypeOfPromise(type: Type, errorNode?: Node, thisTypeForErrorOut?: { value?: Type }): Type | undefined {
38047            //
38048            //  { // type
38049            //      then( // thenFunction
38050            //          onfulfilled: ( // onfulfilledParameterType
38051            //              value: T // valueParameterType
38052            //          ) => any
38053            //      ): any;
38054            //  }
38055            //
38056
38057            if (isTypeAny(type)) {
38058                return undefined;
38059            }
38060
38061            const typeAsPromise = type as PromiseOrAwaitableType;
38062            if (typeAsPromise.promisedTypeOfPromise) {
38063                return typeAsPromise.promisedTypeOfPromise;
38064            }
38065
38066            if (isReferenceToType(type, getGlobalPromiseType(/*reportErrors*/ false))) {
38067                return typeAsPromise.promisedTypeOfPromise = getTypeArguments(type as GenericType)[0];
38068            }
38069
38070            // primitives with a `{ then() }` won't be unwrapped/adopted.
38071            if (allTypesAssignableToKind(getBaseConstraintOrType(type), TypeFlags.Primitive | TypeFlags.Never)) {
38072                return undefined;
38073            }
38074
38075            const thenFunction = getTypeOfPropertyOfType(type, "then" as __String)!; // TODO: GH#18217
38076            if (isTypeAny(thenFunction)) {
38077                return undefined;
38078            }
38079
38080            const thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, SignatureKind.Call) : emptyArray;
38081            if (thenSignatures.length === 0) {
38082                if (errorNode) {
38083                    error(errorNode, Diagnostics.A_promise_must_have_a_then_method);
38084                }
38085                return undefined;
38086            }
38087
38088            let thisTypeForError: Type | undefined;
38089            let candidates: Signature[] | undefined;
38090            for (const thenSignature of thenSignatures) {
38091                const thisType = getThisTypeOfSignature(thenSignature);
38092                if (thisType && thisType !== voidType && !isTypeRelatedTo(type, thisType, subtypeRelation)) {
38093                    thisTypeForError = thisType;
38094                }
38095                else {
38096                    candidates = append(candidates, thenSignature);
38097                }
38098            }
38099
38100            if (!candidates) {
38101                Debug.assertIsDefined(thisTypeForError);
38102                if (thisTypeForErrorOut) {
38103                    thisTypeForErrorOut.value = thisTypeForError;
38104                }
38105                if (errorNode) {
38106                    error(errorNode, Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForError));
38107                }
38108                return undefined;
38109            }
38110
38111            const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(candidates, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull);
38112            if (isTypeAny(onfulfilledParameterType)) {
38113                return undefined;
38114            }
38115
38116            const onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call);
38117            if (onfulfilledParameterSignatures.length === 0) {
38118                if (errorNode) {
38119                    error(errorNode, Diagnostics.The_first_parameter_of_the_then_method_of_a_promise_must_be_a_callback);
38120                }
38121                return undefined;
38122            }
38123
38124            return typeAsPromise.promisedTypeOfPromise = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), UnionReduction.Subtype);
38125        }
38126
38127        /**
38128         * Gets the "awaited type" of a type.
38129         * @param type The type to await.
38130         * @param withAlias When `true`, wraps the "awaited type" in `Awaited<T>` if needed.
38131         * @remarks The "awaited type" of an expression is its "promised type" if the expression is a
38132         * Promise-like type; otherwise, it is the type of the expression. This is used to reflect
38133         * The runtime behavior of the `await` keyword.
38134         */
38135        function checkAwaitedType(type: Type, withAlias: boolean, errorNode: Node, diagnosticMessage: DiagnosticMessage, arg0?: string | number): Type {
38136            const awaitedType = withAlias ?
38137                getAwaitedType(type, errorNode, diagnosticMessage, arg0) :
38138                getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, arg0);
38139            return awaitedType || errorType;
38140        }
38141
38142        /**
38143         * Determines whether a type is an object with a callable `then` member.
38144         */
38145        function isThenableType(type: Type): boolean {
38146            if (allTypesAssignableToKind(getBaseConstraintOrType(type), TypeFlags.Primitive | TypeFlags.Never)) {
38147                // primitive types cannot be considered "thenable" since they are not objects.
38148                return false;
38149            }
38150
38151            const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
38152            return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0;
38153        }
38154
38155        interface AwaitedTypeInstantiation extends Type {
38156            _awaitedTypeBrand: never;
38157            aliasSymbol: Symbol;
38158            aliasTypeArguments: readonly Type[];
38159        }
38160
38161        function isAwaitedTypeInstantiation(type: Type): type is AwaitedTypeInstantiation {
38162            if (type.flags & TypeFlags.Conditional) {
38163                const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
38164                return !!awaitedSymbol && type.aliasSymbol === awaitedSymbol && type.aliasTypeArguments?.length === 1;
38165            }
38166            return false;
38167        }
38168
38169        /**
38170         * For a generic `Awaited<T>`, gets `T`.
38171         */
38172        function unwrapAwaitedType(type: Type) {
38173            return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) :
38174                isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] :
38175                type;
38176        }
38177
38178        function isAwaitedTypeNeeded(type: Type) {
38179            // If this is already an `Awaited<T>`, we shouldn't wrap it. This helps to avoid `Awaited<Awaited<T>>` in higher-order.
38180            if (isTypeAny(type) || isAwaitedTypeInstantiation(type)) {
38181                return false;
38182            }
38183
38184            // We only need `Awaited<T>` if `T` contains possibly non-primitive types.
38185            if (isGenericObjectType(type)) {
38186                const baseConstraint = getBaseConstraintOfType(type);
38187                // We only need `Awaited<T>` if `T` is a type variable that has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`,
38188                // or is promise-like.
38189                if (baseConstraint ?
38190                    baseConstraint.flags & TypeFlags.AnyOrUnknown || isEmptyObjectType(baseConstraint) || someType(baseConstraint, isThenableType) :
38191                    maybeTypeOfKind(type, TypeFlags.TypeVariable)) {
38192                    return true;
38193                }
38194            }
38195
38196            return false;
38197        }
38198
38199        function tryCreateAwaitedType(type: Type): Type | undefined {
38200            // Nothing to do if `Awaited<T>` doesn't exist
38201            const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ true);
38202            if (awaitedSymbol) {
38203                // Unwrap unions that may contain `Awaited<T>`, otherwise its possible to manufacture an `Awaited<Awaited<T> | U>` where
38204                // an `Awaited<T | U>` would suffice.
38205                return getTypeAliasInstantiation(awaitedSymbol, [unwrapAwaitedType(type)]);
38206            }
38207
38208            return undefined;
38209        }
38210
38211        function createAwaitedTypeIfNeeded(type: Type): Type {
38212            // We wrap type `T` in `Awaited<T>` based on the following conditions:
38213            // - `T` is not already an `Awaited<U>`, and
38214            // - `T` is generic, and
38215            // - One of the following applies:
38216            //   - `T` has no base constraint, or
38217            //   - The base constraint of `T` is `any`, `unknown`, `object`, or `{}`, or
38218            //   - The base constraint of `T` is an object type with a callable `then` method.
38219
38220            if (isAwaitedTypeNeeded(type)) {
38221                const awaitedType = tryCreateAwaitedType(type);
38222                if (awaitedType) {
38223                    return awaitedType;
38224                }
38225            }
38226
38227            Debug.assert(getPromisedTypeOfPromise(type) === undefined, "type provided should not be a non-generic 'promise'-like.");
38228            return type;
38229        }
38230
38231        /**
38232         * Gets the "awaited type" of a type.
38233         *
38234         * The "awaited type" of an expression is its "promised type" if the expression is a
38235         * Promise-like type; otherwise, it is the type of the expression. If the "promised
38236         * type" is itself a Promise-like, the "promised type" is recursively unwrapped until a
38237         * non-promise type is found.
38238         *
38239         * This is used to reflect the runtime behavior of the `await` keyword.
38240         */
38241        function getAwaitedType(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined {
38242            const awaitedType = getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, arg0);
38243            return awaitedType && createAwaitedTypeIfNeeded(awaitedType);
38244        }
38245
38246        /**
38247         * Gets the "awaited type" of a type without introducing an `Awaited<T>` wrapper.
38248         *
38249         * @see {@link getAwaitedType}
38250         */
38251        function getAwaitedTypeNoAlias(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined {
38252            if (isTypeAny(type)) {
38253                return type;
38254            }
38255
38256            // If this is already an `Awaited<T>`, just return it. This avoids `Awaited<Awaited<T>>` in higher-order
38257            if (isAwaitedTypeInstantiation(type)) {
38258                return type;
38259            }
38260
38261            // If we've already cached an awaited type, return a possible `Awaited<T>` for it.
38262            const typeAsAwaitable = type as PromiseOrAwaitableType;
38263            if (typeAsAwaitable.awaitedTypeOfType) {
38264                return typeAsAwaitable.awaitedTypeOfType;
38265            }
38266
38267            // For a union, get a union of the awaited types of each constituent.
38268            if (type.flags & TypeFlags.Union) {
38269                if (awaitedTypeStack.lastIndexOf(type.id) >= 0) {
38270                    if (errorNode) {
38271                        error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
38272                    }
38273                    return undefined;
38274                }
38275
38276                const mapper = errorNode ? (constituentType: Type) => getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedTypeNoAlias;
38277
38278                awaitedTypeStack.push(type.id);
38279                const mapped = mapType(type, mapper);
38280                awaitedTypeStack.pop();
38281
38282                return typeAsAwaitable.awaitedTypeOfType = mapped;
38283            }
38284
38285            // If `type` is generic and should be wrapped in `Awaited<T>`, return it.
38286            if (isAwaitedTypeNeeded(type)) {
38287                return typeAsAwaitable.awaitedTypeOfType = type;
38288            }
38289
38290            const thisTypeForErrorOut: { value: Type | undefined } = { value: undefined };
38291            const promisedType = getPromisedTypeOfPromise(type, /*errorNode*/ undefined, thisTypeForErrorOut);
38292            if (promisedType) {
38293                if (type.id === promisedType.id || awaitedTypeStack.lastIndexOf(promisedType.id) >= 0) {
38294                    // Verify that we don't have a bad actor in the form of a promise whose
38295                    // promised type is the same as the promise type, or a mutually recursive
38296                    // promise. If so, we return undefined as we cannot guess the shape. If this
38297                    // were the actual case in the JavaScript, this Promise would never resolve.
38298                    //
38299                    // An example of a bad actor with a singly-recursive promise type might
38300                    // be:
38301                    //
38302                    //  interface BadPromise {
38303                    //      then(
38304                    //          onfulfilled: (value: BadPromise) => any,
38305                    //          onrejected: (error: any) => any): BadPromise;
38306                    //  }
38307                    //
38308                    // The above interface will pass the PromiseLike check, and return a
38309                    // promised type of `BadPromise`. Since this is a self reference, we
38310                    // don't want to keep recursing ad infinitum.
38311                    //
38312                    // An example of a bad actor in the form of a mutually-recursive
38313                    // promise type might be:
38314                    //
38315                    //  interface BadPromiseA {
38316                    //      then(
38317                    //          onfulfilled: (value: BadPromiseB) => any,
38318                    //          onrejected: (error: any) => any): BadPromiseB;
38319                    //  }
38320                    //
38321                    //  interface BadPromiseB {
38322                    //      then(
38323                    //          onfulfilled: (value: BadPromiseA) => any,
38324                    //          onrejected: (error: any) => any): BadPromiseA;
38325                    //  }
38326                    //
38327                    if (errorNode) {
38328                        error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
38329                    }
38330                    return undefined;
38331                }
38332
38333                // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
38334                // See the comments above for more information.
38335                awaitedTypeStack.push(type.id);
38336                const awaitedType = getAwaitedTypeNoAlias(promisedType, errorNode, diagnosticMessage, arg0);
38337                awaitedTypeStack.pop();
38338
38339                if (!awaitedType) {
38340                    return undefined;
38341                }
38342
38343                return typeAsAwaitable.awaitedTypeOfType = awaitedType;
38344            }
38345
38346            // The type was not a promise, so it could not be unwrapped any further.
38347            // As long as the type does not have a callable "then" property, it is
38348            // safe to return the type; otherwise, an error is reported and we return
38349            // undefined.
38350            //
38351            // An example of a non-promise "thenable" might be:
38352            //
38353            //  await { then(): void {} }
38354            //
38355            // The "thenable" does not match the minimal definition for a promise. When
38356            // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
38357            // will never settle. We treat this as an error to help flag an early indicator
38358            // of a runtime problem. If the user wants to return this value from an async
38359            // function, they would need to wrap it in some other value. If they want it to
38360            // be treated as a promise, they can cast to <any>.
38361            if (isThenableType(type)) {
38362                if (errorNode) {
38363                    Debug.assertIsDefined(diagnosticMessage);
38364                    let chain: DiagnosticMessageChain | undefined;
38365                    if (thisTypeForErrorOut.value) {
38366                        chain = chainDiagnosticMessages(chain, Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForErrorOut.value));
38367                    }
38368                    chain = chainDiagnosticMessages(chain, diagnosticMessage, arg0);
38369                    diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, chain));
38370                }
38371                return undefined;
38372            }
38373
38374            return typeAsAwaitable.awaitedTypeOfType = type;
38375        }
38376
38377        /**
38378         * Checks the return type of an async function to ensure it is a compatible
38379         * Promise implementation.
38380         *
38381         * This checks that an async function has a valid Promise-compatible return type.
38382         * An async function has a valid Promise-compatible return type if the resolved value
38383         * of the return type has a construct signature that takes in an `initializer` function
38384         * that in turn supplies a `resolve` function as one of its arguments and results in an
38385         * object with a callable `then` signature.
38386         *
38387         * @param node The signature to check
38388         */
38389        function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature, returnTypeNode: TypeNode) {
38390            // As part of our emit for an async function, we will need to emit the entity name of
38391            // the return type annotation as an expression. To meet the necessary runtime semantics
38392            // for __awaiter, we must also check that the type of the declaration (e.g. the static
38393            // side or "constructor" of the promise type) is compatible `PromiseConstructorLike`.
38394            //
38395            // An example might be (from lib.es6.d.ts):
38396            //
38397            //  interface Promise<T> { ... }
38398            //  interface PromiseConstructor {
38399            //      new <T>(...): Promise<T>;
38400            //  }
38401            //  declare var Promise: PromiseConstructor;
38402            //
38403            // When an async function declares a return type annotation of `Promise<T>`, we
38404            // need to get the type of the `Promise` variable declaration above, which would
38405            // be `PromiseConstructor`.
38406            //
38407            // The same case applies to a class:
38408            //
38409            //  declare class Promise<T> {
38410            //      constructor(...);
38411            //      then<U>(...): Promise<U>;
38412            //  }
38413            //
38414            const returnType = getTypeFromTypeNode(returnTypeNode);
38415
38416            if (languageVersion >= ScriptTarget.ES2015) {
38417                if (isErrorType(returnType)) {
38418                    return;
38419                }
38420                const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
38421                if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) {
38422                    // The promise type was not a valid type reference to the global promise type, so we
38423                    // report an error and return the unknown type.
38424                    error(returnTypeNode, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, typeToString(getAwaitedTypeNoAlias(returnType) || voidType));
38425                    return;
38426                }
38427            }
38428            else {
38429                // Always mark the type node as referenced if it points to a value
38430                markTypeNodeAsReferenced(returnTypeNode);
38431
38432                if (isErrorType(returnType)) {
38433                    return;
38434                }
38435
38436                const promiseConstructorName = getEntityNameFromTypeNode(returnTypeNode);
38437                if (promiseConstructorName === undefined) {
38438                    error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType));
38439                    return;
38440                }
38441
38442                const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, SymbolFlags.Value, /*ignoreErrors*/ true);
38443                const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : errorType;
38444                if (isErrorType(promiseConstructorType)) {
38445                    if (promiseConstructorName.kind === SyntaxKind.Identifier && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) {
38446                        error(returnTypeNode, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
38447                    }
38448                    else {
38449                        error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
38450                    }
38451                    return;
38452                }
38453
38454                const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(/*reportErrors*/ true);
38455                if (globalPromiseConstructorLikeType === emptyObjectType) {
38456                    // If we couldn't resolve the global PromiseConstructorLike type we cannot verify
38457                    // compatibility with __awaiter.
38458                    error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
38459                    return;
38460                }
38461
38462                if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeNode,
38463                    Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) {
38464                    return;
38465                }
38466
38467                // Verify there is no local declaration that could collide with the promise constructor.
38468                const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName);
38469                const collidingSymbol = getSymbol(node.locals!, rootName.escapedText, SymbolFlags.Value);
38470                if (collidingSymbol) {
38471                    error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions,
38472                        idText(rootName),
38473                        entityNameToString(promiseConstructorName));
38474                    return;
38475                }
38476            }
38477            checkAwaitedType(returnType, /*withAlias*/ false, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
38478        }
38479
38480        /** Check a decorator */
38481        function checkDecorator(node: Decorator): void {
38482            const signature = getResolvedSignature(node);
38483            checkDeprecatedSignature(signature, node);
38484            const returnType = getReturnTypeOfSignature(signature);
38485            if (returnType.flags & TypeFlags.Any) {
38486                return;
38487            }
38488
38489            let headMessage: DiagnosticMessage;
38490            let expectedReturnType: Type;
38491            switch (node.parent.kind) {
38492                case SyntaxKind.ClassDeclaration:
38493                case SyntaxKind.StructDeclaration:
38494                    headMessage = Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1;
38495                    const classSymbol = getSymbolOfNode(node.parent);
38496                    const classConstructorType = getTypeOfSymbol(classSymbol);
38497                    expectedReturnType = getUnionType([classConstructorType, voidType]);
38498                    break;
38499
38500                case SyntaxKind.PropertyDeclaration:
38501                case SyntaxKind.Parameter:
38502                    headMessage = Diagnostics.Decorator_function_return_type_is_0_but_is_expected_to_be_void_or_any;
38503                    expectedReturnType = voidType;
38504                    break;
38505
38506                case SyntaxKind.MethodDeclaration:
38507                case SyntaxKind.GetAccessor:
38508                case SyntaxKind.SetAccessor:
38509                    headMessage = Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1;
38510                    const methodType = getTypeOfNode(node.parent);
38511                    const descriptorType = createTypedPropertyDescriptorType(methodType);
38512                    expectedReturnType = getUnionType([descriptorType, voidType]);
38513                    break;
38514
38515                default:
38516                    return Debug.fail();
38517            }
38518
38519            checkTypeAssignableTo(
38520                returnType,
38521                expectedReturnType,
38522                node,
38523                headMessage);
38524        }
38525
38526        /**
38527         * If a TypeNode can be resolved to a value symbol imported from an external module, it is
38528         * marked as referenced to prevent import elision.
38529         */
38530        function markTypeNodeAsReferenced(node: TypeNode) {
38531            markEntityNameOrEntityExpressionAsReference(node && getEntityNameFromTypeNode(node), /*forDecoratorMetadata*/ false);
38532        }
38533
38534        function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression | undefined, forDecoratorMetadata: boolean) {
38535            if (!typeName) return;
38536
38537            const rootName = getFirstIdentifier(typeName);
38538            const meaning = (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias;
38539            const rootSymbol = resolveName(rootName, rootName.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isReference*/ true);
38540            if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) {
38541                if (symbolIsValue(rootSymbol)
38542                    && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))
38543                    && !getTypeOnlyAliasDeclaration(rootSymbol)) {
38544                    markAliasSymbolAsReferenced(rootSymbol);
38545                }
38546                else if (forDecoratorMetadata
38547                    && compilerOptions.isolatedModules
38548                    && getEmitModuleKind(compilerOptions) >= ModuleKind.ES2015
38549                    && !symbolIsValue(rootSymbol)
38550                    && !some(rootSymbol.declarations, isTypeOnlyImportOrExportDeclaration)) {
38551                    const diag = error(typeName, Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled);
38552                    const aliasDeclaration = find(rootSymbol.declarations || emptyArray, isAliasSymbolDeclaration);
38553                    if (aliasDeclaration) {
38554                        addRelatedInfo(diag, createDiagnosticForNode(aliasDeclaration, Diagnostics._0_was_imported_here, idText(rootName)));
38555                    }
38556                }
38557            }
38558        }
38559
38560        /**
38561         * This function marks the type used for metadata decorator as referenced if it is import
38562         * from external module.
38563         * This is different from markTypeNodeAsReferenced because it tries to simplify type nodes in
38564         * union and intersection type
38565         * @param node
38566         */
38567        function markDecoratorMedataDataTypeNodeAsReferenced(node: TypeNode | undefined): void {
38568            const entityName = getEntityNameForDecoratorMetadata(node);
38569            if (entityName && isEntityName(entityName)) {
38570                markEntityNameOrEntityExpressionAsReference(entityName, /*forDecoratorMetadata*/ true);
38571            }
38572        }
38573
38574        function getEntityNameForDecoratorMetadata(node: TypeNode | undefined): EntityName | undefined {
38575            if (node) {
38576                switch (node.kind) {
38577                    case SyntaxKind.IntersectionType:
38578                    case SyntaxKind.UnionType:
38579                        return getEntityNameForDecoratorMetadataFromTypeList((node as UnionOrIntersectionTypeNode).types);
38580
38581                    case SyntaxKind.ConditionalType:
38582                        return getEntityNameForDecoratorMetadataFromTypeList([(node as ConditionalTypeNode).trueType, (node as ConditionalTypeNode).falseType]);
38583
38584                    case SyntaxKind.ParenthesizedType:
38585                    case SyntaxKind.NamedTupleMember:
38586                        return getEntityNameForDecoratorMetadata((node as ParenthesizedTypeNode).type);
38587
38588                    case SyntaxKind.TypeReference:
38589                        return (node as TypeReferenceNode).typeName;
38590                }
38591            }
38592        }
38593
38594        function getEntityNameForDecoratorMetadataFromTypeList(types: readonly TypeNode[]): EntityName | undefined {
38595            let commonEntityName: EntityName | undefined;
38596            for (let typeNode of types) {
38597                while (typeNode.kind === SyntaxKind.ParenthesizedType || typeNode.kind === SyntaxKind.NamedTupleMember) {
38598                    typeNode = (typeNode as ParenthesizedTypeNode | NamedTupleMember).type; // Skip parens if need be
38599                }
38600                if (typeNode.kind === SyntaxKind.NeverKeyword) {
38601                    continue; // Always elide `never` from the union/intersection if possible
38602                }
38603                if (!strictNullChecks && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) {
38604                    continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks
38605                }
38606                const individualEntityName = getEntityNameForDecoratorMetadata(typeNode);
38607                if (!individualEntityName) {
38608                    // Individual is something like string number
38609                    // So it would be serialized to either that type or object
38610                    // Safe to return here
38611                    return undefined;
38612                }
38613
38614                if (commonEntityName) {
38615                    // Note this is in sync with the transformation that happens for type node.
38616                    // Keep this in sync with serializeUnionOrIntersectionType
38617                    // Verify if they refer to same entity and is identifier
38618                    // return undefined if they dont match because we would emit object
38619                    if (!isIdentifier(commonEntityName) ||
38620                        !isIdentifier(individualEntityName) ||
38621                        commonEntityName.escapedText !== individualEntityName.escapedText) {
38622                        return undefined;
38623                    }
38624                }
38625                else {
38626                    commonEntityName = individualEntityName;
38627                }
38628            }
38629            return commonEntityName;
38630        }
38631
38632        function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode | undefined {
38633            const typeNode = getEffectiveTypeAnnotationNode(node);
38634            return isRestParameter(node) ? getRestParameterElementType(typeNode) : typeNode;
38635        }
38636
38637        function checkIdentifierJsDoc(node: Identifier, sourceSymbol: Symbol): void {
38638            if (node.virtual || !jsDocFileCheckInfo.fileNeedCheck || !getJsDocNodeCheckedConfig) {
38639                return;
38640            }
38641            if (!sourceSymbol || !sourceSymbol.valueDeclaration) {
38642                return;
38643            }
38644            const sourceSymbolSourceFile = getSourceFileOfNode(sourceSymbol.valueDeclaration);
38645            if (!sourceSymbolSourceFile) {
38646                return;
38647            }
38648            const sourceFile = getSourceFileOfNode(node);
38649            const checkParam = getJsDocNodeCheckedConfig(jsDocFileCheckInfo, sourceSymbolSourceFile.fileName);
38650            if (!checkParam.nodeNeedCheck) {
38651                return;
38652            }
38653
38654            sourceSymbol.declarations?.forEach(declaration => {
38655                expressionCheckByJsDoc(declaration, node, sourceFile, checkParam.checkConfig);
38656            });
38657        }
38658
38659        /** Check the annotation of a node */
38660        function checkAnnotation(annotation: Annotation, annotationsSet: Set<String>): void {
38661            const signature = getResolvedSignature(annotation);
38662            const returnType = getReturnTypeOfSignature(signature);
38663            if (isErrorType(returnType)) {
38664                return;
38665            }
38666
38667            const annotatedDecl = annotation.parent;
38668
38669            // Only classes or methods must be annotated
38670            if (!isClassDeclaration(annotatedDecl) && !isMethodDeclaration(annotatedDecl)) {
38671                const nodeStr = getTextOfNode(annotatedDecl, /*includeTrivia*/ false);
38672                error(annotation, Diagnostics.Annotation_have_to_be_applied_for_classes_or_methods_only_got_Colon_0, nodeStr);
38673                return;
38674            }
38675
38676            // Prohibit application of annotation for abstract classes and methods
38677            if (hasSyntacticModifier(annotatedDecl, ModifierFlags.Abstract)) {
38678                const nodeStr = getTextOfNode(annotatedDecl, /*includeTrivia*/ false);
38679                error(annotation, Diagnostics.Annotation_have_to_be_applied_only_for_non_abstract_class_declarations_and_method_declarations_in_non_abstract_classes_got_Colon_0, nodeStr);
38680                return;
38681            }
38682
38683            switch (annotatedDecl.kind) {
38684                case SyntaxKind.ClassDeclaration:
38685                    break;
38686                case SyntaxKind.MethodDeclaration:
38687                    const enclosingDecl = annotatedDecl.parent;
38688                    Debug.assert(isClassDeclaration(enclosingDecl));
38689
38690                    /* abstract class C {
38691                     *    @goo
38692                     *    puiblic foo(){}
38693                     * }
38694                     */
38695                    if (hasSyntacticModifier(enclosingDecl, ModifierFlags.Abstract)) {
38696                        const nodeStr = getTextOfNode(enclosingDecl, /*includeTrivia*/ false);
38697                        error(annotation, Diagnostics.Annotation_have_to_be_applied_only_for_non_abstract_class_declarations_and_method_declarations_in_non_abstract_classes_got_Colon_0, nodeStr);
38698                    }
38699                    break;
38700                default:
38701                    Debug.fail();
38702            }
38703
38704            // Check duplication
38705
38706            Debug.assert(annotation.annotationDeclaration);
38707            const typeName = typeToString(getTypeOfSymbol(getSymbolOfNode(annotation.annotationDeclaration)), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
38708            if (annotationsSet.size && annotationsSet.has(typeName)) {
38709                const nodeStr = getTextOfNode(annotation, /*includeTrivia*/ false);
38710                error(annotation, Diagnostics.Repeatable_annotation_are_not_supported_got_Colon_0, nodeStr);
38711                return;
38712            }
38713            else {
38714                annotationsSet.add(typeName);
38715            }
38716        }
38717
38718        /** Returns declaration which is related to an annotation */
38719        function getAnnotationDeclaration(da: Decorator | Annotation): AnnotationDeclaration | undefined {
38720            let ident;
38721            switch (da.expression.kind) {
38722                case SyntaxKind.Identifier:
38723                    ident = da.expression as Identifier;
38724                    break;
38725                case SyntaxKind.PropertyAccessExpression:
38726                    ident = da.expression as PropertyAccessExpression;
38727                    break;
38728                case SyntaxKind.CallExpression:
38729                    ident = getIdentifierFromEntityNameExpression((da.expression as CallExpression).expression);
38730                    break;
38731                default:
38732                    return undefined;
38733            }
38734            if (!ident) {
38735                return undefined;
38736            }
38737            const symbol = getSymbolOfNameOrPropertyAccessExpression(ident, /*ignoreErrors*/ true);
38738            if (!symbol) {
38739                return undefined;
38740            }
38741            const type = getTypeOfSymbolAtLocation(symbol, ident);
38742            if (!type || !type.symbol || !type.symbol.declarations) {
38743                return undefined;
38744            }
38745            if (!isAnnotationDeclaration(type.symbol.declarations[0])) {
38746                return undefined;
38747            }
38748            return type.symbol.declarations[0];
38749        }
38750
38751        /** Check the decorators of a node */
38752        function checkDecorators(node: Node): void {
38753            let atLeastOneDecorator = false;
38754            getAllDecorators(node).forEach(item => {
38755                if (isIdentifier(item.expression)) {
38756                    const symbol = getResolvedSymbol(item.expression);
38757                    if (symbol !== unknownSymbol) {
38758                        checkIdentifierJsDoc(item.expression, symbol);
38759                    }
38760                }
38761                const annotationDecl = getAnnotationDeclaration(item);
38762                if (annotationDecl) {
38763                    (item as Mutable<Decorator>).annotationDeclaration = annotationDecl;
38764                }
38765                else {
38766                    atLeastOneDecorator = true;
38767                }
38768            });
38769
38770            // skip this check for nodes that cannot have decorators. These should have already had an error reported by
38771            // checkGrammarDecorators.
38772            if (!canHaveDecorators(node) || !hasDecorators(node) && !hasAnnotations(node) || !node.modifiers || !nodeCanBeDecorated(node, node.parent, node.parent.parent)) {
38773                return;
38774            }
38775
38776            // Skip checking if we have no at least one decorator
38777            if (atLeastOneDecorator && !compilerOptions.experimentalDecorators) {
38778                error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning);
38779            }
38780
38781            // Accumulator for duplications check
38782            const annotationsSet = new Set<String>();
38783            // Detect annotations and performing specific checks
38784            for (const modifier of node.modifiers) {
38785                if (isAnnotation(modifier)) {
38786                    checkAnnotation(modifier, annotationsSet);
38787                }
38788            }
38789
38790            const firstDecorator = find(node.modifiers, isDecorator);
38791            if (!firstDecorator) {
38792                return;
38793            }
38794
38795            checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.Decorate);
38796            if (node.kind === SyntaxKind.Parameter) {
38797                checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.Param);
38798            }
38799
38800            if (compilerOptions.emitDecoratorMetadata) {
38801                checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.Metadata);
38802
38803                // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator.
38804                switch (node.kind) {
38805                    case SyntaxKind.ClassDeclaration:
38806                        const constructor = getFirstConstructorWithBody(node);
38807                        if (constructor) {
38808                            for (const parameter of constructor.parameters) {
38809                                markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
38810                            }
38811                        }
38812                        break;
38813
38814                    case SyntaxKind.GetAccessor:
38815                    case SyntaxKind.SetAccessor:
38816                        const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
38817                        const otherAccessor = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(node), otherKind);
38818                        markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor));
38819                        break;
38820                    case SyntaxKind.MethodDeclaration:
38821                        for (const parameter of node.parameters) {
38822                            markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
38823                        }
38824
38825                        markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveReturnTypeNode(node));
38826                        break;
38827
38828                    case SyntaxKind.PropertyDeclaration:
38829                        markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveTypeAnnotationNode(node));
38830                        break;
38831
38832                    case SyntaxKind.Parameter:
38833                        markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node));
38834                        const containingSignature = node.parent;
38835                        for (const parameter of containingSignature.parameters) {
38836                            markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
38837                        }
38838                        break;
38839                }
38840            }
38841
38842            for (const modifier of node.modifiers) {
38843                if (isDecorator(modifier)) {
38844                    checkDecorator(modifier);
38845                }
38846            }
38847        }
38848
38849        function checkFunctionDeclaration(node: FunctionDeclaration): void {
38850            addLazyDiagnostic(checkFunctionDeclarationDiagnostics);
38851
38852            function checkFunctionDeclarationDiagnostics() {
38853                checkFunctionOrMethodDeclaration(node);
38854                checkGrammarForGenerator(node);
38855                checkCollisionsForDeclarationName(node, node.name);
38856            }
38857        }
38858
38859        function checkJSDocTypeAliasTag(node: JSDocTypedefTag | JSDocCallbackTag) {
38860            if (!node.typeExpression) {
38861                // If the node had `@property` tags, `typeExpression` would have been set to the first property tag.
38862                error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags);
38863            }
38864
38865            if (node.name) {
38866                checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0);
38867            }
38868            checkSourceElement(node.typeExpression);
38869            checkTypeParameters(getEffectiveTypeParameterDeclarations(node));
38870        }
38871
38872        function checkJSDocTemplateTag(node: JSDocTemplateTag): void {
38873            checkSourceElement(node.constraint);
38874            for (const tp of node.typeParameters) {
38875                checkSourceElement(tp);
38876            }
38877        }
38878
38879        function checkJSDocTypeTag(node: JSDocTypeTag) {
38880            checkSourceElement(node.typeExpression);
38881        }
38882
38883        function checkJSDocLinkLikeTag(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain) {
38884            if (node.name) {
38885                resolveJSDocMemberName(node.name, /*ignoreErrors*/ true);
38886            }
38887        }
38888
38889        function checkJSDocParameterTag(node: JSDocParameterTag) {
38890            checkSourceElement(node.typeExpression);
38891        }
38892        function checkJSDocPropertyTag(node: JSDocPropertyTag) {
38893            checkSourceElement(node.typeExpression);
38894        }
38895
38896        function checkJSDocFunctionType(node: JSDocFunctionType): void {
38897            addLazyDiagnostic(checkJSDocFunctionTypeImplicitAny);
38898            checkSignatureDeclaration(node);
38899
38900            function checkJSDocFunctionTypeImplicitAny() {
38901                if (!node.type && !isJSDocConstructSignature(node)) {
38902                    reportImplicitAny(node, anyType);
38903                }
38904            }
38905        }
38906
38907        function checkJSDocImplementsTag(node: JSDocImplementsTag): void {
38908            const classLike = getEffectiveJSDocHost(node);
38909            if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) {
38910                error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName));
38911            }
38912        }
38913
38914        function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void {
38915            const classLike = getEffectiveJSDocHost(node);
38916            if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) {
38917                error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName));
38918                return;
38919            }
38920
38921            const augmentsTags = getJSDocTags(classLike).filter(isJSDocAugmentsTag);
38922            Debug.assert(augmentsTags.length > 0);
38923            if (augmentsTags.length > 1) {
38924                error(augmentsTags[1], Diagnostics.Class_declarations_cannot_have_more_than_one_augments_or_extends_tag);
38925            }
38926
38927            const name = getIdentifierFromEntityNameExpression(node.class.expression);
38928            const extend = getClassExtendsHeritageElement(classLike);
38929            if (extend) {
38930                const className = getIdentifierFromEntityNameExpression(extend.expression);
38931                if (className && name.escapedText !== className.escapedText) {
38932                    error(name, Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, idText(node.tagName), idText(name), idText(className));
38933                }
38934            }
38935        }
38936
38937        function checkJSDocAccessibilityModifiers(node: JSDocPublicTag | JSDocProtectedTag | JSDocPrivateTag): void {
38938            const host = getJSDocHost(node);
38939            if (host && isPrivateIdentifierClassElementDeclaration(host)) {
38940                error(node, Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier);
38941            }
38942        }
38943
38944        function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier | PrivateIdentifier;
38945        function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateIdentifier | undefined;
38946        function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateIdentifier | undefined {
38947            switch (node.kind) {
38948                case SyntaxKind.Identifier:
38949                    return node as Identifier;
38950                case SyntaxKind.PropertyAccessExpression:
38951                    return (node as PropertyAccessExpression).name;
38952                default:
38953                    return undefined;
38954            }
38955        }
38956
38957        function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration | MethodSignature): void {
38958            checkDecorators(node);
38959            checkSignatureDeclaration(node);
38960            const functionFlags = getFunctionFlags(node);
38961
38962            // Do not use hasDynamicName here, because that returns false for well known symbols.
38963            // We want to perform checkComputedPropertyName for all computed properties, including
38964            // well known symbols.
38965            if (node.name && node.name.kind === SyntaxKind.ComputedPropertyName) {
38966                // This check will account for methods in class/interface declarations,
38967                // as well as accessors in classes/object literals
38968                checkComputedPropertyName(node.name);
38969            }
38970
38971            if (hasBindableName(node)) {
38972                // first we want to check the local symbol that contain this declaration
38973                // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol
38974                // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode
38975                const symbol = getSymbolOfNode(node);
38976                const localSymbol = node.localSymbol || symbol;
38977
38978                // Since the javascript won't do semantic analysis like typescript,
38979                // if the javascript file comes before the typescript file and both contain same name functions,
38980                // checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function.
38981                const firstDeclaration = localSymbol.declarations?.find(
38982                    // Get first non javascript function declaration
38983                    declaration => declaration.kind === node.kind && !(declaration.flags & NodeFlags.JavaScriptFile));
38984
38985                // Only type check the symbol once
38986                if (node === firstDeclaration) {
38987                    checkFunctionOrConstructorSymbol(localSymbol);
38988                }
38989
38990                if (symbol.parent) {
38991                    // run check on export symbol to check that modifiers agree across all exported declarations
38992                    checkFunctionOrConstructorSymbol(symbol);
38993                }
38994            }
38995
38996            const body = node.kind === SyntaxKind.MethodSignature ? undefined : node.body;
38997            checkSourceElement(body);
38998            checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, getReturnTypeFromAnnotation(node));
38999
39000            addLazyDiagnostic(checkFunctionOrMethodDeclarationDiagnostics);
39001
39002            // A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature
39003            if (isInJSFile(node)) {
39004                const typeTag = getJSDocTypeTag(node);
39005                if (typeTag && typeTag.typeExpression && !getContextualCallSignature(getTypeFromTypeNode(typeTag.typeExpression), node)) {
39006                    error(typeTag.typeExpression.type, Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature);
39007                }
39008            }
39009
39010            function checkFunctionOrMethodDeclarationDiagnostics() {
39011                if (!getEffectiveReturnTypeNode(node)) {
39012                    // Report an implicit any error if there is no body, no explicit return type, and node is not a private method
39013                    // in an ambient context
39014                    if (nodeIsMissing(body) && !isPrivateWithinAmbient(node)) {
39015                        reportImplicitAny(node, anyType);
39016                    }
39017
39018                    if (functionFlags & FunctionFlags.Generator && nodeIsPresent(body)) {
39019                        // A generator with a body and no type annotation can still cause errors. It can error if the
39020                        // yielded values have no common supertype, or it can give an implicit any error if it has no
39021                        // yielded values. The only way to trigger these errors is to try checking its return type.
39022                        getReturnTypeOfSignature(getSignatureFromDeclaration(node));
39023                    }
39024                }
39025            }
39026        }
39027
39028        function registerForUnusedIdentifiersCheck(node: PotentiallyUnusedIdentifier): void {
39029            addLazyDiagnostic(registerForUnusedIdentifiersCheckDiagnostics);
39030
39031            function registerForUnusedIdentifiersCheckDiagnostics() {
39032                // May be in a call such as getTypeOfNode that happened to call this. But potentiallyUnusedIdentifiers is only defined in the scope of `checkSourceFile`.
39033                const sourceFile = getSourceFileOfNode(node);
39034                let potentiallyUnusedIdentifiers = allPotentiallyUnusedIdentifiers.get(sourceFile.path);
39035                if (!potentiallyUnusedIdentifiers) {
39036                    potentiallyUnusedIdentifiers = [];
39037                    allPotentiallyUnusedIdentifiers.set(sourceFile.path, potentiallyUnusedIdentifiers);
39038                }
39039                // TODO: GH#22580
39040                // Debug.assert(addToSeen(seenPotentiallyUnusedIdentifiers, getNodeId(node)), "Adding potentially-unused identifier twice");
39041                potentiallyUnusedIdentifiers.push(node);
39042            }
39043        }
39044
39045        type PotentiallyUnusedIdentifier =
39046            | SourceFile | ModuleDeclaration | ClassLikeDeclaration | InterfaceDeclaration
39047            | Block | CaseBlock | ForStatement | ForInStatement | ForOfStatement
39048            | Exclude<SignatureDeclaration, IndexSignatureDeclaration | JSDocFunctionType> | TypeAliasDeclaration
39049            | InferTypeNode;
39050
39051        function checkUnusedIdentifiers(potentiallyUnusedIdentifiers: readonly PotentiallyUnusedIdentifier[], addDiagnostic: AddUnusedDiagnostic) {
39052            for (const node of potentiallyUnusedIdentifiers) {
39053                switch (node.kind) {
39054                    case SyntaxKind.ClassDeclaration:
39055                    case SyntaxKind.ClassExpression:
39056                    case SyntaxKind.StructDeclaration:
39057                        checkUnusedClassMembers(node, addDiagnostic);
39058                        checkUnusedTypeParameters(node, addDiagnostic);
39059                        break;
39060                    case SyntaxKind.SourceFile:
39061                    case SyntaxKind.ModuleDeclaration:
39062                    case SyntaxKind.Block:
39063                    case SyntaxKind.CaseBlock:
39064                    case SyntaxKind.ForStatement:
39065                    case SyntaxKind.ForInStatement:
39066                    case SyntaxKind.ForOfStatement:
39067                        checkUnusedLocalsAndParameters(node, addDiagnostic);
39068                        break;
39069                    case SyntaxKind.Constructor:
39070                    case SyntaxKind.FunctionExpression:
39071                    case SyntaxKind.FunctionDeclaration:
39072                    case SyntaxKind.ArrowFunction:
39073                    case SyntaxKind.MethodDeclaration:
39074                    case SyntaxKind.GetAccessor:
39075                    case SyntaxKind.SetAccessor:
39076                        if (node.body) { // Don't report unused parameters in overloads
39077                            checkUnusedLocalsAndParameters(node, addDiagnostic);
39078                        }
39079                        checkUnusedTypeParameters(node, addDiagnostic);
39080                        break;
39081                    case SyntaxKind.MethodSignature:
39082                    case SyntaxKind.CallSignature:
39083                    case SyntaxKind.ConstructSignature:
39084                    case SyntaxKind.FunctionType:
39085                    case SyntaxKind.ConstructorType:
39086                    case SyntaxKind.TypeAliasDeclaration:
39087                    case SyntaxKind.InterfaceDeclaration:
39088                        checkUnusedTypeParameters(node, addDiagnostic);
39089                        break;
39090                    case SyntaxKind.InferType:
39091                        checkUnusedInferTypeParameter(node, addDiagnostic);
39092                        break;
39093                    default:
39094                        Debug.assertNever(node, "Node should not have been registered for unused identifiers check");
39095                }
39096            }
39097        }
39098
39099        function errorUnusedLocal(declaration: Declaration, name: string, addDiagnostic: AddUnusedDiagnostic) {
39100            const node = getNameOfDeclaration(declaration) || declaration;
39101            const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used : Diagnostics._0_is_declared_but_its_value_is_never_read;
39102            addDiagnostic(declaration, UnusedKind.Local, createDiagnosticForNode(node, message, name));
39103        }
39104
39105        function isIdentifierThatStartsWithUnderscore(node: Node) {
39106            return isIdentifier(node) && idText(node).charCodeAt(0) === CharacterCodes._;
39107        }
39108
39109        function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression | StructDeclaration, addDiagnostic: AddUnusedDiagnostic): void {
39110            for (const member of node.members) {
39111                switch (member.kind) {
39112                    case SyntaxKind.MethodDeclaration:
39113                    case SyntaxKind.PropertyDeclaration:
39114                    case SyntaxKind.GetAccessor:
39115                    case SyntaxKind.SetAccessor:
39116                        if (member.kind === SyntaxKind.SetAccessor && member.symbol.flags & SymbolFlags.GetAccessor) {
39117                            // Already would have reported an error on the getter.
39118                            break;
39119                        }
39120                        const symbol = getSymbolOfNode(member);
39121                        if (!symbol.isReferenced
39122                            && (hasEffectiveModifier(member, ModifierFlags.Private) || isNamedDeclaration(member) && isPrivateIdentifier(member.name))
39123                            && !(member.flags & NodeFlags.Ambient)) {
39124                            addDiagnostic(member, UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol)));
39125                        }
39126                        break;
39127                    case SyntaxKind.Constructor:
39128                        for (const parameter of (member as ConstructorDeclaration).parameters) {
39129                            if (!parameter.symbol.isReferenced && hasSyntacticModifier(parameter, ModifierFlags.Private)) {
39130                                addDiagnostic(parameter, UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol)));
39131                            }
39132                        }
39133                        break;
39134                    case SyntaxKind.IndexSignature:
39135                    case SyntaxKind.SemicolonClassElement:
39136                    case SyntaxKind.ClassStaticBlockDeclaration:
39137                        // Can't be private
39138                        break;
39139                    default:
39140                        Debug.fail("Unexpected class member");
39141                }
39142            }
39143        }
39144
39145        function checkUnusedInferTypeParameter(node: InferTypeNode, addDiagnostic: AddUnusedDiagnostic): void {
39146            const { typeParameter } = node;
39147            if (isTypeParameterUnused(typeParameter)) {
39148                addDiagnostic(node, UnusedKind.Parameter, createDiagnosticForNode(node, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(typeParameter.name)));
39149            }
39150        }
39151
39152        function checkUnusedTypeParameters(node: ClassLikeDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration, addDiagnostic: AddUnusedDiagnostic): void {
39153            // Only report errors on the last declaration for the type parameter container;
39154            // this ensures that all uses have been accounted for.
39155            const declarations = getSymbolOfNode(node).declarations;
39156            if (!declarations || last(declarations) !== node) return;
39157
39158            const typeParameters = getEffectiveTypeParameterDeclarations(node);
39159            const seenParentsWithEveryUnused = new Set<DeclarationWithTypeParameterChildren>();
39160
39161            for (const typeParameter of typeParameters) {
39162                if (!isTypeParameterUnused(typeParameter)) continue;
39163
39164                const name = idText(typeParameter.name);
39165                const { parent } = typeParameter;
39166                if (parent.kind !== SyntaxKind.InferType && parent.typeParameters!.every(isTypeParameterUnused)) {
39167                    if (tryAddToSet(seenParentsWithEveryUnused, parent)) {
39168                        const sourceFile = getSourceFileOfNode(parent);
39169                        const range = isJSDocTemplateTag(parent)
39170                            // Whole @template tag
39171                            ? rangeOfNode(parent)
39172                            // Include the `<>` in the error message
39173                            : rangeOfTypeParameters(sourceFile, parent.typeParameters!);
39174                        const only = parent.typeParameters!.length === 1;
39175                        //TODO: following line is possible reason for bug #41974, unusedTypeParameters_TemplateTag
39176                        const message = only ? Diagnostics._0_is_declared_but_its_value_is_never_read : Diagnostics.All_type_parameters_are_unused;
39177                        const arg0 = only ? name : undefined;
39178                        addDiagnostic(typeParameter, UnusedKind.Parameter, createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, message, arg0));
39179                    }
39180                }
39181                else {
39182                    //TODO: following line is possible reason for bug #41974, unusedTypeParameters_TemplateTag
39183                    addDiagnostic(typeParameter, UnusedKind.Parameter, createDiagnosticForNode(typeParameter, Diagnostics._0_is_declared_but_its_value_is_never_read, name));
39184                }
39185            }
39186        }
39187        function isTypeParameterUnused(typeParameter: TypeParameterDeclaration): boolean {
39188            return !(getMergedSymbol(typeParameter.symbol).isReferenced! & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderscore(typeParameter.name);
39189        }
39190
39191        function addToGroup<K, V>(map: ESMap<string, [K, V[]]>, key: K, value: V, getKey: (key: K) => number | string): void {
39192            const keyString = String(getKey(key));
39193            const group = map.get(keyString);
39194            if (group) {
39195                group[1].push(value);
39196            }
39197            else {
39198                map.set(keyString, [key, [value]]);
39199            }
39200        }
39201
39202        function tryGetRootParameterDeclaration(node: Node): ParameterDeclaration | undefined {
39203            return tryCast(getRootDeclaration(node), isParameter);
39204        }
39205
39206        function isValidUnusedLocalDeclaration(declaration: Declaration): boolean {
39207            if (isBindingElement(declaration)) {
39208                if (isObjectBindingPattern(declaration.parent)) {
39209                    /**
39210                     * ignore starts with underscore names _
39211                     * const { a: _a } = { a: 1 }
39212                     */
39213                    return !!(declaration.propertyName && isIdentifierThatStartsWithUnderscore(declaration.name));
39214                }
39215                return isIdentifierThatStartsWithUnderscore(declaration.name);
39216            }
39217            return isAmbientModule(declaration) ||
39218                (isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!);
39219        }
39220
39221        function checkUnusedLocalsAndParameters(nodeWithLocals: Node, addDiagnostic: AddUnusedDiagnostic): void {
39222            // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value.
39223            const unusedImports = new Map<string, [ImportClause, ImportedDeclaration[]]>();
39224            const unusedDestructures = new Map<string, [BindingPattern, BindingElement[]]>();
39225            const unusedVariables = new Map<string, [VariableDeclarationList, VariableDeclaration[]]>();
39226            nodeWithLocals.locals!.forEach(local => {
39227                // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`.
39228                // If it's a type parameter merged with a parameter, check if the parameter-side is used.
39229                if (local.flags & SymbolFlags.TypeParameter ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced! & SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) {
39230                    return;
39231                }
39232
39233                if (local.declarations) {
39234                    for (const declaration of local.declarations) {
39235                        if (isValidUnusedLocalDeclaration(declaration)) {
39236                            continue;
39237                        }
39238
39239                        if (isImportedDeclaration(declaration)) {
39240                            addToGroup(unusedImports, importClauseFromImported(declaration), declaration, getNodeId);
39241                        }
39242                        else if (isBindingElement(declaration) && isObjectBindingPattern(declaration.parent)) {
39243                            // In `{ a, ...b }, `a` is considered used since it removes a property from `b`. `b` may still be unused though.
39244                            const lastElement = last(declaration.parent.elements);
39245                            if (declaration === lastElement || !last(declaration.parent.elements).dotDotDotToken) {
39246                                addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId);
39247                            }
39248                        }
39249                        else if (isVariableDeclaration(declaration)) {
39250                            addToGroup(unusedVariables, declaration.parent, declaration, getNodeId);
39251                        }
39252                        else {
39253                            const parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration);
39254                            const name = local.valueDeclaration && getNameOfDeclaration(local.valueDeclaration);
39255                            if (parameter && name) {
39256                                if (!isParameterPropertyDeclaration(parameter, parameter.parent) && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) {
39257                                    if (isBindingElement(declaration) && isArrayBindingPattern(declaration.parent)) {
39258                                        addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId);
39259                                    }
39260                                    else {
39261                                        addDiagnostic(parameter, UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local)));
39262                                    }
39263                                }
39264                            }
39265                            else {
39266                                errorUnusedLocal(declaration, symbolName(local), addDiagnostic);
39267                            }
39268                        }
39269                    }
39270                }
39271            });
39272            unusedImports.forEach(([importClause, unuseds]) => {
39273                const importDecl = importClause.parent;
39274                const nDeclarations = (importClause.name ? 1 : 0) +
39275                    (importClause.namedBindings ?
39276                        (importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? 1 : importClause.namedBindings.elements.length)
39277                        : 0);
39278                if (nDeclarations === unuseds.length) {
39279                    addDiagnostic(importDecl, UnusedKind.Local, unuseds.length === 1
39280                        ? createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name!))
39281                        : createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused));
39282                }
39283                else {
39284                    for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name!), addDiagnostic);
39285                }
39286            });
39287            unusedDestructures.forEach(([bindingPattern, bindingElements]) => {
39288                const kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? UnusedKind.Parameter : UnusedKind.Local;
39289                if (bindingPattern.elements.length === bindingElements.length) {
39290                    if (bindingElements.length === 1 && bindingPattern.parent.kind === SyntaxKind.VariableDeclaration && bindingPattern.parent.parent.kind === SyntaxKind.VariableDeclarationList) {
39291                        addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId);
39292                    }
39293                    else {
39294                        addDiagnostic(bindingPattern, kind, bindingElements.length === 1
39295                            ? createDiagnosticForNode(bindingPattern, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(bindingElements).name))
39296                            : createDiagnosticForNode(bindingPattern, Diagnostics.All_destructured_elements_are_unused));
39297                    }
39298                }
39299                else {
39300                    for (const e of bindingElements) {
39301                        addDiagnostic(e, kind, createDiagnosticForNode(e, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(e.name)));
39302                    }
39303                }
39304            });
39305            unusedVariables.forEach(([declarationList, declarations]) => {
39306                if (declarationList.declarations.length === declarations.length) {
39307                    addDiagnostic(declarationList, UnusedKind.Local, declarations.length === 1
39308                        ? createDiagnosticForNode(first(declarations).name, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(declarations).name))
39309                        : createDiagnosticForNode(declarationList.parent.kind === SyntaxKind.VariableStatement ? declarationList.parent : declarationList, Diagnostics.All_variables_are_unused));
39310                }
39311                else {
39312                    for (const decl of declarations) {
39313                        addDiagnostic(decl, UnusedKind.Local, createDiagnosticForNode(decl, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(decl.name)));
39314                    }
39315                }
39316            });
39317        }
39318
39319        function checkPotentialUncheckedRenamedBindingElementsInTypes() {
39320            for (const node of potentialUnusedRenamedBindingElementsInTypes) {
39321                if (!getSymbolOfNode(node)?.isReferenced) {
39322                    const wrappingDeclaration = walkUpBindingElementsAndPatterns(node);
39323                    Debug.assert(isParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here");
39324                    const diagnostic = createDiagnosticForNode(node.name, Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, declarationNameToString(node.name), declarationNameToString(node.propertyName));
39325                    if (!wrappingDeclaration.type) {
39326                        // entire parameter does not have type annotation, suggest adding an annotation
39327                        addRelatedInfo(
39328                            diagnostic,
39329                            createFileDiagnostic(getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 1, Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, declarationNameToString(node.propertyName))
39330                        );
39331                    }
39332                    diagnostics.add(diagnostic);
39333                }
39334            }
39335        }
39336
39337        function bindingNameText(name: BindingName): string {
39338            switch (name.kind) {
39339                case SyntaxKind.Identifier:
39340                    return idText(name);
39341                case SyntaxKind.ArrayBindingPattern:
39342                case SyntaxKind.ObjectBindingPattern:
39343                    return bindingNameText(cast(first(name.elements), isBindingElement).name);
39344                default:
39345                    return Debug.assertNever(name);
39346            }
39347        }
39348
39349        type ImportedDeclaration = ImportClause | ImportSpecifier | NamespaceImport;
39350        function isImportedDeclaration(node: Node): node is ImportedDeclaration {
39351            return node.kind === SyntaxKind.ImportClause || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.NamespaceImport;
39352        }
39353        function importClauseFromImported(decl: ImportedDeclaration): ImportClause {
39354            return decl.kind === SyntaxKind.ImportClause ? decl : decl.kind === SyntaxKind.NamespaceImport ? decl.parent : decl.parent.parent;
39355        }
39356
39357        function checkBlock(node: Block) {
39358            // Grammar checking for SyntaxKind.Block
39359            if (node.kind === SyntaxKind.Block) {
39360                checkGrammarStatementInAmbientContext(node);
39361            }
39362            if (isFunctionOrModuleBlock(node)) {
39363                const saveFlowAnalysisDisabled = flowAnalysisDisabled;
39364                forEach(node.statements, checkSourceElement);
39365                flowAnalysisDisabled = saveFlowAnalysisDisabled;
39366            }
39367            else {
39368                forEach(node.statements, checkSourceElement);
39369            }
39370            if (node.locals) {
39371                registerForUnusedIdentifiersCheck(node);
39372            }
39373        }
39374
39375        function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
39376            // no rest parameters \ declaration context \ overload - no codegen impact
39377            if (languageVersion >= ScriptTarget.ES2015 || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node as FunctionLikeDeclaration).body)) {
39378                return;
39379            }
39380
39381            forEach(node.parameters, p => {
39382                if (p.name && !isBindingPattern(p.name) && p.name.escapedText === argumentsSymbol.escapedName) {
39383                    errorSkippedOn("noEmit", p, Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters);
39384                }
39385            });
39386        }
39387
39388        /**
39389         * Checks whether an {@link Identifier}, in the context of another {@link Node}, would collide with a runtime value
39390         * of {@link name} in an outer scope. This is used to check for collisions for downlevel transformations that
39391         * require names like `Object`, `Promise`, `Reflect`, `require`, `exports`, etc.
39392         */
39393        function needCollisionCheckForIdentifier(node: Node, identifier: Identifier | undefined, name: string): boolean {
39394            if (identifier?.escapedText !== name) {
39395                return false;
39396            }
39397
39398            if (node.kind === SyntaxKind.PropertyDeclaration ||
39399                node.kind === SyntaxKind.PropertySignature ||
39400                node.kind === SyntaxKind.MethodDeclaration ||
39401                node.kind === SyntaxKind.MethodSignature ||
39402                node.kind === SyntaxKind.GetAccessor ||
39403                node.kind === SyntaxKind.SetAccessor ||
39404                node.kind === SyntaxKind.PropertyAssignment) {
39405                // it is ok to have member named '_super', '_this', `Promise`, etc. - member access is always qualified
39406                return false;
39407            }
39408
39409            if (node.flags & NodeFlags.Ambient) {
39410                // ambient context - no codegen impact
39411                return false;
39412            }
39413
39414            if (isImportClause(node) || isImportEqualsDeclaration(node) || isImportSpecifier(node)) {
39415                // type-only imports do not require collision checks against runtime values.
39416                if (isTypeOnlyImportOrExportDeclaration(node)) {
39417                    return false;
39418                }
39419            }
39420
39421            const root = getRootDeclaration(node);
39422            if (isParameter(root) && nodeIsMissing((root.parent as FunctionLikeDeclaration).body)) {
39423                // just an overload - no codegen impact
39424                return false;
39425            }
39426
39427            return true;
39428        }
39429
39430        // this function will run after checking the source file so 'CaptureThis' is correct for all nodes
39431        function checkIfThisIsCapturedInEnclosingScope(node: Node): void {
39432            findAncestor(node, current => {
39433                if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) {
39434                    const isDeclaration = node.kind !== SyntaxKind.Identifier;
39435                    if (isDeclaration) {
39436                        error(getNameOfDeclaration(node as Declaration), Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
39437                    }
39438                    else {
39439                        error(node, Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference);
39440                    }
39441                    return true;
39442                }
39443                return false;
39444            });
39445        }
39446
39447        function checkIfNewTargetIsCapturedInEnclosingScope(node: Node): void {
39448            findAncestor(node, current => {
39449                if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureNewTarget) {
39450                    const isDeclaration = node.kind !== SyntaxKind.Identifier;
39451                    if (isDeclaration) {
39452                        error(getNameOfDeclaration(node as Declaration), Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference);
39453                    }
39454                    else {
39455                        error(node, Diagnostics.Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference);
39456                    }
39457                    return true;
39458                }
39459                return false;
39460            });
39461        }
39462
39463        function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier | undefined) {
39464            // No need to check for require or exports for ES6 modules and later
39465            if (moduleKind >= ModuleKind.ES2015 && !(moduleKind >= ModuleKind.Node16 && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) {
39466                return;
39467            }
39468
39469            if (!name || !needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
39470                return;
39471            }
39472
39473            // Uninstantiated modules shouldnt do this check
39474            if (isModuleDeclaration(node) && getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
39475                return;
39476            }
39477
39478            // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
39479            const parent = getDeclarationContainer(node);
39480            if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile)) {
39481                // If the declaration happens to be in external module, report error that require and exports are reserved keywords
39482                errorSkippedOn("noEmit", name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module,
39483                    declarationNameToString(name), declarationNameToString(name));
39484            }
39485        }
39486
39487        function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier | undefined): void {
39488            if (!name || languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) {
39489                return;
39490            }
39491
39492            // Uninstantiated modules shouldnt do this check
39493            if (isModuleDeclaration(node) && getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
39494                return;
39495            }
39496
39497            // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
39498            const parent = getDeclarationContainer(node);
39499            if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile) && parent.flags & NodeFlags.HasAsyncFunctions) {
39500                // If the declaration happens to be in external module, report error that Promise is a reserved identifier.
39501                errorSkippedOn("noEmit", name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions,
39502                    declarationNameToString(name), declarationNameToString(name));
39503            }
39504        }
39505
39506        function recordPotentialCollisionWithWeakMapSetInGeneratedCode(node: Node, name: Identifier): void {
39507            if (languageVersion <= ScriptTarget.ES2021
39508                && (needCollisionCheckForIdentifier(node, name, "WeakMap") || needCollisionCheckForIdentifier(node, name, "WeakSet"))) {
39509                potentialWeakMapSetCollisions.push(node);
39510            }
39511        }
39512
39513        function checkWeakMapSetCollision(node: Node) {
39514            const enclosingBlockScope = getEnclosingBlockScopeContainer(node);
39515            if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) {
39516                Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier");
39517                errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText);
39518            }
39519        }
39520
39521        function recordPotentialCollisionWithReflectInGeneratedCode(node: Node, name: Identifier | undefined): void {
39522            if (name && languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021
39523                && needCollisionCheckForIdentifier(node, name, "Reflect")) {
39524                potentialReflectCollisions.push(node);
39525            }
39526        }
39527
39528        function checkReflectCollision(node: Node) {
39529            let hasCollision = false;
39530            if (isClassExpression(node)) {
39531                // ClassExpression names don't contribute to their containers, but do matter for any of their block-scoped members.
39532                for (const member of node.members) {
39533                    if (getNodeCheckFlags(member) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
39534                        hasCollision = true;
39535                        break;
39536                    }
39537                }
39538            }
39539            else if (isFunctionExpression(node)) {
39540                // FunctionExpression names don't contribute to their containers, but do matter for their contents
39541                if (getNodeCheckFlags(node) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
39542                    hasCollision = true;
39543                }
39544            }
39545            else {
39546                const container = getEnclosingBlockScopeContainer(node);
39547                if (container && getNodeCheckFlags(container) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) {
39548                    hasCollision = true;
39549                }
39550            }
39551            if (hasCollision) {
39552                Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name), "The target of a Reflect collision check should be an identifier");
39553                errorSkippedOn("noEmit", node, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers,
39554                    declarationNameToString(node.name),
39555                    "Reflect");
39556            }
39557        }
39558
39559        function checkCollisionsForDeclarationName(node: Node, name: Identifier | undefined) {
39560            if (!name) return;
39561            checkCollisionWithRequireExportsInGeneratedCode(node, name);
39562            checkCollisionWithGlobalPromiseInGeneratedCode(node, name);
39563            recordPotentialCollisionWithWeakMapSetInGeneratedCode(node, name);
39564            recordPotentialCollisionWithReflectInGeneratedCode(node, name);
39565            if (isClassLike(node)) {
39566                checkTypeNameIsReserved(name, Diagnostics.Class_name_cannot_be_0);
39567                if (!(node.flags & NodeFlags.Ambient)) {
39568                    checkClassNameCollisionWithObject(name);
39569                }
39570            }
39571            else if (isEnumDeclaration(node)) {
39572                checkTypeNameIsReserved(name, Diagnostics.Enum_name_cannot_be_0);
39573            }
39574            else if (isAnnotationDeclaration(node)) {
39575                checkTypeNameIsReserved(name, Diagnostics.Annotation_name_cannot_be_0);
39576                if (!(node.flags & NodeFlags.Ambient)) {
39577                    checkClassNameCollisionWithObject(name);
39578                }
39579            }
39580        }
39581
39582        function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) {
39583            // - ScriptBody : StatementList
39584            // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
39585            // also occurs in the VarDeclaredNames of StatementList.
39586
39587            // - Block : { StatementList }
39588            // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
39589            // also occurs in the VarDeclaredNames of StatementList.
39590
39591            // Variable declarations are hoisted to the top of their function scope. They can shadow
39592            // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
39593            // by the binder as the declaration scope is different.
39594            // A non-initialized declaration is a no-op as the block declaration will resolve before the var
39595            // declaration. the problem is if the declaration has an initializer. this will act as a write to the
39596            // block declared value. this is fine for let, but not const.
39597            // Only consider declarations with initializers, uninitialized const declarations will not
39598            // step on a let/const variable.
39599            // Do not consider const and const declarations, as duplicate block-scoped declarations
39600            // are handled by the binder.
39601            // We are only looking for const declarations that step on let\const declarations from a
39602            // different scope. e.g.:
39603            //      {
39604            //          const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration
39605            //          const x = 0; // symbol for this declaration will be 'symbol'
39606            //      }
39607
39608            // skip block-scoped variables and parameters
39609            if ((getCombinedNodeFlags(node) & NodeFlags.BlockScoped) !== 0 || isParameterDeclaration(node)) {
39610                return;
39611            }
39612
39613            // skip variable declarations that don't have initializers
39614            // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern
39615            // so we'll always treat binding elements as initialized
39616            if (node.kind === SyntaxKind.VariableDeclaration && !node.initializer) {
39617                return;
39618            }
39619
39620            const symbol = getSymbolOfNode(node);
39621            if (symbol.flags & SymbolFlags.FunctionScopedVariable) {
39622                if (!isIdentifier(node.name)) return Debug.fail();
39623                const localDeclarationSymbol = resolveName(node, node.name.escapedText, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false);
39624                if (localDeclarationSymbol &&
39625                    localDeclarationSymbol !== symbol &&
39626                    localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
39627                    if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
39628                        const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!;
39629                        const container =
39630                            varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent
39631                                ? varDeclList.parent.parent
39632                                : undefined;
39633
39634                        // names of block-scoped and function scoped variables can collide only
39635                        // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
39636                        const namesShareScope =
39637                            container &&
39638                            (container.kind === SyntaxKind.Block && isFunctionLike(container.parent) ||
39639                                container.kind === SyntaxKind.ModuleBlock ||
39640                                container.kind === SyntaxKind.ModuleDeclaration ||
39641                                container.kind === SyntaxKind.SourceFile);
39642
39643                        // here we know that function scoped variable is shadowed by block scoped one
39644                        // if they are defined in the same scope - binder has already reported redeclaration error
39645                        // otherwise if variable has an initializer - show error that initialization will fail
39646                        // since LHS will be block scoped name instead of function scoped
39647                        if (!namesShareScope) {
39648                            const name = symbolToString(localDeclarationSymbol);
39649                            error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name);
39650                        }
39651                    }
39652                }
39653            }
39654        }
39655
39656        function convertAutoToAny(type: Type) {
39657            return type === autoType ? anyType : type === autoArrayType ? anyArrayType : type;
39658        }
39659
39660        // Check variable, parameter, or property declaration
39661        function checkVariableLikeDeclaration(node: ParameterDeclaration | PropertyDeclaration | PropertySignature | AnnotationPropertyDeclaration | VariableDeclaration | BindingElement) {
39662            checkDecorators(node);
39663            if (!isBindingElement(node)) {
39664                checkSourceElement(node.type);
39665            }
39666
39667            // JSDoc `function(string, string): string` syntax results in parameters with no name
39668            if (!node.name) {
39669                return;
39670            }
39671
39672            // For a computed property, just check the initializer and exit
39673            // Do not use hasDynamicName here, because that returns false for well known symbols.
39674            // We want to perform checkComputedPropertyName for all computed properties, including
39675            // well known symbols.
39676            if (node.name.kind === SyntaxKind.ComputedPropertyName) {
39677                checkComputedPropertyName(node.name);
39678                if (hasOnlyExpressionInitializer(node) && node.initializer) {
39679                    checkExpressionCached(node.initializer);
39680                }
39681            }
39682
39683            if (isBindingElement(node)) {
39684                if (
39685                  node.propertyName &&
39686                  isIdentifier(node.name) &&
39687                  isParameterDeclaration(node) &&
39688                  nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) {
39689                    // type F = ({a: string}) => void;
39690                    //               ^^^^^^
39691                    // variable renaming in function type notation is confusing,
39692                    // so we forbid it even if noUnusedLocals is not enabled
39693                    potentialUnusedRenamedBindingElementsInTypes.push(node);
39694                    return;
39695                }
39696
39697                if (isObjectBindingPattern(node.parent) && node.dotDotDotToken && languageVersion < ScriptTarget.ES2018) {
39698                    checkExternalEmitHelpers(node, ExternalEmitHelpers.Rest);
39699                }
39700                // check computed properties inside property names of binding elements
39701                if (node.propertyName && node.propertyName.kind === SyntaxKind.ComputedPropertyName) {
39702                    checkComputedPropertyName(node.propertyName);
39703                }
39704
39705                // check private/protected variable access
39706                const parent = node.parent.parent;
39707                const parentCheckMode = node.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal;
39708                const parentType = getTypeForBindingElementParent(parent, parentCheckMode);
39709                const name = node.propertyName || node.name;
39710                if (parentType && !isBindingPattern(name)) {
39711                    const exprType = getLiteralTypeFromPropertyName(name);
39712                    if (isTypeUsableAsPropertyName(exprType)) {
39713                        const nameText = getPropertyNameFromType(exprType);
39714                        const property = getPropertyOfType(parentType, nameText);
39715                        if (property) {
39716                            markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isSelfTypeAccess*/ false); // A destructuring is never a write-only reference.
39717                            checkPropertyAccessibility(node, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, /*writing*/ false, parentType, property);
39718                        }
39719                    }
39720                }
39721            }
39722
39723            // For a binding pattern, check contained binding elements
39724            if (isBindingPattern(node.name)) {
39725                if (node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) {
39726                    checkExternalEmitHelpers(node, ExternalEmitHelpers.Read);
39727                }
39728
39729                forEach(node.name.elements, checkSourceElement);
39730            }
39731
39732            // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body
39733            if (isParameter(node) && node.initializer && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) {
39734                error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
39735                return;
39736            }
39737            // For a binding pattern, validate the initializer and exit
39738            if (isBindingPattern(node.name)) {
39739                const needCheckInitializer = hasOnlyExpressionInitializer(node) && node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement;
39740                const needCheckWidenedType = !some(node.name.elements, not(isOmittedExpression));
39741                if (needCheckInitializer || needCheckWidenedType) {
39742                    // Don't validate for-in initializer as it is already an error
39743                    const widenedType = getWidenedTypeForVariableLikeDeclaration(node);
39744                    if (needCheckInitializer) {
39745                        const initializerType = checkExpressionCached(node.initializer);
39746                        if (strictNullChecks && needCheckWidenedType) {
39747                            checkNonNullNonVoidType(initializerType, node);
39748                        }
39749                        else {
39750                            checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer);
39751                        }
39752                    }
39753                    // check the binding pattern with empty elements
39754                    if (needCheckWidenedType) {
39755                        if (isArrayBindingPattern(node.name)) {
39756                            checkIteratedTypeOrElementType(IterationUse.Destructuring, widenedType, undefinedType, node);
39757                        }
39758                        else if (strictNullChecks) {
39759                            checkNonNullNonVoidType(widenedType, node);
39760                        }
39761                    }
39762                }
39763                return;
39764            }
39765            // For a commonjs `const x = require`, validate the alias and exit
39766            const symbol = getSymbolOfNode(node);
39767            if (symbol.flags & SymbolFlags.Alias && isVariableDeclarationInitializedToBareOrAccessedRequire(node.kind === SyntaxKind.BindingElement ? node.parent.parent : node)) {
39768                checkAliasSymbol(node as BindingElement | VariableDeclaration);
39769                return;
39770            }
39771
39772            const type = convertAutoToAny(getTypeOfSymbol(symbol));
39773            if (node === symbol.valueDeclaration) {
39774                // Node is the primary declaration of the symbol, just validate the initializer
39775                // Don't validate for-in initializer as it is already an error
39776                const initializer = hasOnlyExpressionInitializer(node) && getEffectiveInitializer(node);
39777                if (initializer) {
39778                    const isJSObjectLiteralInitializer = isInJSFile(node) &&
39779                        isObjectLiteralExpression(initializer) &&
39780                        (initializer.properties.length === 0 || isPrototypeAccess(node.name)) &&
39781                        !!symbol.exports?.size;
39782                    if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
39783                        checkTypeAssignableToAndOptionallyElaborate(checkExpressionCached(initializer), type, node, initializer, /*headMessage*/ undefined);
39784                    }
39785                }
39786                if (symbol.declarations && symbol.declarations.length > 1) {
39787                    if (some(symbol.declarations, d => d !== node && isVariableLike(d) && !areDeclarationFlagsIdentical(d, node))) {
39788                        error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name));
39789                    }
39790                }
39791            }
39792            else {
39793                // Node is a secondary declaration, check that type is identical to primary declaration and check that
39794                // initializer is consistent with type associated with the node
39795                const declarationType = convertAutoToAny(getWidenedTypeForVariableLikeDeclaration(node));
39796
39797                if (!isErrorType(type) && !isErrorType(declarationType) &&
39798                    !isTypeIdenticalTo(type, declarationType) &&
39799                    !(symbol.flags & SymbolFlags.Assignment)) {
39800                    errorNextVariableOrPropertyDeclarationMustHaveSameType(symbol.valueDeclaration, type, node, declarationType);
39801                }
39802                if (hasOnlyExpressionInitializer(node) && node.initializer) {
39803                    checkTypeAssignableToAndOptionallyElaborate(checkExpressionCached(node.initializer), declarationType, node, node.initializer, /*headMessage*/ undefined);
39804                }
39805                if (symbol.valueDeclaration && !areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) {
39806                    error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name));
39807                }
39808            }
39809            if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.AnnotationPropertyDeclaration) {
39810                // We know we don't have a binding pattern or computed name here
39811                checkExportsOnMergedDeclarations(node);
39812                if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) {
39813                    checkVarDeclaredNamesNotShadowed(node);
39814                }
39815                checkCollisionsForDeclarationName(node, node.name);
39816            }
39817        }
39818
39819        function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstDeclaration: Declaration | undefined, firstType: Type, nextDeclaration: Declaration, nextType: Type): void {
39820            const nextDeclarationName = getNameOfDeclaration(nextDeclaration);
39821            const message = nextDeclaration.kind === SyntaxKind.PropertyDeclaration || nextDeclaration.kind === SyntaxKind.PropertySignature
39822                ? Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2
39823                : Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2;
39824            const declName = declarationNameToString(nextDeclarationName);
39825            const err = error(
39826                nextDeclarationName,
39827                message,
39828                declName,
39829                typeToString(firstType),
39830                typeToString(nextType)
39831            );
39832            if (firstDeclaration) {
39833                addRelatedInfo(err,
39834                    createDiagnosticForNode(firstDeclaration, Diagnostics._0_was_also_declared_here, declName)
39835                );
39836            }
39837        }
39838
39839        function areDeclarationFlagsIdentical(left: Declaration, right: Declaration) {
39840            if ((left.kind === SyntaxKind.Parameter && right.kind === SyntaxKind.VariableDeclaration) ||
39841                (left.kind === SyntaxKind.VariableDeclaration && right.kind === SyntaxKind.Parameter)) {
39842                // Differences in optionality between parameters and variables are allowed.
39843                return true;
39844            }
39845
39846            if (hasQuestionToken(left) !== hasQuestionToken(right)) {
39847                return false;
39848            }
39849
39850            const interestingFlags = ModifierFlags.Private |
39851                ModifierFlags.Protected |
39852                ModifierFlags.Async |
39853                ModifierFlags.Abstract |
39854                ModifierFlags.Readonly |
39855                ModifierFlags.Static;
39856
39857            return getSelectedEffectiveModifierFlags(left, interestingFlags) === getSelectedEffectiveModifierFlags(right, interestingFlags);
39858        }
39859
39860        function checkVariableDeclaration(node: VariableDeclaration) {
39861            tracing?.push(tracing.Phase.Check, "checkVariableDeclaration", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath });
39862            checkGrammarVariableDeclaration(node);
39863            checkVariableLikeDeclaration(node);
39864            tracing?.pop();
39865        }
39866
39867        function checkBindingElement(node: BindingElement) {
39868            checkGrammarBindingElement(node);
39869            return checkVariableLikeDeclaration(node);
39870        }
39871
39872        function checkVariableStatement(node: VariableStatement) {
39873            // Grammar checking
39874            if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node);
39875            forEach(node.declarationList.declarations, checkSourceElement);
39876        }
39877
39878        function checkExpressionStatement(node: ExpressionStatement) {
39879            // Grammar checking
39880            checkGrammarStatementInAmbientContext(node);
39881
39882            checkExpression(node.expression);
39883        }
39884
39885        function checkIfStatement(node: IfStatement) {
39886            // Grammar checking
39887            checkGrammarStatementInAmbientContext(node);
39888            const type = checkTruthinessExpression(node.expression);
39889            checkTestingKnownTruthyCallableOrAwaitableType(node.expression, type, node.thenStatement);
39890            checkSourceElement(node.thenStatement);
39891
39892            if (node.thenStatement.kind === SyntaxKind.EmptyStatement) {
39893                error(node.thenStatement, Diagnostics.The_body_of_an_if_statement_cannot_be_the_empty_statement);
39894            }
39895
39896            checkSourceElement(node.elseStatement);
39897        }
39898
39899        function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, condType: Type, body?: Statement | Expression) {
39900            if (!strictNullChecks) return;
39901
39902            helper(condExpr, body);
39903            while (isBinaryExpression(condExpr) && condExpr.operatorToken.kind === SyntaxKind.BarBarToken) {
39904                condExpr = condExpr.left;
39905                helper(condExpr, body);
39906            }
39907
39908            function helper(condExpr: Expression, body: Expression | Statement | undefined) {
39909                const location = isBinaryExpression(condExpr) &&
39910                    (condExpr.operatorToken.kind === SyntaxKind.BarBarToken || condExpr.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)
39911                    ? condExpr.right
39912                    : condExpr;
39913                if (isModuleExportsAccessExpression(location)) return;
39914                const type = location === condExpr ? condType : checkTruthinessExpression(location);
39915                const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression);
39916                if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return;
39917
39918                // While it technically should be invalid for any known-truthy value
39919                // to be tested, we de-scope to functions and Promises unreferenced in
39920                // the block as a heuristic to identify the most common bugs. There
39921                // are too many false positives for values sourced from type
39922                // definitions without strictNullChecks otherwise.
39923                const callSignatures = getSignaturesOfType(type, SignatureKind.Call);
39924                const isPromise = !!getAwaitedTypeOfPromise(type);
39925                if (callSignatures.length === 0 && !isPromise) {
39926                    return;
39927                }
39928
39929                const testedNode = isIdentifier(location) ? location
39930                    : isPropertyAccessExpression(location) ? location.name
39931                    : isBinaryExpression(location) && isIdentifier(location.right) ? location.right
39932                    : undefined;
39933                const testedSymbol = testedNode && getSymbolAtLocation(testedNode);
39934                if (!testedSymbol && !isPromise) {
39935                    return;
39936                }
39937
39938                const isUsed = testedSymbol && isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol)
39939                    || testedSymbol && body && isSymbolUsedInConditionBody(condExpr, body, testedNode, testedSymbol);
39940                if (!isUsed) {
39941                    if (isPromise) {
39942                        errorAndMaybeSuggestAwait(
39943                            location,
39944                            /*maybeMissingAwait*/ true,
39945                            Diagnostics.This_condition_will_always_return_true_since_this_0_is_always_defined,
39946                            getTypeNameForErrorDisplay(type));
39947                    }
39948                    else {
39949                        error(location, Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead);
39950                    }
39951                }
39952            }
39953        }
39954
39955        function isSymbolUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean {
39956            return !!forEachChild(body, function check(childNode): boolean | undefined {
39957                if (isIdentifier(childNode)) {
39958                    const childSymbol = getSymbolAtLocation(childNode);
39959                    if (childSymbol && childSymbol === testedSymbol) {
39960                        // If the test was a simple identifier, the above check is sufficient
39961                        if (isIdentifier(expr) || isIdentifier(testedNode) && isBinaryExpression(testedNode.parent)) {
39962                            return true;
39963                        }
39964                        // Otherwise we need to ensure the symbol is called on the same target
39965                        let testedExpression = testedNode.parent;
39966                        let childExpression = childNode.parent;
39967                        while (testedExpression && childExpression) {
39968                            if (isIdentifier(testedExpression) && isIdentifier(childExpression) ||
39969                                testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword) {
39970                                return getSymbolAtLocation(testedExpression) === getSymbolAtLocation(childExpression);
39971                            }
39972                            else if (isPropertyAccessExpression(testedExpression) && isPropertyAccessExpression(childExpression)) {
39973                                if (getSymbolAtLocation(testedExpression.name) !== getSymbolAtLocation(childExpression.name)) {
39974                                    return false;
39975                                }
39976                                childExpression = childExpression.expression;
39977                                testedExpression = testedExpression.expression;
39978                            }
39979                            else if (isCallExpression(testedExpression) && isCallExpression(childExpression)) {
39980                                childExpression = childExpression.expression;
39981                                testedExpression = testedExpression.expression;
39982                            }
39983                            else {
39984                                return false;
39985                            }
39986                        }
39987                    }
39988                }
39989                return forEachChild(childNode, check);
39990            });
39991        }
39992
39993        function isSymbolUsedInBinaryExpressionChain(node: Node, testedSymbol: Symbol): boolean {
39994            while (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
39995                const isUsed = forEachChild(node.right, function visit(child): boolean | undefined {
39996                    if (isIdentifier(child)) {
39997                        const symbol = getSymbolAtLocation(child);
39998                        if (symbol && symbol === testedSymbol) {
39999                            return true;
40000                        }
40001                    }
40002                    return forEachChild(child, visit);
40003                });
40004                if (isUsed) {
40005                    return true;
40006                }
40007                node = node.parent;
40008            }
40009            return false;
40010        }
40011
40012        function checkDoStatement(node: DoStatement) {
40013            // Grammar checking
40014            checkGrammarStatementInAmbientContext(node);
40015
40016            checkSourceElement(node.statement);
40017            checkTruthinessExpression(node.expression);
40018        }
40019
40020        function checkWhileStatement(node: WhileStatement) {
40021            // Grammar checking
40022            checkGrammarStatementInAmbientContext(node);
40023
40024            checkTruthinessExpression(node.expression);
40025            checkSourceElement(node.statement);
40026        }
40027
40028        function checkTruthinessOfType(type: Type, node: Node) {
40029            if (type.flags & TypeFlags.Void) {
40030                error(node, Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness);
40031            }
40032            return type;
40033        }
40034
40035        function checkTruthinessExpression(node: Expression, checkMode?: CheckMode) {
40036            return checkTruthinessOfType(checkExpression(node, checkMode), node);
40037        }
40038
40039        function checkForStatement(node: ForStatement) {
40040            // Grammar checking
40041            if (!checkGrammarStatementInAmbientContext(node)) {
40042                if (node.initializer && node.initializer.kind === SyntaxKind.VariableDeclarationList) {
40043                    checkGrammarVariableDeclarationList(node.initializer as VariableDeclarationList);
40044                }
40045            }
40046
40047            if (node.initializer) {
40048                if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
40049                    forEach((node.initializer as VariableDeclarationList).declarations, checkVariableDeclaration);
40050                }
40051                else {
40052                    checkExpression(node.initializer);
40053                }
40054            }
40055
40056            if (node.condition) checkTruthinessExpression(node.condition);
40057            if (node.incrementor) checkExpression(node.incrementor);
40058            checkSourceElement(node.statement);
40059            if (node.locals) {
40060                registerForUnusedIdentifiersCheck(node);
40061            }
40062        }
40063
40064        function checkForOfStatement(node: ForOfStatement): void {
40065            checkGrammarForInOrForOfStatement(node);
40066
40067            const container = getContainingFunctionOrClassStaticBlock(node);
40068            if (node.awaitModifier) {
40069                if (container && isClassStaticBlockDeclaration(container)) {
40070                    grammarErrorOnNode(node.awaitModifier, Diagnostics.For_await_loops_cannot_be_used_inside_a_class_static_block);
40071                }
40072                else {
40073                    const functionFlags = getFunctionFlags(container);
40074                    if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Async)) === FunctionFlags.Async && languageVersion < ScriptTarget.ESNext) {
40075                        // for..await..of in an async function or async generator function prior to ESNext requires the __asyncValues helper
40076                        checkExternalEmitHelpers(node, ExternalEmitHelpers.ForAwaitOfIncludes);
40077                    }
40078                }
40079            }
40080            else if (compilerOptions.downlevelIteration && languageVersion < ScriptTarget.ES2015) {
40081                // for..of prior to ES2015 requires the __values helper when downlevelIteration is enabled
40082                checkExternalEmitHelpers(node, ExternalEmitHelpers.ForOfIncludes);
40083            }
40084
40085            // Check the LHS and RHS
40086            // If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS
40087            // via checkRightHandSideOfForOf.
40088            // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference.
40089            // Then check that the RHS is assignable to it.
40090            if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
40091                checkForInOrForOfVariableDeclaration(node);
40092            }
40093            else {
40094                const varExpr = node.initializer;
40095                const iteratedType = checkRightHandSideOfForOf(node);
40096
40097                // There may be a destructuring assignment on the left side
40098                if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
40099                    // iteratedType may be undefined. In this case, we still want to check the structure of
40100                    // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like
40101                    // to short circuit the type relation checking as much as possible, so we pass the unknownType.
40102                    checkDestructuringAssignment(varExpr, iteratedType || errorType);
40103                }
40104                else {
40105                    const leftType = checkExpression(varExpr);
40106                    checkReferenceExpression(
40107                        varExpr,
40108                        Diagnostics.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access,
40109                        Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_an_optional_property_access);
40110
40111                    // iteratedType will be undefined if the rightType was missing properties/signatures
40112                    // required to get its iteratedType (like [Symbol.iterator] or next). This may be
40113                    // because we accessed properties from anyType, or it may have led to an error inside
40114                    // getElementTypeOfIterable.
40115                    if (iteratedType) {
40116                        checkTypeAssignableToAndOptionallyElaborate(iteratedType, leftType, varExpr, node.expression);
40117                    }
40118                }
40119            }
40120
40121            checkSourceElement(node.statement);
40122            if (node.locals) {
40123                registerForUnusedIdentifiersCheck(node);
40124            }
40125        }
40126
40127        function checkForInStatement(node: ForInStatement) {
40128            // Grammar checking
40129            checkGrammarForInOrForOfStatement(node);
40130
40131            const rightType = getNonNullableTypeIfNeeded(checkExpression(node.expression));
40132            // TypeScript 1.0 spec (April 2014): 5.4
40133            // In a 'for-in' statement of the form
40134            // for (let VarDecl in Expr) Statement
40135            //   VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
40136            //   and Expr must be an expression of type Any, an object type, or a type parameter type.
40137            if (node.initializer.kind === SyntaxKind.VariableDeclarationList) {
40138                const variable = (node.initializer as VariableDeclarationList).declarations[0];
40139                if (variable && isBindingPattern(variable.name)) {
40140                    error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
40141                }
40142                checkForInOrForOfVariableDeclaration(node);
40143            }
40144            else {
40145                // In a 'for-in' statement of the form
40146                // for (Var in Expr) Statement
40147                //   Var must be an expression classified as a reference of type Any or the String primitive type,
40148                //   and Expr must be an expression of type Any, an object type, or a type parameter type.
40149                const varExpr = node.initializer;
40150                const leftType = checkExpression(varExpr);
40151                if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
40152                    error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
40153                }
40154                else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) {
40155                    error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
40156                }
40157                else {
40158                    // run check only former check succeeded to avoid cascading errors
40159                    checkReferenceExpression(
40160                        varExpr,
40161                        Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_a_variable_or_a_property_access,
40162                        Diagnostics.The_left_hand_side_of_a_for_in_statement_may_not_be_an_optional_property_access);
40163                }
40164            }
40165
40166            // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
40167            // in this case error about missing name is already reported - do not report extra one
40168            if (rightType === neverType || !isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) {
40169                error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType));
40170            }
40171
40172            checkSourceElement(node.statement);
40173            if (node.locals) {
40174                registerForUnusedIdentifiersCheck(node);
40175            }
40176        }
40177
40178        function checkForInOrForOfVariableDeclaration(iterationStatement: ForInOrOfStatement): void {
40179            const variableDeclarationList = iterationStatement.initializer as VariableDeclarationList;
40180            // checkGrammarForInOrForOfStatement will check that there is exactly one declaration.
40181            if (variableDeclarationList.declarations.length >= 1) {
40182                const decl = variableDeclarationList.declarations[0];
40183                checkVariableDeclaration(decl);
40184            }
40185        }
40186
40187        function checkRightHandSideOfForOf(statement: ForOfStatement): Type {
40188            const use = statement.awaitModifier ? IterationUse.ForAwaitOf : IterationUse.ForOf;
40189            return checkIteratedTypeOrElementType(use, checkNonNullExpression(statement.expression), undefinedType, statement.expression);
40190        }
40191
40192        function checkIteratedTypeOrElementType(use: IterationUse, inputType: Type, sentType: Type, errorNode: Node | undefined): Type {
40193            if (isTypeAny(inputType)) {
40194                return inputType;
40195            }
40196            return getIteratedTypeOrElementType(use, inputType, sentType, errorNode, /*checkAssignability*/ true) || anyType;
40197        }
40198
40199        /**
40200         * When consuming an iterable type in a for..of, spread, or iterator destructuring assignment
40201         * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type
40202         * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier.
40203         */
40204        function getIteratedTypeOrElementType(use: IterationUse, inputType: Type, sentType: Type, errorNode: Node | undefined, checkAssignability: boolean): Type | undefined {
40205            const allowAsyncIterables = (use & IterationUse.AllowsAsyncIterablesFlag) !== 0;
40206            if (inputType === neverType) {
40207                reportTypeNotIterableError(errorNode!, inputType, allowAsyncIterables); // TODO: GH#18217
40208                return undefined;
40209            }
40210
40211            const uplevelIteration = languageVersion >= ScriptTarget.ES2015;
40212            const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration;
40213            const possibleOutOfBounds = compilerOptions.noUncheckedIndexedAccess && !!(use & IterationUse.PossiblyOutOfBounds);
40214
40215            // Get the iterated type of an `Iterable<T>` or `IterableIterator<T>` only in ES2015
40216            // or higher, when inside of an async generator or for-await-if, or when
40217            // downlevelIteration is requested.
40218            if (uplevelIteration || downlevelIteration || allowAsyncIterables) {
40219                // We only report errors for an invalid iterable type in ES2015 or higher.
40220                const iterationTypes = getIterationTypesOfIterable(inputType, use, uplevelIteration ? errorNode : undefined);
40221                if (checkAssignability) {
40222                    if (iterationTypes) {
40223                        const diagnostic =
40224                            use & IterationUse.ForOfFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_for_of_will_always_send_0 :
40225                            use & IterationUse.SpreadFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_spread_will_always_send_0 :
40226                            use & IterationUse.DestructuringFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_destructuring_will_always_send_0 :
40227                            use & IterationUse.YieldStarFlag ? Diagnostics.Cannot_delegate_iteration_to_value_because_the_next_method_of_its_iterator_expects_type_1_but_the_containing_generator_will_always_send_0 :
40228                            undefined;
40229                        if (diagnostic) {
40230                            checkTypeAssignableTo(sentType, iterationTypes.nextType, errorNode, diagnostic);
40231                        }
40232                    }
40233                }
40234                if (iterationTypes || uplevelIteration) {
40235                    return possibleOutOfBounds ? includeUndefinedInIndexSignature(iterationTypes && iterationTypes.yieldType) : (iterationTypes && iterationTypes.yieldType);
40236                }
40237            }
40238
40239            let arrayType = inputType;
40240            let reportedError = false;
40241            let hasStringConstituent = false;
40242
40243            // If strings are permitted, remove any string-like constituents from the array type.
40244            // This allows us to find other non-string element types from an array unioned with
40245            // a string.
40246            if (use & IterationUse.AllowsStringInputFlag) {
40247                if (arrayType.flags & TypeFlags.Union) {
40248                    // After we remove all types that are StringLike, we will know if there was a string constituent
40249                    // based on whether the result of filter is a new array.
40250                    const arrayTypes = (inputType as UnionType).types;
40251                    const filteredTypes = filter(arrayTypes, t => !(t.flags & TypeFlags.StringLike));
40252                    if (filteredTypes !== arrayTypes) {
40253                        arrayType = getUnionType(filteredTypes, UnionReduction.Subtype);
40254                    }
40255                }
40256                else if (arrayType.flags & TypeFlags.StringLike) {
40257                    arrayType = neverType;
40258                }
40259
40260                hasStringConstituent = arrayType !== inputType;
40261                if (hasStringConstituent) {
40262                    if (languageVersion < ScriptTarget.ES5) {
40263                        if (errorNode) {
40264                            error(errorNode, Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher);
40265                            reportedError = true;
40266                        }
40267                    }
40268
40269                    // Now that we've removed all the StringLike types, if no constituents remain, then the entire
40270                    // arrayOrStringType was a string.
40271                    if (arrayType.flags & TypeFlags.Never) {
40272                        return possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType;
40273                    }
40274                }
40275            }
40276
40277            if (!isArrayLikeType(arrayType)) {
40278                if (errorNode && !reportedError) {
40279                    // Which error we report depends on whether we allow strings or if there was a
40280                    // string constituent. For example, if the input type is number | string, we
40281                    // want to say that number is not an array type. But if the input was just
40282                    // number and string input is allowed, we want to say that number is not an
40283                    // array type or a string type.
40284                    const allowsStrings = !!(use & IterationUse.AllowsStringInputFlag) && !hasStringConstituent;
40285                    const [defaultDiagnostic, maybeMissingAwait] = getIterationDiagnosticDetails(allowsStrings, downlevelIteration);
40286                    errorAndMaybeSuggestAwait(
40287                        errorNode,
40288                        maybeMissingAwait && !!getAwaitedTypeOfPromise(arrayType),
40289                        defaultDiagnostic,
40290                        typeToString(arrayType));
40291                }
40292                return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType : undefined;
40293            }
40294
40295            const arrayElementType = getIndexTypeOfType(arrayType, numberType);
40296            if (hasStringConstituent && arrayElementType) {
40297                // This is just an optimization for the case where arrayOrStringType is string | string[]
40298                if (arrayElementType.flags & TypeFlags.StringLike && !compilerOptions.noUncheckedIndexedAccess) {
40299                    return stringType;
40300                }
40301
40302                return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], UnionReduction.Subtype);
40303            }
40304
40305            return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) : arrayElementType;
40306
40307            function getIterationDiagnosticDetails(allowsStrings: boolean, downlevelIteration: boolean | undefined): [error: DiagnosticMessage, maybeMissingAwait: boolean] {
40308                if (downlevelIteration) {
40309                    return allowsStrings
40310                        ? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]
40311                        : [Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true];
40312                }
40313
40314                const yieldType = getIterationTypeOfIterable(use, IterationTypeKind.Yield, inputType, /*errorNode*/ undefined);
40315
40316                if (yieldType) {
40317                    return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, false];
40318                }
40319
40320                if (isES2015OrLaterIterable(inputType.symbol?.escapedName)) {
40321                    return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true];
40322                }
40323
40324                return allowsStrings
40325                    ? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type, true]
40326                    : [Diagnostics.Type_0_is_not_an_array_type, true];
40327            }
40328        }
40329
40330        function isES2015OrLaterIterable(n: __String) {
40331            switch (n) {
40332                case "Float32Array":
40333                case "Float64Array":
40334                case "Int16Array":
40335                case "Int32Array":
40336                case "Int8Array":
40337                case "NodeList":
40338                case "Uint16Array":
40339                case "Uint32Array":
40340                case "Uint8Array":
40341                case "Uint8ClampedArray":
40342                    return true;
40343            }
40344            return false;
40345        }
40346
40347        /**
40348         * Gets the requested "iteration type" from an `Iterable`-like or `AsyncIterable`-like type.
40349         */
40350        function getIterationTypeOfIterable(use: IterationUse, typeKind: IterationTypeKind, inputType: Type, errorNode: Node | undefined): Type | undefined {
40351            if (isTypeAny(inputType)) {
40352                return undefined;
40353            }
40354
40355            const iterationTypes = getIterationTypesOfIterable(inputType, use, errorNode);
40356            return iterationTypes && iterationTypes[getIterationTypesKeyFromIterationTypeKind(typeKind)];
40357        }
40358
40359        function createIterationTypes(yieldType: Type = neverType, returnType: Type = neverType, nextType: Type = unknownType): IterationTypes {
40360            // `yieldType` and `returnType` are defaulted to `neverType` they each will be combined
40361            // via `getUnionType` when merging iteration types. `nextType` is defined as `unknownType`
40362            // as it is combined via `getIntersectionType` when merging iteration types.
40363
40364            // Use the cache only for intrinsic types to keep it small as they are likely to be
40365            // more frequently created (i.e. `Iterator<number, void, unknown>`). Iteration types
40366            // are also cached on the type they are requested for, so we shouldn't need to maintain
40367            // the cache for less-frequently used types.
40368            if (yieldType.flags & TypeFlags.Intrinsic &&
40369                returnType.flags & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined) &&
40370                nextType.flags & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined)) {
40371                const id = getTypeListId([yieldType, returnType, nextType]);
40372                let iterationTypes = iterationTypesCache.get(id);
40373                if (!iterationTypes) {
40374                    iterationTypes = { yieldType, returnType, nextType };
40375                    iterationTypesCache.set(id, iterationTypes);
40376                }
40377                return iterationTypes;
40378            }
40379            return { yieldType, returnType, nextType };
40380        }
40381
40382        /**
40383         * Combines multiple `IterationTypes` records.
40384         *
40385         * If `array` is empty or all elements are missing or are references to `noIterationTypes`,
40386         * then `noIterationTypes` is returned. Otherwise, an `IterationTypes` record is returned
40387         * for the combined iteration types.
40388         */
40389        function combineIterationTypes(array: (IterationTypes | undefined)[]) {
40390            let yieldTypes: Type[] | undefined;
40391            let returnTypes: Type[] | undefined;
40392            let nextTypes: Type[] | undefined;
40393            for (const iterationTypes of array) {
40394                if (iterationTypes === undefined || iterationTypes === noIterationTypes) {
40395                    continue;
40396                }
40397                if (iterationTypes === anyIterationTypes) {
40398                    return anyIterationTypes;
40399                }
40400                yieldTypes = append(yieldTypes, iterationTypes.yieldType);
40401                returnTypes = append(returnTypes, iterationTypes.returnType);
40402                nextTypes = append(nextTypes, iterationTypes.nextType);
40403            }
40404            if (yieldTypes || returnTypes || nextTypes) {
40405                return createIterationTypes(
40406                    yieldTypes && getUnionType(yieldTypes),
40407                    returnTypes && getUnionType(returnTypes),
40408                    nextTypes && getIntersectionType(nextTypes));
40409            }
40410            return noIterationTypes;
40411        }
40412
40413        function getCachedIterationTypes(type: Type, cacheKey: MatchingKeys<IterableOrIteratorType, IterationTypes | undefined>) {
40414            return (type as IterableOrIteratorType)[cacheKey];
40415        }
40416
40417        function setCachedIterationTypes(type: Type, cacheKey: MatchingKeys<IterableOrIteratorType, IterationTypes | undefined>, cachedTypes: IterationTypes) {
40418            return (type as IterableOrIteratorType)[cacheKey] = cachedTypes;
40419        }
40420
40421        /**
40422         * Gets the *yield*, *return*, and *next* types from an `Iterable`-like or `AsyncIterable`-like type.
40423         *
40424         * At every level that involves analyzing return types of signatures, we union the return types of all the signatures.
40425         *
40426         * Another thing to note is that at any step of this process, we could run into a dead end,
40427         * meaning either the property is missing, or we run into the anyType. If either of these things
40428         * happens, we return `undefined` to signal that we could not find the iteration type. If a property
40429         * is missing, and the previous step did not result in `any`, then we also give an error if the
40430         * caller requested it. Then the caller can decide what to do in the case where there is no iterated
40431         * type.
40432         *
40433         * For a **for-of** statement, `yield*` (in a normal generator), spread, array
40434         * destructuring, or normal generator we will only ever look for a `[Symbol.iterator]()`
40435         * method.
40436         *
40437         * For an async generator we will only ever look at the `[Symbol.asyncIterator]()` method.
40438         *
40439         * For a **for-await-of** statement or a `yield*` in an async generator we will look for
40440         * the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method.
40441         */
40442        function getIterationTypesOfIterable(type: Type, use: IterationUse, errorNode: Node | undefined) {
40443            if (isTypeAny(type)) {
40444                return anyIterationTypes;
40445            }
40446
40447            if (!(type.flags & TypeFlags.Union)) {
40448                const errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined;
40449                const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode, errorOutputContainer);
40450                if (iterationTypes === noIterationTypes) {
40451                    if (errorNode) {
40452                        const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag));
40453                        if (errorOutputContainer?.errors) {
40454                            addRelatedInfo(rootDiag, ...errorOutputContainer.errors);
40455                        }
40456                    }
40457                    return undefined;
40458                }
40459                else if (errorOutputContainer?.errors?.length) {
40460                    for (const diag of errorOutputContainer.errors) {
40461                        diagnostics.add(diag);
40462                    }
40463                }
40464                return iterationTypes;
40465            }
40466
40467            const cacheKey = use & IterationUse.AllowsAsyncIterablesFlag ? "iterationTypesOfAsyncIterable" : "iterationTypesOfIterable";
40468            const cachedTypes = getCachedIterationTypes(type, cacheKey);
40469            if (cachedTypes) return cachedTypes === noIterationTypes ? undefined : cachedTypes;
40470
40471            let allIterationTypes: IterationTypes[] | undefined;
40472            for (const constituent of (type as UnionType).types) {
40473                const errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined;
40474                const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode, errorOutputContainer);
40475                if (iterationTypes === noIterationTypes) {
40476                    if (errorNode) {
40477                        const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag));
40478                        if (errorOutputContainer?.errors) {
40479                            addRelatedInfo(rootDiag, ...errorOutputContainer.errors);
40480                        }
40481                    }
40482                    setCachedIterationTypes(type, cacheKey, noIterationTypes);
40483                    return undefined;
40484                }
40485                else if (errorOutputContainer?.errors?.length) {
40486                    for (const diag of errorOutputContainer.errors) {
40487                        diagnostics.add(diag);
40488                    }
40489                }
40490
40491                allIterationTypes = append(allIterationTypes, iterationTypes);
40492            }
40493
40494            const iterationTypes = allIterationTypes ? combineIterationTypes(allIterationTypes) : noIterationTypes;
40495            setCachedIterationTypes(type, cacheKey, iterationTypes);
40496            return iterationTypes === noIterationTypes ? undefined : iterationTypes;
40497        }
40498
40499        function getAsyncFromSyncIterationTypes(iterationTypes: IterationTypes, errorNode: Node | undefined) {
40500            if (iterationTypes === noIterationTypes) return noIterationTypes;
40501            if (iterationTypes === anyIterationTypes) return anyIterationTypes;
40502            const { yieldType, returnType, nextType } = iterationTypes;
40503            // if we're requesting diagnostics, report errors for a missing `Awaited<T>`.
40504            if (errorNode) {
40505                getGlobalAwaitedSymbol(/*reportErrors*/ true);
40506            }
40507            return createIterationTypes(
40508                getAwaitedType(yieldType, errorNode) || anyType,
40509                getAwaitedType(returnType, errorNode) || anyType,
40510                nextType);
40511        }
40512
40513        /**
40514         * Gets the *yield*, *return*, and *next* types from a non-union type.
40515         *
40516         * If we are unable to find the *yield*, *return*, and *next* types, `noIterationTypes` is
40517         * returned to indicate to the caller that it should report an error. Otherwise, an
40518         * `IterationTypes` record is returned.
40519         *
40520         * NOTE: You probably don't want to call this directly and should be calling
40521         * `getIterationTypesOfIterable` instead.
40522         */
40523        function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined) {
40524            if (isTypeAny(type)) {
40525                return anyIterationTypes;
40526            }
40527
40528            // If we are reporting errors and encounter a cached `noIterationTypes`, we should ignore the cached value and continue as if nothing was cached.
40529            // In addition, we should not cache any new results for this call.
40530            let noCache = false;
40531
40532            if (use & IterationUse.AllowsAsyncIterablesFlag) {
40533                const iterationTypes =
40534                    getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) ||
40535                    getIterationTypesOfIterableFast(type, asyncIterationTypesResolver);
40536                if (iterationTypes) {
40537                    if (iterationTypes === noIterationTypes && errorNode) {
40538                        // ignore the cached value
40539                        noCache = true;
40540                    }
40541                    else {
40542                        return use & IterationUse.ForOfFlag ?
40543                            getAsyncFromSyncIterationTypes(iterationTypes, errorNode) :
40544                            iterationTypes;
40545                    }
40546                }
40547            }
40548
40549            if (use & IterationUse.AllowsSyncIterablesFlag) {
40550                let iterationTypes =
40551                    getIterationTypesOfIterableCached(type, syncIterationTypesResolver) ||
40552                    getIterationTypesOfIterableFast(type, syncIterationTypesResolver);
40553                if (iterationTypes) {
40554                    if (iterationTypes === noIterationTypes && errorNode) {
40555                        // ignore the cached value
40556                        noCache = true;
40557                    }
40558                    else {
40559                        if (use & IterationUse.AllowsAsyncIterablesFlag) {
40560                            // for a sync iterable in an async context, only use the cached types if they are valid.
40561                            if (iterationTypes !== noIterationTypes) {
40562                                iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode);
40563                                return noCache ? iterationTypes : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes);
40564                            }
40565                        }
40566                        else {
40567                            return iterationTypes;
40568                        }
40569                    }
40570                }
40571            }
40572
40573            if (use & IterationUse.AllowsAsyncIterablesFlag) {
40574                const iterationTypes = getIterationTypesOfIterableSlow(type, asyncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
40575                if (iterationTypes !== noIterationTypes) {
40576                    return iterationTypes;
40577                }
40578            }
40579
40580            if (use & IterationUse.AllowsSyncIterablesFlag) {
40581                let iterationTypes = getIterationTypesOfIterableSlow(type, syncIterationTypesResolver, errorNode, errorOutputContainer, noCache);
40582                if (iterationTypes !== noIterationTypes) {
40583                    if (use & IterationUse.AllowsAsyncIterablesFlag) {
40584                        iterationTypes = getAsyncFromSyncIterationTypes(iterationTypes, errorNode);
40585                        return noCache ? iterationTypes : setCachedIterationTypes(type, "iterationTypesOfAsyncIterable", iterationTypes);
40586                    }
40587                    else {
40588                        return iterationTypes;
40589                    }
40590                }
40591            }
40592
40593            return noIterationTypes;
40594        }
40595
40596        /**
40597         * Gets the *yield*, *return*, and *next* types of an `Iterable`-like or
40598         * `AsyncIterable`-like type from the cache.
40599         *
40600         * NOTE: You probably don't want to call this directly and should be calling
40601         * `getIterationTypesOfIterable` instead.
40602         */
40603        function getIterationTypesOfIterableCached(type: Type, resolver: IterationTypesResolver) {
40604            return getCachedIterationTypes(type, resolver.iterableCacheKey);
40605        }
40606
40607        function getIterationTypesOfGlobalIterableType(globalType: Type, resolver: IterationTypesResolver) {
40608            const globalIterationTypes =
40609                getIterationTypesOfIterableCached(globalType, resolver) ||
40610                getIterationTypesOfIterableSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false);
40611            return globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes;
40612        }
40613
40614        /**
40615         * Gets the *yield*, *return*, and *next* types of an `Iterable`-like or `AsyncIterable`-like
40616         * type from from common heuristics.
40617         *
40618         * If we previously analyzed this type and found no iteration types, `noIterationTypes` is
40619         * returned. If we found iteration types, an `IterationTypes` record is returned.
40620         * Otherwise, we return `undefined` to indicate to the caller it should perform a more
40621         * exhaustive analysis.
40622         *
40623         * NOTE: You probably don't want to call this directly and should be calling
40624         * `getIterationTypesOfIterable` instead.
40625         */
40626        function getIterationTypesOfIterableFast(type: Type, resolver: IterationTypesResolver) {
40627            // As an optimization, if the type is an instantiation of one of the following global types, then
40628            // just grab its related type argument:
40629            // - `Iterable<T>` or `AsyncIterable<T>`
40630            // - `IterableIterator<T>` or `AsyncIterableIterator<T>`
40631            let globalType: Type;
40632            if (isReferenceToType(type, globalType = resolver.getGlobalIterableType(/*reportErrors*/ false)) ||
40633                isReferenceToType(type, globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false))) {
40634                const [yieldType] = getTypeArguments(type as GenericType);
40635                // The "return" and "next" types of `Iterable` and `IterableIterator` are defined by the
40636                // iteration types of their `[Symbol.iterator]()` method. The same is true for their async cousins.
40637                // While we define these as `any` and `undefined` in our libs by default, a custom lib *could* use
40638                // different definitions.
40639                const { returnType, nextType } = getIterationTypesOfGlobalIterableType(globalType, resolver);
40640                return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType));
40641            }
40642
40643            // As an optimization, if the type is an instantiation of the following global type, then
40644            // just grab its related type arguments:
40645            // - `Generator<T, TReturn, TNext>` or `AsyncGenerator<T, TReturn, TNext>`
40646            if (isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) {
40647                const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType);
40648                return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType));
40649            }
40650        }
40651
40652        function getPropertyNameForKnownSymbolName(symbolName: string): __String {
40653            const ctorType = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false);
40654            const uniqueType = ctorType && getTypeOfPropertyOfType(getTypeOfSymbol(ctorType), escapeLeadingUnderscores(symbolName));
40655            return uniqueType && isTypeUsableAsPropertyName(uniqueType) ? getPropertyNameFromType(uniqueType) : `__@${symbolName}` as __String;
40656        }
40657
40658        /**
40659         * Gets the *yield*, *return*, and *next* types of an `Iterable`-like or `AsyncIterable`-like
40660         * type from its members.
40661         *
40662         * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
40663         * record is returned. Otherwise, `noIterationTypes` is returned.
40664         *
40665         * NOTE: You probably don't want to call this directly and should be calling
40666         * `getIterationTypesOfIterable` instead.
40667         */
40668        function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) {
40669            const method = getPropertyOfType(type, getPropertyNameForKnownSymbolName(resolver.iteratorSymbolName));
40670            const methodType = method && !(method.flags & SymbolFlags.Optional) ? getTypeOfSymbol(method) : undefined;
40671            if (isTypeAny(methodType)) {
40672                return noCache ? anyIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes);
40673            }
40674
40675            const signatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined;
40676            if (!some(signatures)) {
40677                return noCache ? noIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes);
40678            }
40679
40680            const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature));
40681            const iterationTypes = getIterationTypesOfIteratorWorker(iteratorType, resolver, errorNode, errorOutputContainer, noCache) ?? noIterationTypes;
40682            return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes);
40683        }
40684
40685        function reportTypeNotIterableError(errorNode: Node, type: Type, allowAsyncIterables: boolean): Diagnostic {
40686            const message = allowAsyncIterables
40687                ? Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator
40688                : Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator;
40689            const suggestAwait =
40690                // for (const x of Promise<...>) or [...Promise<...>]
40691                !!getAwaitedTypeOfPromise(type)
40692                // for (const x of AsyncIterable<...>)
40693                || (
40694                    !allowAsyncIterables &&
40695                    isForOfStatement(errorNode.parent) &&
40696                    errorNode.parent.expression === errorNode &&
40697                    getGlobalAsyncIterableType(/** reportErrors */ false) !== emptyGenericType &&
40698                    isTypeAssignableTo(type, getGlobalAsyncIterableType(/** reportErrors */ false)
40699                ));
40700            return errorAndMaybeSuggestAwait(errorNode, suggestAwait, message, typeToString(type));
40701        }
40702
40703        /**
40704         * Gets the *yield*, *return*, and *next* types from an `Iterator`-like or `AsyncIterator`-like type.
40705         *
40706         * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
40707         * record is returned. Otherwise, `undefined` is returned.
40708         */
40709        function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined) {
40710            return getIterationTypesOfIteratorWorker(type, resolver, errorNode, errorOutputContainer, /*noCache*/ false);
40711        }
40712
40713        /**
40714         * Gets the *yield*, *return*, and *next* types from an `Iterator`-like or `AsyncIterator`-like type.
40715         *
40716         * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
40717         * record is returned. Otherwise, `undefined` is returned.
40718         *
40719         * NOTE: You probably don't want to call this directly and should be calling
40720         * `getIterationTypesOfIterator` instead.
40721         */
40722        function getIterationTypesOfIteratorWorker(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) {
40723            if (isTypeAny(type)) {
40724                return anyIterationTypes;
40725            }
40726
40727            let iterationTypes =
40728                getIterationTypesOfIteratorCached(type, resolver) ||
40729                getIterationTypesOfIteratorFast(type, resolver);
40730
40731            if (iterationTypes === noIterationTypes && errorNode) {
40732                iterationTypes = undefined;
40733                noCache = true;
40734            }
40735
40736            iterationTypes ??= getIterationTypesOfIteratorSlow(type, resolver, errorNode, errorOutputContainer, noCache);
40737            return iterationTypes === noIterationTypes ? undefined : iterationTypes;
40738        }
40739
40740        /**
40741         * Gets the iteration types of an `Iterator`-like or `AsyncIterator`-like type from the
40742         * cache.
40743         *
40744         * NOTE: You probably don't want to call this directly and should be calling
40745         * `getIterationTypesOfIterator` instead.
40746         */
40747        function getIterationTypesOfIteratorCached(type: Type, resolver: IterationTypesResolver) {
40748            return getCachedIterationTypes(type, resolver.iteratorCacheKey);
40749        }
40750
40751        /**
40752         * Gets the iteration types of an `Iterator`-like or `AsyncIterator`-like type from the
40753         * cache or from common heuristics.
40754         *
40755         * If we previously analyzed this type and found no iteration types, `noIterationTypes` is
40756         * returned. If we found iteration types, an `IterationTypes` record is returned.
40757         * Otherwise, we return `undefined` to indicate to the caller it should perform a more
40758         * exhaustive analysis.
40759         *
40760         * NOTE: You probably don't want to call this directly and should be calling
40761         * `getIterationTypesOfIterator` instead.
40762         */
40763        function getIterationTypesOfIteratorFast(type: Type, resolver: IterationTypesResolver) {
40764            // As an optimization, if the type is an instantiation of one of the following global types,
40765            // then just grab its related type argument:
40766            // - `IterableIterator<T>` or `AsyncIterableIterator<T>`
40767            // - `Iterator<T, TReturn, TNext>` or `AsyncIterator<T, TReturn, TNext>`
40768            // - `Generator<T, TReturn, TNext>` or `AsyncGenerator<T, TReturn, TNext>`
40769            const globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false);
40770            if (isReferenceToType(type, globalType)) {
40771                const [yieldType] = getTypeArguments(type as GenericType);
40772                // The "return" and "next" types of `IterableIterator` and `AsyncIterableIterator` are defined by the
40773                // iteration types of their `next`, `return`, and `throw` methods. While we define these as `any`
40774                // and `undefined` in our libs by default, a custom lib *could* use different definitions.
40775                const globalIterationTypes =
40776                    getIterationTypesOfIteratorCached(globalType, resolver) ||
40777                    getIterationTypesOfIteratorSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false);
40778                const { returnType, nextType } = globalIterationTypes === noIterationTypes ? defaultIterationTypes : globalIterationTypes;
40779                return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType));
40780            }
40781            if (isReferenceToType(type, resolver.getGlobalIteratorType(/*reportErrors*/ false)) ||
40782                isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) {
40783                const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType);
40784                return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType));
40785            }
40786        }
40787
40788        function isIteratorResult(type: Type, kind: IterationTypeKind.Yield | IterationTypeKind.Return) {
40789            // From https://tc39.github.io/ecma262/#sec-iteratorresult-interface:
40790            // > [done] is the result status of an iterator `next` method call. If the end of the iterator was reached `done` is `true`.
40791            // > If the end was not reached `done` is `false` and a value is available.
40792            // > If a `done` property (either own or inherited) does not exist, it is consider to have the value `false`.
40793            const doneType = getTypeOfPropertyOfType(type, "done" as __String) || falseType;
40794            return isTypeAssignableTo(kind === IterationTypeKind.Yield ? falseType : trueType, doneType);
40795        }
40796
40797        function isYieldIteratorResult(type: Type) {
40798            return isIteratorResult(type, IterationTypeKind.Yield);
40799        }
40800
40801        function isReturnIteratorResult(type: Type) {
40802            return isIteratorResult(type, IterationTypeKind.Return);
40803        }
40804
40805        /**
40806         * Gets the *yield* and *return* types of an `IteratorResult`-like type.
40807         *
40808         * If we are unable to determine a *yield* or a *return* type, `noIterationTypes` is
40809         * returned to indicate to the caller that it should handle the error. Otherwise, an
40810         * `IterationTypes` record is returned.
40811         */
40812        function getIterationTypesOfIteratorResult(type: Type) {
40813            if (isTypeAny(type)) {
40814                return anyIterationTypes;
40815            }
40816
40817            const cachedTypes = getCachedIterationTypes(type, "iterationTypesOfIteratorResult");
40818            if (cachedTypes) {
40819                return cachedTypes;
40820            }
40821
40822            // As an optimization, if the type is an instantiation of one of the global `IteratorYieldResult<T>`
40823            // or `IteratorReturnResult<TReturn>` types, then just grab its type argument.
40824            if (isReferenceToType(type, getGlobalIteratorYieldResultType(/*reportErrors*/ false))) {
40825                const yieldType = getTypeArguments(type as GenericType)[0];
40826                return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(yieldType, /*returnType*/ undefined, /*nextType*/ undefined));
40827            }
40828            if (isReferenceToType(type, getGlobalIteratorReturnResultType(/*reportErrors*/ false))) {
40829                const returnType = getTypeArguments(type as GenericType)[0];
40830                return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(/*yieldType*/ undefined, returnType, /*nextType*/ undefined));
40831            }
40832
40833            // Choose any constituents that can produce the requested iteration type.
40834            const yieldIteratorResult = filterType(type, isYieldIteratorResult);
40835            const yieldType = yieldIteratorResult !== neverType ? getTypeOfPropertyOfType(yieldIteratorResult, "value" as __String) : undefined;
40836
40837            const returnIteratorResult = filterType(type, isReturnIteratorResult);
40838            const returnType = returnIteratorResult !== neverType ? getTypeOfPropertyOfType(returnIteratorResult, "value" as __String) : undefined;
40839
40840            if (!yieldType && !returnType) {
40841                return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", noIterationTypes);
40842            }
40843
40844            // From https://tc39.github.io/ecma262/#sec-iteratorresult-interface
40845            // > ... If the iterator does not have a return value, `value` is `undefined`. In that case, the
40846            // > `value` property may be absent from the conforming object if it does not inherit an explicit
40847            // > `value` property.
40848            return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(yieldType, returnType || voidType, /*nextType*/ undefined));
40849        }
40850
40851        /**
40852         * Gets the *yield*, *return*, and *next* types of a the `next()`, `return()`, or
40853         * `throw()` method of an `Iterator`-like or `AsyncIterator`-like type.
40854         *
40855         * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
40856         * record is returned. Otherwise, we return `undefined`.
40857         */
40858        function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined): IterationTypes | undefined {
40859            const method = getPropertyOfType(type, methodName as __String);
40860
40861            // Ignore 'return' or 'throw' if they are missing.
40862            if (!method && methodName !== "next") {
40863                return undefined;
40864            }
40865
40866            const methodType = method && !(methodName === "next" && (method.flags & SymbolFlags.Optional))
40867                ? methodName === "next" ? getTypeOfSymbol(method) : getTypeWithFacts(getTypeOfSymbol(method), TypeFacts.NEUndefinedOrNull)
40868                : undefined;
40869
40870            if (isTypeAny(methodType)) {
40871                // `return()` and `throw()` don't provide a *next* type.
40872                return methodName === "next" ? anyIterationTypes : anyIterationTypesExceptNext;
40873            }
40874
40875            // Both async and non-async iterators *must* have a `next` method.
40876            const methodSignatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : emptyArray;
40877            if (methodSignatures.length === 0) {
40878                if (errorNode) {
40879                    const diagnostic = methodName === "next"
40880                        ? resolver.mustHaveANextMethodDiagnostic
40881                        : resolver.mustBeAMethodDiagnostic;
40882                    if (errorOutputContainer) {
40883                        errorOutputContainer.errors ??= [];
40884                        errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, diagnostic, methodName));
40885                    }
40886                    else {
40887                        error(errorNode, diagnostic, methodName);
40888                    }
40889                }
40890                return methodName === "next" ? noIterationTypes : undefined;
40891            }
40892
40893            // If the method signature comes exclusively from the global iterator or generator type,
40894            // create iteration types from its type arguments like `getIterationTypesOfIteratorFast`
40895            // does (so as to remove `undefined` from the next and return types). We arrive here when
40896            // a contextual type for a generator was not a direct reference to one of those global types,
40897            // but looking up `methodType` referred to one of them (and nothing else). E.g., in
40898            // `interface SpecialIterator extends Iterator<number> {}`, `SpecialIterator` is not a
40899            // reference to `Iterator`, but its `next` member derives exclusively from `Iterator`.
40900            if (methodType?.symbol && methodSignatures.length === 1) {
40901                const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false);
40902                const globalIteratorType = resolver.getGlobalIteratorType(/*reportErrors*/ false);
40903                const isGeneratorMethod = globalGeneratorType.symbol?.members?.get(methodName as __String) === methodType.symbol;
40904                const isIteratorMethod = !isGeneratorMethod && globalIteratorType.symbol?.members?.get(methodName as __String) === methodType.symbol;
40905                if (isGeneratorMethod || isIteratorMethod) {
40906                    const globalType = isGeneratorMethod ? globalGeneratorType : globalIteratorType;
40907                    const { mapper } = methodType as AnonymousType;
40908                    return createIterationTypes(
40909                        getMappedType(globalType.typeParameters![0], mapper!),
40910                        getMappedType(globalType.typeParameters![1], mapper!),
40911                        methodName === "next" ? getMappedType(globalType.typeParameters![2], mapper!) : undefined);
40912                }
40913            }
40914
40915            // Extract the first parameter and return type of each signature.
40916            let methodParameterTypes: Type[] | undefined;
40917            let methodReturnTypes: Type[] | undefined;
40918            for (const signature of methodSignatures) {
40919                if (methodName !== "throw" && some(signature.parameters)) {
40920                    methodParameterTypes = append(methodParameterTypes, getTypeAtPosition(signature, 0));
40921                }
40922                methodReturnTypes = append(methodReturnTypes, getReturnTypeOfSignature(signature));
40923            }
40924
40925            // Resolve the *next* or *return* type from the first parameter of a `next()` or
40926            // `return()` method, respectively.
40927            let returnTypes: Type[] | undefined;
40928            let nextType: Type | undefined;
40929            if (methodName !== "throw") {
40930                const methodParameterType = methodParameterTypes ? getUnionType(methodParameterTypes) : unknownType;
40931                if (methodName === "next") {
40932                    // The value of `next(value)` is *not* awaited by async generators
40933                    nextType = methodParameterType;
40934                }
40935                else if (methodName === "return") {
40936                    // The value of `return(value)` *is* awaited by async generators
40937                    const resolvedMethodParameterType = resolver.resolveIterationType(methodParameterType, errorNode) || anyType;
40938                    returnTypes = append(returnTypes, resolvedMethodParameterType);
40939                }
40940            }
40941
40942            // Resolve the *yield* and *return* types from the return type of the method (i.e. `IteratorResult`)
40943            let yieldType: Type;
40944            const methodReturnType = methodReturnTypes ? getIntersectionType(methodReturnTypes) : neverType;
40945            const resolvedMethodReturnType = resolver.resolveIterationType(methodReturnType, errorNode) || anyType;
40946            const iterationTypes = getIterationTypesOfIteratorResult(resolvedMethodReturnType);
40947            if (iterationTypes === noIterationTypes) {
40948                if (errorNode) {
40949                    if (errorOutputContainer) {
40950                        errorOutputContainer.errors ??= [];
40951                        errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName));
40952                    }
40953                    else {
40954                        error(errorNode, resolver.mustHaveAValueDiagnostic, methodName);
40955                    }
40956                }
40957                yieldType = anyType;
40958                returnTypes = append(returnTypes, anyType);
40959            }
40960            else {
40961                yieldType = iterationTypes.yieldType;
40962                returnTypes = append(returnTypes, iterationTypes.returnType);
40963            }
40964
40965            return createIterationTypes(yieldType, getUnionType(returnTypes), nextType);
40966        }
40967
40968        /**
40969         * Gets the *yield*, *return*, and *next* types of an `Iterator`-like or `AsyncIterator`-like
40970         * type from its members.
40971         *
40972         * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes`
40973         * record is returned. Otherwise, `noIterationTypes` is returned.
40974         *
40975         * NOTE: You probably don't want to call this directly and should be calling
40976         * `getIterationTypesOfIterator` instead.
40977         */
40978        function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) {
40979            const iterationTypes = combineIterationTypes([
40980                getIterationTypesOfMethod(type, resolver, "next", errorNode, errorOutputContainer),
40981                getIterationTypesOfMethod(type, resolver, "return", errorNode, errorOutputContainer),
40982                getIterationTypesOfMethod(type, resolver, "throw", errorNode, errorOutputContainer),
40983            ]);
40984            return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iteratorCacheKey, iterationTypes);
40985        }
40986
40987        /**
40988         * Gets the requested "iteration type" from a type that is either `Iterable`-like, `Iterator`-like,
40989         * `IterableIterator`-like, or `Generator`-like (for a non-async generator); or `AsyncIterable`-like,
40990         * `AsyncIterator`-like, `AsyncIterableIterator`-like, or `AsyncGenerator`-like (for an async generator).
40991         */
40992        function getIterationTypeOfGeneratorFunctionReturnType(kind: IterationTypeKind, returnType: Type, isAsyncGenerator: boolean): Type | undefined {
40993            if (isTypeAny(returnType)) {
40994                return undefined;
40995            }
40996
40997            const iterationTypes = getIterationTypesOfGeneratorFunctionReturnType(returnType, isAsyncGenerator);
40998            return iterationTypes && iterationTypes[getIterationTypesKeyFromIterationTypeKind(kind)];
40999        }
41000
41001        function getIterationTypesOfGeneratorFunctionReturnType(type: Type, isAsyncGenerator: boolean) {
41002            if (isTypeAny(type)) {
41003                return anyIterationTypes;
41004            }
41005
41006            const use = isAsyncGenerator ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType;
41007            const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver;
41008            return getIterationTypesOfIterable(type, use, /*errorNode*/ undefined) ||
41009                getIterationTypesOfIterator(type, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined);
41010        }
41011
41012        function checkBreakOrContinueStatement(node: BreakOrContinueStatement) {
41013            // Grammar checking
41014            if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node);
41015
41016            // TODO: Check that target label is valid
41017        }
41018
41019        function unwrapReturnType(returnType: Type, functionFlags: FunctionFlags) {
41020            const isGenerator = !!(functionFlags & FunctionFlags.Generator);
41021            const isAsync = !!(functionFlags & FunctionFlags.Async);
41022            if (isGenerator) {
41023                const returnIterationType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync);
41024                if (!returnIterationType) {
41025                    return errorType;
41026                }
41027                return isAsync ? getAwaitedTypeNoAlias(unwrapAwaitedType(returnIterationType)) : returnIterationType;
41028            }
41029            return isAsync ? getAwaitedTypeNoAlias(returnType) || errorType : returnType;
41030        }
41031
41032        function isUnwrappedReturnTypeVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean {
41033            const unwrappedReturnType = unwrapReturnType(returnType, getFunctionFlags(func));
41034            return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.AnyOrUnknown);
41035        }
41036
41037        function checkReturnStatement(node: ReturnStatement) {
41038            // Grammar checking
41039            if (checkGrammarStatementInAmbientContext(node)) {
41040                return;
41041            }
41042
41043            const container = getContainingFunctionOrClassStaticBlock(node);
41044            if(container && isClassStaticBlockDeclaration(container)) {
41045                grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_cannot_be_used_inside_a_class_static_block);
41046                return;
41047            }
41048
41049            if (!container) {
41050                grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body);
41051                return;
41052            }
41053
41054            const signature = getSignatureFromDeclaration(container);
41055            const returnType = getReturnTypeOfSignature(signature);
41056            const functionFlags = getFunctionFlags(container);
41057            if (strictNullChecks || node.expression || returnType.flags & TypeFlags.Never) {
41058                const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType;
41059                if (container.kind === SyntaxKind.SetAccessor) {
41060                    if (node.expression) {
41061                        error(node, Diagnostics.Setters_cannot_return_a_value);
41062                    }
41063                }
41064                else if (container.kind === SyntaxKind.Constructor) {
41065                    if (node.expression && !checkTypeAssignableToAndOptionallyElaborate(exprType, returnType, node, node.expression)) {
41066                        error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
41067                    }
41068                }
41069                else if (getReturnTypeFromAnnotation(container)) {
41070                    const unwrappedReturnType = unwrapReturnType(returnType, functionFlags) ?? returnType;
41071                    const unwrappedExprType = functionFlags & FunctionFlags.Async
41072                        ? checkAwaitedType(exprType, /*withAlias*/ false, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)
41073                        : exprType;
41074                    if (unwrappedReturnType) {
41075                        // If the function has a return type, but promisedType is
41076                        // undefined, an error will be reported in checkAsyncFunctionReturnType
41077                        // so we don't need to report one here.
41078                        checkTypeAssignableToAndOptionallyElaborate(unwrappedExprType, unwrappedReturnType, node, node.expression);
41079                    }
41080                }
41081            }
41082            else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(container, returnType)) {
41083                // The function has a return type, but the return statement doesn't have an expression.
41084                error(node, Diagnostics.Not_all_code_paths_return_a_value);
41085            }
41086        }
41087
41088        function checkWithStatement(node: WithStatement) {
41089            // Grammar checking for withStatement
41090            if (!checkGrammarStatementInAmbientContext(node)) {
41091                if (node.flags & NodeFlags.AwaitContext) {
41092                    grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_an_async_function_block);
41093                }
41094            }
41095
41096            checkExpression(node.expression);
41097
41098            const sourceFile = getSourceFileOfNode(node);
41099            if (!hasParseDiagnostics(sourceFile)) {
41100                const start = getSpanOfTokenAtPosition(sourceFile, node.pos).start;
41101                const end = node.statement.pos;
41102                grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any);
41103            }
41104        }
41105
41106        function checkSwitchStatement(node: SwitchStatement) {
41107            // Grammar checking
41108            checkGrammarStatementInAmbientContext(node);
41109
41110            let firstDefaultClause: CaseOrDefaultClause;
41111            let hasDuplicateDefaultClause = false;
41112
41113            const expressionType = checkExpression(node.expression);
41114            const expressionIsLiteral = isLiteralType(expressionType);
41115            forEach(node.caseBlock.clauses, clause => {
41116                // Grammar check for duplicate default clauses, skip if we already report duplicate default clause
41117                if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) {
41118                    if (firstDefaultClause === undefined) {
41119                        firstDefaultClause = clause;
41120                    }
41121                    else {
41122                        grammarErrorOnNode(clause, Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement);
41123                        hasDuplicateDefaultClause = true;
41124                    }
41125                }
41126
41127                if (clause.kind === SyntaxKind.CaseClause) {
41128                    addLazyDiagnostic(createLazyCaseClauseDiagnostics(clause));
41129                }
41130                forEach(clause.statements, checkSourceElement);
41131                if (compilerOptions.noFallthroughCasesInSwitch && clause.fallthroughFlowNode && isReachableFlowNode(clause.fallthroughFlowNode)) {
41132                    error(clause, Diagnostics.Fallthrough_case_in_switch);
41133                }
41134
41135                function createLazyCaseClauseDiagnostics(clause: CaseClause) {
41136                    return () => {
41137                        // TypeScript 1.0 spec (April 2014): 5.9
41138                        // In a 'switch' statement, each 'case' expression must be of a type that is comparable
41139                        // to or from the type of the 'switch' expression.
41140                        let caseType = checkExpression(clause.expression);
41141                        const caseIsLiteral = isLiteralType(caseType);
41142                        let comparedExpressionType = expressionType;
41143                        if (!caseIsLiteral || !expressionIsLiteral) {
41144                            caseType = caseIsLiteral ? getBaseTypeOfLiteralType(caseType) : caseType;
41145                            comparedExpressionType = getBaseTypeOfLiteralType(expressionType);
41146                        }
41147                        if (!isTypeEqualityComparableTo(comparedExpressionType, caseType)) {
41148                            // expressionType is not comparable to caseType, try the reversed check and report errors if it fails
41149                            checkTypeComparableTo(caseType, comparedExpressionType, clause.expression, /*headMessage*/ undefined);
41150                        }
41151                    };
41152                }
41153            });
41154            if (node.caseBlock.locals) {
41155                registerForUnusedIdentifiersCheck(node.caseBlock);
41156            }
41157        }
41158
41159        function checkLabeledStatement(node: LabeledStatement) {
41160            // Grammar checking
41161            if (!checkGrammarStatementInAmbientContext(node)) {
41162                findAncestor(node.parent, current => {
41163                    if (isFunctionLike(current)) {
41164                        return "quit";
41165                    }
41166                    if (current.kind === SyntaxKind.LabeledStatement && (current as LabeledStatement).label.escapedText === node.label.escapedText) {
41167                        grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNode(node.label));
41168                        return true;
41169                    }
41170                    return false;
41171                });
41172            }
41173
41174            // ensure that label is unique
41175            checkSourceElement(node.statement);
41176        }
41177
41178        function checkThrowStatement(node: ThrowStatement) {
41179            // Grammar checking
41180            if (!checkGrammarStatementInAmbientContext(node)) {
41181                if (isIdentifier(node.expression) && !node.expression.escapedText) {
41182                    grammarErrorAfterFirstToken(node, Diagnostics.Line_break_not_permitted_here);
41183                }
41184            }
41185
41186            if (node.expression) {
41187                checkExpression(node.expression);
41188            }
41189        }
41190
41191        function checkTryStatement(node: TryStatement) {
41192            // Grammar checking
41193            checkGrammarStatementInAmbientContext(node);
41194
41195            checkBlock(node.tryBlock);
41196            const catchClause = node.catchClause;
41197            if (catchClause) {
41198                // Grammar checking
41199                if (catchClause.variableDeclaration) {
41200                    const declaration = catchClause.variableDeclaration;
41201                    const typeNode = getEffectiveTypeAnnotationNode(getRootDeclaration(declaration));
41202                    if (typeNode) {
41203                        const type = getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ false, CheckMode.Normal);
41204                        if (type && !(type.flags & TypeFlags.AnyOrUnknown)) {
41205                            grammarErrorOnFirstToken(typeNode, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified);
41206                        }
41207                    }
41208                    else if (declaration.initializer) {
41209                        grammarErrorOnFirstToken(declaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer);
41210                    }
41211                    else {
41212                        const blockLocals = catchClause.block.locals;
41213                        if (blockLocals) {
41214                            forEachKey(catchClause.locals!, caughtName => {
41215                                const blockLocal = blockLocals.get(caughtName);
41216                                if (blockLocal?.valueDeclaration && (blockLocal.flags & SymbolFlags.BlockScopedVariable) !== 0) {
41217                                    grammarErrorOnNode(blockLocal.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName);
41218                                }
41219                            });
41220                        }
41221                    }
41222                }
41223
41224                checkBlock(catchClause.block);
41225            }
41226
41227            if (node.finallyBlock) {
41228                checkBlock(node.finallyBlock);
41229            }
41230        }
41231
41232        function checkIndexConstraints(type: Type, symbol: Symbol, isStaticIndex?: boolean) {
41233            const indexInfos = getIndexInfosOfType(type);
41234            if (indexInfos.length === 0) {
41235                return;
41236            }
41237            for (const prop of getPropertiesOfObjectType(type)) {
41238                if (!(isStaticIndex && prop.flags & SymbolFlags.Prototype)) {
41239                    checkIndexConstraintForProperty(type, prop, getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique, /*includeNonPublic*/ true), getNonMissingTypeOfSymbol(prop));
41240                }
41241            }
41242            const typeDeclaration = symbol.valueDeclaration;
41243            if (typeDeclaration && isClassLike(typeDeclaration)) {
41244                for (const member of typeDeclaration.members) {
41245                    // Only process instance properties with computed names here. Static properties cannot be in conflict with indexers,
41246                    // and properties with literal names were already checked.
41247                    if (!isStatic(member) && !hasBindableName(member)) {
41248                        const symbol = getSymbolOfNode(member);
41249                        checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol));
41250                    }
41251                }
41252            }
41253            if (indexInfos.length > 1) {
41254                for (const info of indexInfos) {
41255                    checkIndexConstraintForIndexSignature(type, info);
41256                }
41257            }
41258        }
41259
41260        function checkIndexConstraintForProperty(type: Type, prop: Symbol, propNameType: Type, propType: Type) {
41261            const declaration = prop.valueDeclaration;
41262            const name = getNameOfDeclaration(declaration);
41263            if (name && isPrivateIdentifier(name)) {
41264                return;
41265            }
41266            const indexInfos = getApplicableIndexInfos(type, propNameType);
41267            const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined;
41268            const propDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression ||
41269                name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined;
41270            const localPropDeclaration = getParentOfSymbol(prop) === type.symbol ? declaration : undefined;
41271            for (const info of indexInfos) {
41272                const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined;
41273                // We check only when (a) the property is declared in the containing type, or (b) the applicable index signature is declared
41274                // in the containing type, or (c) the containing type is an interface and no base interface contains both the property and
41275                // the index signature (i.e. property and index signature are declared in separate inherited interfaces).
41276                const errorNode = localPropDeclaration || localIndexDeclaration ||
41277                    (interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getPropertyOfObjectType(base, prop.escapedName) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined);
41278                if (errorNode && !isTypeAssignableTo(propType, info.type)) {
41279                    const diagnostic = createError(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3,
41280                        symbolToString(prop), typeToString(propType), typeToString(info.keyType), typeToString(info.type));
41281                    if (propDeclaration && errorNode !== propDeclaration) {
41282                        addRelatedInfo(diagnostic, createDiagnosticForNode(propDeclaration, Diagnostics._0_is_declared_here, symbolToString(prop)));
41283                    }
41284                    diagnostics.add(diagnostic);
41285                }
41286            }
41287        }
41288
41289        function checkIndexConstraintForIndexSignature(type: Type, checkInfo: IndexInfo) {
41290            const declaration = checkInfo.declaration;
41291            const indexInfos = getApplicableIndexInfos(type, checkInfo.keyType);
41292            const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined;
41293            const localCheckDeclaration = declaration && getParentOfSymbol(getSymbolOfNode(declaration)) === type.symbol ? declaration : undefined;
41294            for (const info of indexInfos) {
41295                if (info === checkInfo) continue;
41296                const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined;
41297                // We check only when (a) the check index signature is declared in the containing type, or (b) the applicable index
41298                // signature is declared in the containing type, or (c) the containing type is an interface and no base interface contains
41299                // both index signatures (i.e. the index signatures are declared in separate inherited interfaces).
41300                const errorNode = localCheckDeclaration || localIndexDeclaration ||
41301                    (interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getIndexInfoOfType(base, checkInfo.keyType) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined);
41302                if (errorNode && !isTypeAssignableTo(checkInfo.type, info.type)) {
41303                    error(errorNode, Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3,
41304                        typeToString(checkInfo.keyType), typeToString(checkInfo.type), typeToString(info.keyType), typeToString(info.type));
41305                }
41306            }
41307        }
41308
41309        function checkTypeNameIsReserved(name: Identifier, message: DiagnosticMessage): void {
41310            // TS 1.0 spec (April 2014): 3.6.1
41311            // The predefined type keywords are reserved and cannot be used as names of user defined types.
41312            switch (name.escapedText) {
41313                case "any":
41314                case "unknown":
41315                case "never":
41316                case "number":
41317                case "bigint":
41318                case "boolean":
41319                case "string":
41320                case "symbol":
41321                case "void":
41322                case "object":
41323                    error(name, message, name.escapedText as string);
41324            }
41325        }
41326
41327        /**
41328         * The name cannot be used as 'Object' of user defined types with special target.
41329         */
41330        function checkClassNameCollisionWithObject(name: Identifier): void {
41331            if (languageVersion >= ScriptTarget.ES5 && name.escapedText === "Object"
41332                && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(name).impliedNodeFormat === ModuleKind.CommonJS)) {
41333                error(name, Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494
41334            }
41335        }
41336
41337        function checkUnmatchedJSDocParameters(node: SignatureDeclaration) {
41338            const jsdocParameters = filter(getJSDocTags(node), isJSDocParameterTag);
41339            if (!length(jsdocParameters)) return;
41340
41341            const isJs = isInJSFile(node);
41342            const parameters = new Set<__String>();
41343            const excludedParameters = new Set<number>();
41344            forEach(node.parameters, ({ name }, index) => {
41345                if (isIdentifier(name)) {
41346                    parameters.add(name.escapedText);
41347                }
41348                if (isBindingPattern(name)) {
41349                    excludedParameters.add(index);
41350                }
41351            });
41352
41353            const containsArguments = containsArgumentsReference(node);
41354            if (containsArguments) {
41355                const lastJSDocParam = lastOrUndefined(jsdocParameters);
41356                if (isJs && lastJSDocParam && isIdentifier(lastJSDocParam.name) && lastJSDocParam.typeExpression &&
41357                    lastJSDocParam.typeExpression.type && !parameters.has(lastJSDocParam.name.escapedText) && !isArrayType(getTypeFromTypeNode(lastJSDocParam.typeExpression.type))) {
41358                    error(lastJSDocParam.name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, idText(lastJSDocParam.name));
41359                }
41360            }
41361            else {
41362                forEach(jsdocParameters, ({ name, isNameFirst }, index) => {
41363                    if (excludedParameters.has(index) || isIdentifier(name) && parameters.has(name.escapedText)) {
41364                        return;
41365                    }
41366                    if (isQualifiedName(name)) {
41367                        if (isJs) {
41368                            error(name, Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, entityNameToString(name), entityNameToString(name.left));
41369                        }
41370                    }
41371                    else {
41372                        if (!isNameFirst) {
41373                            errorOrSuggestion(isJs, name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, idText(name));
41374                        }
41375                    }
41376                });
41377            }
41378        }
41379
41380        /**
41381         * Check each type parameter and check that type parameters have no duplicate type parameter declarations
41382         */
41383        function checkTypeParameters(typeParameterDeclarations: readonly TypeParameterDeclaration[] | undefined) {
41384            let seenDefault = false;
41385            if (typeParameterDeclarations) {
41386                for (let i = 0; i < typeParameterDeclarations.length; i++) {
41387                    const node = typeParameterDeclarations[i];
41388                    checkTypeParameter(node);
41389
41390                    addLazyDiagnostic(createCheckTypeParameterDiagnostic(node, i));
41391                }
41392            }
41393
41394            function createCheckTypeParameterDiagnostic(node: TypeParameterDeclaration, i: number) {
41395                return () => {
41396                    if (node.default) {
41397                        seenDefault = true;
41398                        checkTypeParametersNotReferenced(node.default, typeParameterDeclarations!, i);
41399                    }
41400                    else if (seenDefault) {
41401                        error(node, Diagnostics.Required_type_parameters_may_not_follow_optional_type_parameters);
41402                    }
41403                    for (let j = 0; j < i; j++) {
41404                        if (typeParameterDeclarations![j].symbol === node.symbol) {
41405                            error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name));
41406                        }
41407                    }
41408                };
41409            }
41410        }
41411
41412        /** Check that type parameter defaults only reference previously declared type parameters */
41413        function checkTypeParametersNotReferenced(root: TypeNode, typeParameters: readonly TypeParameterDeclaration[], index: number) {
41414            visit(root);
41415            function visit(node: Node) {
41416                if (node.kind === SyntaxKind.TypeReference) {
41417                    const type = getTypeFromTypeReference(node as TypeReferenceNode);
41418                    if (type.flags & TypeFlags.TypeParameter) {
41419                        for (let i = index; i < typeParameters.length; i++) {
41420                            if (type.symbol === getSymbolOfNode(typeParameters[i])) {
41421                                error(node, Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters);
41422                            }
41423                        }
41424                    }
41425                }
41426                forEachChild(node, visit);
41427            }
41428        }
41429
41430        /** Check that type parameter lists are identical across multiple declarations */
41431        function checkTypeParameterListsIdentical(symbol: Symbol) {
41432            if (symbol.declarations && symbol.declarations.length === 1) {
41433                return;
41434            }
41435
41436            const links = getSymbolLinks(symbol);
41437            if (!links.typeParametersChecked) {
41438                links.typeParametersChecked = true;
41439                const declarations = getClassOrInterfaceDeclarationsOfSymbol(symbol);
41440                if (!declarations || declarations.length <= 1) {
41441                    return;
41442                }
41443
41444                const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
41445                if (!areTypeParametersIdentical(declarations, type.localTypeParameters!, getEffectiveTypeParameterDeclarations)) {
41446                    // Report an error on every conflicting declaration.
41447                    const name = symbolToString(symbol);
41448                    for (const declaration of declarations) {
41449                        error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name);
41450                    }
41451                }
41452            }
41453        }
41454
41455        function areTypeParametersIdentical<T extends DeclarationWithTypeParameters | TypeParameterDeclaration>(declarations: readonly T[], targetParameters: TypeParameter[], getTypeParameterDeclarations: (node: T) => readonly TypeParameterDeclaration[]) {
41456            const maxTypeArgumentCount = length(targetParameters);
41457            const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters);
41458
41459            for (const declaration of declarations) {
41460                // If this declaration has too few or too many type parameters, we report an error
41461                const sourceParameters = getTypeParameterDeclarations(declaration);
41462                const numTypeParameters = sourceParameters.length;
41463                if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) {
41464                    return false;
41465                }
41466
41467                for (let i = 0; i < numTypeParameters; i++) {
41468                    const source = sourceParameters[i];
41469                    const target = targetParameters[i];
41470
41471                    // If the type parameter node does not have the same as the resolved type
41472                    // parameter at this position, we report an error.
41473                    if (source.name.escapedText !== target.symbol.escapedName) {
41474                        return false;
41475                    }
41476
41477                    // If the type parameter node does not have an identical constraint as the resolved
41478                    // type parameter at this position, we report an error.
41479                    const constraint = getEffectiveConstraintOfTypeParameter(source);
41480                    const sourceConstraint = constraint && getTypeFromTypeNode(constraint);
41481                    const targetConstraint = getConstraintOfTypeParameter(target);
41482                    // relax check if later interface augmentation has no constraint, it's more broad and is OK to merge with
41483                    // a more constrained interface (this could be generalized to a full hierarchy check, but that's maybe overkill)
41484                    if (sourceConstraint && targetConstraint && !isTypeIdenticalTo(sourceConstraint, targetConstraint)) {
41485                        return false;
41486                    }
41487
41488                    // If the type parameter node has a default and it is not identical to the default
41489                    // for the type parameter at this position, we report an error.
41490                    const sourceDefault = source.default && getTypeFromTypeNode(source.default);
41491                    const targetDefault = getDefaultFromTypeParameter(target);
41492                    if (sourceDefault && targetDefault && !isTypeIdenticalTo(sourceDefault, targetDefault)) {
41493                        return false;
41494                    }
41495                }
41496            }
41497
41498            return true;
41499        }
41500
41501        function checkClassExpression(node: ClassExpression): Type {
41502            checkClassLikeDeclaration(node);
41503            checkNodeDeferred(node);
41504            return getTypeOfSymbol(getSymbolOfNode(node));
41505        }
41506
41507        function checkClassExpressionDeferred(node: ClassExpression) {
41508            forEach(node.members, checkSourceElement);
41509            registerForUnusedIdentifiersCheck(node);
41510        }
41511
41512        function checkClassDeclaration(node: ClassDeclaration) {
41513            const firstDecorator = find(node.modifiers, isDecorator);
41514            if (firstDecorator && some(node.members, p => hasStaticModifier(p) && isPrivateIdentifierClassElementDeclaration(p))) {
41515                grammarErrorOnNode(firstDecorator, Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator);
41516            }
41517            if (!node.name && !hasSyntacticModifier(node, ModifierFlags.Default)) {
41518                grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
41519            }
41520            checkClassLikeDeclaration(node);
41521            forEach(node.members, checkSourceElement);
41522
41523            registerForUnusedIdentifiersCheck(node);
41524        }
41525
41526        function checkStructDeclaration(node: StructDeclaration) {
41527            if (!node.name && !hasSyntacticModifier(node, ModifierFlags.Default)) {
41528                grammarErrorOnFirstToken(node, Diagnostics.A_struct_declaration_without_the_default_modifier_must_have_a_name);
41529            }
41530            checkClassLikeDeclaration(node);
41531            checkStructName(node);
41532            forEach(node.members, checkSourceElement);
41533
41534            registerForUnusedIdentifiersCheck(node);
41535        }
41536
41537        function checkStructName(node: StructDeclaration) {
41538            if (host.getCompilerOptions().ets && node.name && isIdentifier(node.name)) {
41539                const arrReservedComponents = host.getCompilerOptions().ets?.components;
41540                if (arrReservedComponents!.includes(node.name.escapedText.toString())) {
41541                    error(node.name, Diagnostics.The_struct_name_cannot_contain_reserved_tag_name_Colon_0, node.name.escapedText.toString());
41542                }
41543            }
41544        }
41545
41546        function checkAnnotationDeclaration(node: AnnotationDeclaration) {
41547            checkGrammarAnnotationDeclaration(node);
41548            checkDecorators(node);
41549
41550            const firstDecorator = find(node.modifiers, isDecorator);
41551            if (firstDecorator) {
41552                grammarErrorOnNode(firstDecorator, Diagnostics.Decorators_are_not_valid_here);
41553            }
41554            const firstAnnotation = find(node.modifiers, isAnnotation);
41555            if (firstAnnotation) {
41556                grammarErrorOnNode(firstAnnotation, Diagnostics.Annotation_cannot_be_applied_for_annotation_declaration);
41557            }
41558
41559            checkCollisionsForDeclarationName(node, node.name);
41560
41561            checkExportsOnMergedDeclarations(node);
41562            const symbol = getSymbolOfNode(node);
41563            const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
41564            const staticType = getTypeOfSymbol(symbol) as ObjectType;
41565
41566            checkClassForDuplicateDeclarations(node);
41567
41568            addLazyDiagnostic(() => {
41569                checkIndexConstraints(type, symbol);
41570                checkIndexConstraints(staticType, symbol, /*isStaticIndex*/ true);
41571                checkTypeForDuplicateIndexSignatures(node);
41572                checkPropertyInitialization(node);
41573            });
41574
41575            forEach(node.members, checkSourceElement);
41576        }
41577
41578        function checkGrammarAnnotationDeclaration(node: AnnotationDeclaration) {
41579            Debug.assert(node.parent);
41580            if (!isSourceFile(node.parent)) {
41581                grammarErrorOnNode(node, Diagnostics.Annotation_must_be_defined_at_top_level_only);
41582            }
41583            checkGrammarDecoratorsAndModifiers(node);
41584        }
41585
41586        function checkClassLikeDeclaration(node: ClassLikeDeclaration) {
41587            checkGrammarClassLikeDeclaration(node);
41588            checkDecorators(node);
41589            checkCollisionsForDeclarationName(node, node.name);
41590            checkTypeParameters(getEffectiveTypeParameterDeclarations(node));
41591            checkExportsOnMergedDeclarations(node);
41592            const symbol = getSymbolOfNode(node);
41593            const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
41594            const typeWithThis = getTypeWithThisArgument(type);
41595            const staticType = getTypeOfSymbol(symbol) as ObjectType;
41596            checkTypeParameterListsIdentical(symbol);
41597            checkFunctionOrConstructorSymbol(symbol);
41598            checkClassForDuplicateDeclarations(node);
41599
41600            // Only check for reserved static identifiers on non-ambient context.
41601            const nodeInAmbientContext = !!(node.flags & NodeFlags.Ambient);
41602            if (!nodeInAmbientContext) {
41603                checkClassForStaticPropertyNameConflicts(node);
41604            }
41605
41606            const baseTypeNode = getEffectiveBaseTypeNode(node);
41607            if (baseTypeNode) {
41608                forEach(baseTypeNode.typeArguments, checkSourceElement);
41609                if (languageVersion < ScriptTarget.ES2015) {
41610                    checkExternalEmitHelpers(baseTypeNode.parent, ExternalEmitHelpers.Extends);
41611                }
41612                // check both @extends and extends if both are specified.
41613                const extendsNode = getClassExtendsHeritageElement(node);
41614                if (extendsNode && extendsNode !== baseTypeNode) {
41615                    checkExpression(extendsNode.expression);
41616                }
41617
41618                const baseTypes = getBaseTypes(type);
41619                if (baseTypes.length) {
41620                    addLazyDiagnostic(() => {
41621                        const baseType = baseTypes[0];
41622                        const baseConstructorType = getBaseConstructorTypeOfClass(type);
41623                        const staticBaseType = getApparentType(baseConstructorType);
41624                        checkBaseTypeAccessibility(staticBaseType, baseTypeNode);
41625                        checkSourceElement(baseTypeNode.expression);
41626                        if (some(baseTypeNode.typeArguments)) {
41627                            forEach(baseTypeNode.typeArguments, checkSourceElement);
41628                            for (const constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode)) {
41629                                if (!checkTypeArgumentConstraints(baseTypeNode, constructor.typeParameters!)) {
41630                                    break;
41631                                }
41632                            }
41633                        }
41634                        const baseWithThis = getTypeWithThisArgument(baseType, type.thisType);
41635                        if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) {
41636                            issueMemberSpecificError(node, typeWithThis, baseWithThis, Diagnostics.Class_0_incorrectly_extends_base_class_1);
41637                        }
41638                        else {
41639                            // Report static side error only when instance type is assignable
41640                            checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
41641                                Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
41642                        }
41643                        if (baseConstructorType.flags & TypeFlags.TypeVariable) {
41644                            if (!isMixinConstructorType(staticType)) {
41645                                error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any);
41646                            }
41647                            else {
41648                                const constructSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
41649                                if (constructSignatures.some(signature => signature.flags & SignatureFlags.Abstract) && !hasSyntacticModifier(node, ModifierFlags.Abstract)) {
41650                                    error(node.name || node, Diagnostics.A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract);
41651                                }
41652                            }
41653                        }
41654
41655                        if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) {
41656                            // When the static base type is a "class-like" constructor function (but not actually a class), we verify
41657                            // that all instantiated base constructor signatures return the same type.
41658                            const constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode);
41659                            if (forEach(constructors, sig => !isJSConstructor(sig.declaration) && !isTypeIdenticalTo(getReturnTypeOfSignature(sig), baseType))) {
41660                                error(baseTypeNode.expression, Diagnostics.Base_constructors_must_all_have_the_same_return_type);
41661                            }
41662                        }
41663                        checkKindsOfPropertyMemberOverrides(type, baseType);
41664                    });
41665                }
41666            }
41667
41668            checkMembersForOverrideModifier(node, type, typeWithThis, staticType);
41669
41670            const implementedTypeNodes = getEffectiveImplementsTypeNodes(node);
41671            if (implementedTypeNodes) {
41672                for (const typeRefNode of implementedTypeNodes) {
41673                    if (!isEntityNameExpression(typeRefNode.expression) || isOptionalChain(typeRefNode.expression)) {
41674                        error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments);
41675                    }
41676                    checkTypeReferenceNode(typeRefNode);
41677                    addLazyDiagnostic(createImplementsDiagnostics(typeRefNode));
41678                }
41679            }
41680
41681            addLazyDiagnostic(() => {
41682                checkIndexConstraints(type, symbol);
41683                checkIndexConstraints(staticType, symbol, /*isStaticIndex*/ true);
41684                checkTypeForDuplicateIndexSignatures(node);
41685                checkPropertyInitialization(node);
41686            });
41687
41688            function createImplementsDiagnostics(typeRefNode: ExpressionWithTypeArguments) {
41689                return () => {
41690                    const t = getReducedType(getTypeFromTypeNode(typeRefNode));
41691                    if (!isErrorType(t)) {
41692                        if (isValidBaseType(t)) {
41693                            const genericDiag = t.symbol && t.symbol.flags & SymbolFlags.Class ?
41694                                Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass :
41695                                Diagnostics.Class_0_incorrectly_implements_interface_1;
41696                            const baseWithThis = getTypeWithThisArgument(t, type.thisType);
41697                            if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) {
41698                                issueMemberSpecificError(node, typeWithThis, baseWithThis, genericDiag);
41699                            }
41700                        }
41701                        else {
41702                            error(typeRefNode, Diagnostics.A_class_can_only_implement_an_object_type_or_intersection_of_object_types_with_statically_known_members);
41703                        }
41704                    }
41705                };
41706            }
41707        }
41708
41709        function checkMembersForOverrideModifier(node: ClassLikeDeclaration, type: InterfaceType, typeWithThis: Type, staticType: ObjectType) {
41710            const baseTypeNode = getEffectiveBaseTypeNode(node);
41711            const baseTypes = baseTypeNode && getBaseTypes(type);
41712            const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(first(baseTypes), type.thisType) : undefined;
41713            const baseStaticType = getBaseConstructorTypeOfClass(type);
41714
41715            for (const member of node.members) {
41716                if (hasAmbientModifier(member)) {
41717                    continue;
41718                }
41719
41720                if (isConstructorDeclaration(member)) {
41721                    forEach(member.parameters, param => {
41722                        if (isParameterPropertyDeclaration(param, member)) {
41723                            checkExistingMemberForOverrideModifier(
41724                                node,
41725                                staticType,
41726                                baseStaticType,
41727                                baseWithThis,
41728                                type,
41729                                typeWithThis,
41730                                param,
41731                                /* memberIsParameterProperty */ true
41732                            );
41733                        }
41734                    });
41735                }
41736                checkExistingMemberForOverrideModifier(
41737                    node,
41738                    staticType,
41739                    baseStaticType,
41740                    baseWithThis,
41741                    type,
41742                    typeWithThis,
41743                    member,
41744                    /* memberIsParameterProperty */ false,
41745                );
41746            }
41747        }
41748
41749        /**
41750         * @param member Existing member node to be checked.
41751         * Note: `member` cannot be a synthetic node.
41752         */
41753        function checkExistingMemberForOverrideModifier(
41754            node: ClassLikeDeclaration,
41755            staticType: ObjectType,
41756            baseStaticType: Type,
41757            baseWithThis: Type | undefined,
41758            type: InterfaceType,
41759            typeWithThis: Type,
41760            member: ClassElement | ParameterPropertyDeclaration,
41761            memberIsParameterProperty: boolean,
41762            reportErrors = true,
41763        ): MemberOverrideStatus {
41764            const declaredProp = member.name
41765                && getSymbolAtLocation(member.name)
41766                || getSymbolAtLocation(member);
41767            if (!declaredProp) {
41768                return MemberOverrideStatus.Ok;
41769            }
41770
41771            return checkMemberForOverrideModifier(
41772                node,
41773                staticType,
41774                baseStaticType,
41775                baseWithThis,
41776                type,
41777                typeWithThis,
41778                hasOverrideModifier(member),
41779                hasAbstractModifier(member),
41780                isStatic(member),
41781                memberIsParameterProperty,
41782                symbolName(declaredProp),
41783                reportErrors ? member : undefined,
41784            );
41785        }
41786
41787        /**
41788         * Checks a class member declaration for either a missing or an invalid `override` modifier.
41789         * Note: this function can be used for speculative checking,
41790         * i.e. checking a member that does not yet exist in the program.
41791         * An example of that would be to call this function in a completions scenario,
41792         * when offering a method declaration as completion.
41793         * @param errorNode The node where we should report an error, or undefined if we should not report errors.
41794         */
41795        function checkMemberForOverrideModifier(
41796            node: ClassLikeDeclaration,
41797            staticType: ObjectType,
41798            baseStaticType: Type,
41799            baseWithThis: Type | undefined,
41800            type: InterfaceType,
41801            typeWithThis: Type,
41802            memberHasOverrideModifier: boolean,
41803            memberHasAbstractModifier: boolean,
41804            memberIsStatic: boolean,
41805            memberIsParameterProperty: boolean,
41806            memberName: string,
41807            errorNode?: Node,
41808        ): MemberOverrideStatus {
41809            const isJs = isInJSFile(node);
41810            const nodeInAmbientContext = !!(node.flags & NodeFlags.Ambient);
41811            if (baseWithThis && (memberHasOverrideModifier || compilerOptions.noImplicitOverride)) {
41812                const memberEscapedName = escapeLeadingUnderscores(memberName);
41813                const thisType = memberIsStatic ? staticType : typeWithThis;
41814                const baseType = memberIsStatic ? baseStaticType : baseWithThis;
41815                const prop = getPropertyOfType(thisType, memberEscapedName);
41816                const baseProp = getPropertyOfType(baseType, memberEscapedName);
41817
41818                const baseClassName = typeToString(baseWithThis);
41819                if (prop && !baseProp && memberHasOverrideModifier) {
41820                    if (errorNode) {
41821                        const suggestion = getSuggestedSymbolForNonexistentClassMember(memberName, baseType); // Again, using symbol name: note that's different from `symbol.escapedName`
41822                        suggestion ?
41823                            error(
41824                                errorNode,
41825                                isJs ?
41826                                    Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 :
41827                                    Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1,
41828                                baseClassName,
41829                                symbolToString(suggestion)) :
41830                            error(
41831                                errorNode,
41832                                isJs ?
41833                                    Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 :
41834                                    Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0,
41835                                baseClassName);
41836                    }
41837                    return MemberOverrideStatus.HasInvalidOverride;
41838                }
41839                else if (prop && baseProp?.declarations && compilerOptions.noImplicitOverride && !nodeInAmbientContext) {
41840                    const baseHasAbstract = some(baseProp.declarations, hasAbstractModifier);
41841                    if (memberHasOverrideModifier) {
41842                        return MemberOverrideStatus.Ok;
41843                    }
41844
41845                    if (!baseHasAbstract) {
41846                        if (errorNode) {
41847                            const diag = memberIsParameterProperty ?
41848                                isJs ?
41849                                    Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 :
41850                                    Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 :
41851                                isJs ?
41852                                    Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 :
41853                                    Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0;
41854                            error(errorNode, diag, baseClassName);
41855                        }
41856                        return MemberOverrideStatus.NeedsOverride;
41857                    }
41858                    else if (memberHasAbstractModifier && baseHasAbstract) {
41859                        if (errorNode) {
41860                            error(errorNode, Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0, baseClassName);
41861                        }
41862                        return MemberOverrideStatus.NeedsOverride;
41863                    }
41864                }
41865            }
41866            else if (memberHasOverrideModifier) {
41867                if (errorNode) {
41868                    const className = typeToString(type);
41869                    error(
41870                        errorNode,
41871                        isJs ?
41872                            Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class :
41873                            Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class,
41874                        className);
41875                }
41876                return MemberOverrideStatus.HasInvalidOverride;
41877            }
41878
41879            return MemberOverrideStatus.Ok;
41880        }
41881
41882        function issueMemberSpecificError(node: ClassLikeDeclaration, typeWithThis: Type, baseWithThis: Type, broadDiag: DiagnosticMessage) {
41883            // iterate over all implemented properties and issue errors on each one which isn't compatible, rather than the class as a whole, if possible
41884            let issuedMemberError = false;
41885            for (const member of node.members) {
41886                if (isStatic(member)) {
41887                    continue;
41888                }
41889                const declaredProp = member.name && getSymbolAtLocation(member.name) || getSymbolAtLocation(member);
41890                if (declaredProp) {
41891                    const prop = getPropertyOfType(typeWithThis, declaredProp.escapedName);
41892                    const baseProp = getPropertyOfType(baseWithThis, declaredProp.escapedName);
41893                    if (prop && baseProp) {
41894                        const rootChain = () => chainDiagnosticMessages(
41895                            /*details*/ undefined,
41896                            Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2,
41897                            symbolToString(declaredProp),
41898                            typeToString(typeWithThis),
41899                            typeToString(baseWithThis)
41900                        );
41901                        if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, /*message*/ undefined, rootChain)) {
41902                            issuedMemberError = true;
41903                        }
41904                    }
41905                }
41906            }
41907            if (!issuedMemberError) {
41908                // check again with diagnostics to generate a less-specific error
41909                checkTypeAssignableTo(typeWithThis, baseWithThis, node.name || node, broadDiag);
41910            }
41911        }
41912
41913        function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) {
41914            const signatures = getSignaturesOfType(type, SignatureKind.Construct);
41915            if (signatures.length) {
41916                const declaration = signatures[0].declaration;
41917                if (declaration && hasEffectiveModifier(declaration, ModifierFlags.Private)) {
41918                    const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol)!;
41919                    if (!isNodeWithinClass(node, typeClassDeclaration)) {
41920                        error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol));
41921                    }
41922                }
41923            }
41924        }
41925
41926        /**
41927         * Checks a member declaration node to see if has a missing or invalid `override` modifier.
41928         * @param node Class-like node where the member is declared.
41929         * @param member Member declaration node.
41930         * Note: `member` can be a synthetic node without a parent.
41931         */
41932        function getMemberOverrideModifierStatus(node: ClassLikeDeclaration, member: ClassElement): MemberOverrideStatus {
41933            if (!member.name) {
41934                return MemberOverrideStatus.Ok;
41935            }
41936
41937            const symbol = getSymbolOfNode(node);
41938            const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
41939            const typeWithThis = getTypeWithThisArgument(type);
41940            const staticType = getTypeOfSymbol(symbol) as ObjectType;
41941
41942            const baseTypeNode = getEffectiveBaseTypeNode(node);
41943            const baseTypes = baseTypeNode && getBaseTypes(type);
41944            const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(first(baseTypes), type.thisType) : undefined;
41945            const baseStaticType = getBaseConstructorTypeOfClass(type);
41946
41947            const memberHasOverrideModifier = member.parent
41948                ? hasOverrideModifier(member)
41949                : hasSyntacticModifier(member, ModifierFlags.Override);
41950
41951            const memberName = unescapeLeadingUnderscores(getTextOfPropertyName(member.name));
41952
41953            return checkMemberForOverrideModifier(
41954                node,
41955                staticType,
41956                baseStaticType,
41957                baseWithThis,
41958                type,
41959                typeWithThis,
41960                memberHasOverrideModifier,
41961                hasAbstractModifier(member),
41962                isStatic(member),
41963                /* memberIsParameterProperty */ false,
41964                memberName,
41965            );
41966        }
41967
41968        function getTargetSymbol(s: Symbol) {
41969            // if symbol is instantiated its flags are not copied from the 'target'
41970            // so we'll need to get back original 'target' symbol to work with correct set of flags
41971            return getCheckFlags(s) & CheckFlags.Instantiated ? (s as TransientSymbol).target! : s;
41972        }
41973
41974        function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) {
41975            return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration =>
41976                d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration);
41977        }
41978
41979        function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: BaseType): void {
41980            // TypeScript 1.0 spec (April 2014): 8.2.3
41981            // A derived class inherits all members from its base class it doesn't override.
41982            // Inheritance means that a derived class implicitly contains all non - overridden members of the base class.
41983            // Both public and private property members are inherited, but only public property members can be overridden.
41984            // A property member in a derived class is said to override a property member in a base class
41985            // when the derived class property member has the same name and kind(instance or static)
41986            // as the base class property member.
41987            // The type of an overriding property member must be assignable(section 3.8.4)
41988            // to the type of the overridden property member, or otherwise a compile - time error occurs.
41989            // Base class instance member functions can be overridden by derived class instance member functions,
41990            // but not by other kinds of members.
41991            // Base class instance member variables and accessors can be overridden by
41992            // derived class instance member variables and accessors, but not by other kinds of members.
41993
41994            // NOTE: assignability is checked in checkClassDeclaration
41995            const baseProperties = getPropertiesOfType(baseType);
41996            basePropertyCheck: for (const baseProperty of baseProperties) {
41997                const base = getTargetSymbol(baseProperty);
41998
41999                if (base.flags & SymbolFlags.Prototype) {
42000                    continue;
42001                }
42002                const baseSymbol = getPropertyOfObjectType(type, base.escapedName);
42003                if (!baseSymbol) {
42004                    continue;
42005                }
42006                const derived = getTargetSymbol(baseSymbol);
42007                const baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base);
42008
42009                Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration.");
42010
42011                // In order to resolve whether the inherited method was overridden in the base class or not,
42012                // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated*
42013                // type declaration, derived and base resolve to the same symbol even in the case of generic classes.
42014                if (derived === base) {
42015                    // derived class inherits base without override/redeclaration
42016                    const derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol)!;
42017
42018                    // It is an error to inherit an abstract member without implementing it or being declared abstract.
42019                    // If there is no declaration for the derived class (as in the case of class expressions),
42020                    // then the class cannot be declared abstract.
42021                    if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasSyntacticModifier(derivedClassDecl, ModifierFlags.Abstract))) {
42022                        // Searches other base types for a declaration that would satisfy the inherited abstract member.
42023                        // (The class may have more than one base type via declaration merging with an interface with the
42024                        // same name.)
42025                        for (const otherBaseType of getBaseTypes(type)) {
42026                            if (otherBaseType === baseType) continue;
42027                            const baseSymbol = getPropertyOfObjectType(otherBaseType, base.escapedName);
42028                            const derivedElsewhere = baseSymbol && getTargetSymbol(baseSymbol);
42029                            if (derivedElsewhere && derivedElsewhere !== base) {
42030                                continue basePropertyCheck;
42031                            }
42032                        }
42033
42034                        if (derivedClassDecl.kind === SyntaxKind.ClassExpression) {
42035                            error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1,
42036                                symbolToString(baseProperty), typeToString(baseType));
42037                        }
42038                        else {
42039                            error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
42040                                typeToString(type), symbolToString(baseProperty), typeToString(baseType));
42041                        }
42042                    }
42043                }
42044                else {
42045                    // derived overrides base.
42046                    const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived);
42047                    if (baseDeclarationFlags & ModifierFlags.Private || derivedDeclarationFlags & ModifierFlags.Private) {
42048                        // either base or derived property is private - not override, skip it
42049                        continue;
42050                    }
42051
42052                    let errorMessage: DiagnosticMessage;
42053                    const basePropertyFlags = base.flags & SymbolFlags.PropertyOrAccessor;
42054                    const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor;
42055                    if (basePropertyFlags && derivedPropertyFlags) {
42056                        // property/accessor is overridden with property/accessor
42057                        if ((getCheckFlags(base) & CheckFlags.Synthetic
42058                            ? base.declarations?.some(d => isPropertyAbstractOrInterface(d, baseDeclarationFlags))
42059                            : base.declarations?.every(d => isPropertyAbstractOrInterface(d, baseDeclarationFlags)))
42060                            || getCheckFlags(base) & CheckFlags.Mapped
42061                            || derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) {
42062                            // when the base property is abstract or from an interface, base/derived flags don't need to match
42063                            // for intersection properties, this must be true of *any* of the declarations, for others it must be true of *all*
42064                            // same when the derived property is from an assignment
42065                            continue;
42066                        }
42067
42068                        const overriddenInstanceProperty = basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property;
42069                        const overriddenInstanceAccessor = basePropertyFlags === SymbolFlags.Property && derivedPropertyFlags !== SymbolFlags.Property;
42070                        if (overriddenInstanceProperty || overriddenInstanceAccessor) {
42071                            const errorMessage = overriddenInstanceProperty ?
42072                                Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property :
42073                                Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor;
42074                            error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType), typeToString(type));
42075                        }
42076                        else if (useDefineForClassFields) {
42077                            const uninitialized = derived.declarations?.find(d => d.kind === SyntaxKind.PropertyDeclaration && !(d as PropertyDeclaration).initializer);
42078                            if (uninitialized
42079                                && !(derived.flags & SymbolFlags.Transient)
42080                                && !(baseDeclarationFlags & ModifierFlags.Abstract)
42081                                && !(derivedDeclarationFlags & ModifierFlags.Abstract)
42082                                && !derived.declarations?.some(d => !!(d.flags & NodeFlags.Ambient))) {
42083                                const constructor = findConstructorDeclaration(getClassLikeDeclarationOfSymbol(type.symbol)!);
42084                                const propName = (uninitialized as PropertyDeclaration).name;
42085                                if ((uninitialized as PropertyDeclaration).exclamationToken
42086                                    || !constructor
42087                                    || !isIdentifier(propName)
42088                                    || !strictNullChecks
42089                                    || !isPropertyInitializedInConstructor(propName, type, constructor)) {
42090                                    const errorMessage = Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration;
42091                                    error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType));
42092                                }
42093                            }
42094                        }
42095
42096                        // correct case
42097                        continue;
42098                    }
42099                    else if (isPrototypeProperty(base)) {
42100                        if (isPrototypeProperty(derived) || derived.flags & SymbolFlags.Property) {
42101                            // method is overridden with method or property -- correct case
42102                            continue;
42103                        }
42104                        else {
42105                            Debug.assert(!!(derived.flags & SymbolFlags.Accessor));
42106                            errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor;
42107                        }
42108                    }
42109                    else if (base.flags & SymbolFlags.Accessor) {
42110                        errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
42111                    }
42112                    else {
42113                        errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function;
42114                    }
42115
42116                    error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
42117                }
42118            }
42119        }
42120
42121        function isPropertyAbstractOrInterface(declaration: Declaration, baseDeclarationFlags: ModifierFlags) {
42122            return baseDeclarationFlags & ModifierFlags.Abstract && (!isPropertyDeclaration(declaration) || !declaration.initializer)
42123                || isInterfaceDeclaration(declaration.parent);
42124        }
42125
42126        function getNonInheritedProperties(type: InterfaceType, baseTypes: BaseType[], properties: Symbol[]) {
42127            if (!length(baseTypes)) {
42128                return properties;
42129            }
42130            const seen = new Map<__String, Symbol>();
42131            forEach(properties, p => {
42132                seen.set(p.escapedName, p);
42133            });
42134
42135            for (const base of baseTypes) {
42136                const properties = getPropertiesOfType(getTypeWithThisArgument(base, type.thisType));
42137                for (const prop of properties) {
42138                    const existing = seen.get(prop.escapedName);
42139                    if (existing && prop.parent === existing.parent) {
42140                        seen.delete(prop.escapedName);
42141                    }
42142                }
42143            }
42144
42145            return arrayFrom(seen.values());
42146        }
42147
42148        function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean {
42149            const baseTypes = getBaseTypes(type);
42150            if (baseTypes.length < 2) {
42151                return true;
42152            }
42153
42154            interface InheritanceInfoMap { prop: Symbol; containingType: Type; }
42155            const seen = new Map<__String, InheritanceInfoMap>();
42156            forEach(resolveDeclaredMembers(type).declaredProperties, p => {
42157                seen.set(p.escapedName, { prop: p, containingType: type });
42158            });
42159            let ok = true;
42160
42161            for (const base of baseTypes) {
42162                const properties = getPropertiesOfType(getTypeWithThisArgument(base, type.thisType));
42163                for (const prop of properties) {
42164                    const existing = seen.get(prop.escapedName);
42165                    if (!existing) {
42166                        seen.set(prop.escapedName, { prop, containingType: base });
42167                    }
42168                    else {
42169                        const isInheritedProperty = existing.containingType !== type;
42170                        if (isInheritedProperty && !isPropertyIdenticalTo(existing.prop, prop)) {
42171                            ok = false;
42172
42173                            const typeName1 = typeToString(existing.containingType);
42174                            const typeName2 = typeToString(base);
42175
42176                            let errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2);
42177                            errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
42178                            diagnostics.add(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo));
42179                        }
42180                    }
42181                }
42182            }
42183
42184            return ok;
42185        }
42186
42187        function checkPropertyInitialization(node: ClassLikeDeclaration | AnnotationDeclaration) {
42188            if (!strictNullChecks || !strictPropertyInitialization || node.flags & NodeFlags.Ambient) {
42189                return;
42190            }
42191            const constructor = (!isAnnotationDeclaration(node)) ? findConstructorDeclaration(node) : undefined;
42192            for (const member of node.members) {
42193                if (getEffectiveModifierFlags(member) & ModifierFlags.Ambient) {
42194                    continue;
42195                }
42196                if (!isStatic(member) && isPropertyWithoutInitializer(member)) {
42197                    const propName = (member as PropertyDeclaration).name;
42198                    if (isIdentifier(propName) || isPrivateIdentifier(propName) || isComputedPropertyName(propName)) {
42199                        const type = getTypeOfSymbol(getSymbolOfNode(member));
42200                        if (!(type.flags & TypeFlags.AnyOrUnknown || containsUndefinedType(type))) {
42201                            if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) {
42202                                error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName));
42203                            }
42204                        }
42205                    }
42206                }
42207            }
42208        }
42209
42210        function isPropertyWithoutInitializer(node: Node) {
42211            return node.kind === SyntaxKind.PropertyDeclaration &&
42212                !hasAbstractModifier(node) &&
42213                !(node as PropertyDeclaration).exclamationToken &&
42214                !(node as PropertyDeclaration).initializer;
42215        }
42216
42217        function isPropertyInitializedInStaticBlocks(propName: Identifier | PrivateIdentifier, propType: Type, staticBlocks: readonly ClassStaticBlockDeclaration[], startPos: number, endPos: number) {
42218            for (const staticBlock of staticBlocks) {
42219                // static block must be within the provided range as they are evaluated in document order (unlike constructors)
42220                if (staticBlock.pos >= startPos && staticBlock.pos <= endPos) {
42221                    const reference = factory.createPropertyAccessExpression(factory.createThis(), propName);
42222                    setParent(reference.expression, reference);
42223                    setParent(reference, staticBlock);
42224                    reference.flowNode = staticBlock.returnFlowNode;
42225                    const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
42226                    if (!containsUndefinedType(flowType)) {
42227                        return true;
42228                    }
42229                }
42230            }
42231            return false;
42232        }
42233
42234        function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier | ComputedPropertyName, propType: Type, constructor: ConstructorDeclaration) {
42235            const reference = isComputedPropertyName(propName)
42236                ? factory.createElementAccessExpression(factory.createThis(), propName.expression)
42237                : factory.createPropertyAccessExpression(factory.createThis(), propName);
42238            setParent(reference.expression, reference);
42239            setParent(reference, constructor);
42240            reference.flowNode = constructor.returnFlowNode;
42241            const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
42242            return !containsUndefinedType(flowType);
42243        }
42244
42245
42246        function checkInterfaceDeclaration(node: InterfaceDeclaration) {
42247            // Grammar checking
42248            if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node);
42249
42250            checkTypeParameters(node.typeParameters);
42251            addLazyDiagnostic(() => {
42252                checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
42253
42254                checkExportsOnMergedDeclarations(node);
42255                const symbol = getSymbolOfNode(node);
42256                checkTypeParameterListsIdentical(symbol);
42257
42258                // Only check this symbol once
42259                const firstInterfaceDecl = getDeclarationOfKind<InterfaceDeclaration>(symbol, SyntaxKind.InterfaceDeclaration);
42260                if (node === firstInterfaceDecl) {
42261                    const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
42262                    const typeWithThis = getTypeWithThisArgument(type);
42263                    // run subsequent checks only if first set succeeded
42264                    if (checkInheritedPropertiesAreIdentical(type, node.name)) {
42265                        for (const baseType of getBaseTypes(type)) {
42266                            checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
42267                        }
42268                        checkIndexConstraints(type, symbol);
42269                    }
42270                }
42271                checkObjectTypeForDuplicateDeclarations(node);
42272            });
42273            forEach(getInterfaceBaseTypeNodes(node), heritageElement => {
42274                if (!isEntityNameExpression(heritageElement.expression) || isOptionalChain(heritageElement.expression)) {
42275                    error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments);
42276                }
42277                checkTypeReferenceNode(heritageElement);
42278            });
42279
42280            forEach(node.members, checkSourceElement);
42281
42282            addLazyDiagnostic(() => {
42283                checkTypeForDuplicateIndexSignatures(node);
42284                registerForUnusedIdentifiersCheck(node);
42285            });
42286        }
42287
42288        function checkTypeAliasDeclaration(node: TypeAliasDeclaration) {
42289            // Grammar checking
42290            checkGrammarDecoratorsAndModifiers(node);
42291            checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0);
42292            checkExportsOnMergedDeclarations(node);
42293            checkTypeParameters(node.typeParameters);
42294            if (node.type.kind === SyntaxKind.IntrinsicKeyword) {
42295                if (!intrinsicTypeKinds.has(node.name.escapedText as string) || length(node.typeParameters) !== 1) {
42296                    error(node.type, Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types);
42297                }
42298            }
42299            else {
42300                checkSourceElement(node.type);
42301                registerForUnusedIdentifiersCheck(node);
42302            }
42303        }
42304
42305        function computeEnumMemberValues(node: EnumDeclaration) {
42306            const nodeLinks = getNodeLinks(node);
42307            if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) {
42308                nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed;
42309                let autoValue: number | undefined = 0;
42310                for (const member of node.members) {
42311                    const value = computeMemberValue(member, autoValue);
42312                    getNodeLinks(member).enumMemberValue = value;
42313                    autoValue = typeof value === "number" ? value + 1 : undefined;
42314                }
42315            }
42316        }
42317
42318        function computeMemberValue(member: EnumMember, autoValue: number | undefined) {
42319            if (isComputedNonLiteralName(member.name)) {
42320                error(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums);
42321            }
42322            else {
42323                const text = getTextOfPropertyName(member.name);
42324                if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) {
42325                    error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name);
42326                }
42327            }
42328            if (member.initializer) {
42329                return computeConstantValue(member);
42330            }
42331            // In ambient non-const numeric enum declarations, enum members without initializers are
42332            // considered computed members (as opposed to having auto-incremented values).
42333            if (member.parent.flags & NodeFlags.Ambient && !isEnumConst(member.parent) && getEnumKind(getSymbolOfNode(member.parent)) === EnumKind.Numeric) {
42334                return undefined;
42335            }
42336            // If the member declaration specifies no value, the member is considered a constant enum member.
42337            // If the member is the first member in the enum declaration, it is assigned the value zero.
42338            // Otherwise, it is assigned the value of the immediately preceding member plus one, and an error
42339            // occurs if the immediately preceding member is not a constant enum member.
42340            if (autoValue !== undefined) {
42341                return autoValue;
42342            }
42343            error(member.name, Diagnostics.Enum_member_must_have_initializer);
42344            return undefined;
42345        }
42346
42347        function computeConstantValue(member: EnumMember): string | number | undefined {
42348            const enumKind = getEnumKind(getSymbolOfNode(member.parent));
42349            const isConstEnum = isEnumConst(member.parent);
42350            const initializer = member.initializer!;
42351            const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer);
42352            if (value !== undefined) {
42353                if (isConstEnum && typeof value === "number" && !isFinite(value)) {
42354                    error(initializer, isNaN(value) ?
42355                        Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN :
42356                        Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value);
42357                }
42358            }
42359            else if (enumKind === EnumKind.Literal) {
42360                error(initializer, Diagnostics.Computed_values_are_not_permitted_in_an_enum_with_string_valued_members);
42361                return 0;
42362            }
42363            else if (isConstEnum) {
42364                error(initializer, Diagnostics.const_enum_member_initializers_can_only_contain_literal_values_and_other_computed_enum_values);
42365            }
42366            else if (member.parent.flags & NodeFlags.Ambient) {
42367                error(initializer, Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression);
42368            }
42369            else {
42370                // Only here do we need to check that the initializer is assignable to the enum type.
42371                const source = checkExpression(initializer);
42372                if (!isTypeAssignableToKind(source, TypeFlags.NumberLike)) {
42373                    error(initializer, Diagnostics.Only_numeric_enums_can_have_computed_members_but_this_expression_has_type_0_If_you_do_not_need_exhaustiveness_checks_consider_using_an_object_literal_instead, typeToString(source));
42374                }
42375                else {
42376                    checkTypeAssignableTo(source, getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined);
42377                }
42378            }
42379            return value;
42380
42381            function evaluate(expr: Expression): string | number | undefined {
42382                switch (expr.kind) {
42383                    case SyntaxKind.PrefixUnaryExpression:
42384                        const value = evaluate((expr as PrefixUnaryExpression).operand);
42385                        if (typeof value === "number") {
42386                            switch ((expr as PrefixUnaryExpression).operator) {
42387                                case SyntaxKind.PlusToken: return value;
42388                                case SyntaxKind.MinusToken: return -value;
42389                                case SyntaxKind.TildeToken: return ~value;
42390                            }
42391                        }
42392                        break;
42393                    case SyntaxKind.BinaryExpression:
42394                        const left = evaluate((expr as BinaryExpression).left);
42395                        const right = evaluate((expr as BinaryExpression).right);
42396                        if (typeof left === "number" && typeof right === "number") {
42397                            switch ((expr as BinaryExpression).operatorToken.kind) {
42398                                case SyntaxKind.BarToken: return left | right;
42399                                case SyntaxKind.AmpersandToken: return left & right;
42400                                case SyntaxKind.GreaterThanGreaterThanToken: return left >> right;
42401                                case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return left >>> right;
42402                                case SyntaxKind.LessThanLessThanToken: return left << right;
42403                                case SyntaxKind.CaretToken: return left ^ right;
42404                                case SyntaxKind.AsteriskToken: return left * right;
42405                                case SyntaxKind.SlashToken: return left / right;
42406                                case SyntaxKind.PlusToken: return left + right;
42407                                case SyntaxKind.MinusToken: return left - right;
42408                                case SyntaxKind.PercentToken: return left % right;
42409                                case SyntaxKind.AsteriskAsteriskToken: return left ** right;
42410                            }
42411                        }
42412                        else if (typeof left === "string" && typeof right === "string" && (expr as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken) {
42413                            return left + right;
42414                        }
42415                        break;
42416                    case SyntaxKind.StringLiteral:
42417                    case SyntaxKind.NoSubstitutionTemplateLiteral:
42418                        return (expr as StringLiteralLike).text;
42419                    case SyntaxKind.NumericLiteral:
42420                        checkGrammarNumericLiteral(expr as NumericLiteral);
42421                        return +(expr as NumericLiteral).text;
42422                    case SyntaxKind.ParenthesizedExpression:
42423                        return evaluate((expr as ParenthesizedExpression).expression);
42424                    case SyntaxKind.Identifier:
42425                        const identifier = expr as Identifier;
42426                        if (isInfinityOrNaNString(identifier.escapedText)) {
42427                            return +(identifier.escapedText);
42428                        }
42429                        return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText);
42430                    case SyntaxKind.ElementAccessExpression:
42431                    case SyntaxKind.PropertyAccessExpression:
42432                        if (isConstantMemberAccess(expr)) {
42433                            const type = getTypeOfExpression(expr.expression);
42434                            if (type.symbol && type.symbol.flags & SymbolFlags.Enum) {
42435                                let name: __String;
42436                                if (expr.kind === SyntaxKind.PropertyAccessExpression) {
42437                                    name = expr.name.escapedText;
42438                                }
42439                                else {
42440                                    name = escapeLeadingUnderscores(cast(expr.argumentExpression, isLiteralExpression).text);
42441                                }
42442                                return evaluateEnumMember(expr, type.symbol, name);
42443                            }
42444                        }
42445                        break;
42446                }
42447                return undefined;
42448            }
42449
42450            function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) {
42451                const memberSymbol = enumSymbol.exports!.get(name);
42452                if (memberSymbol) {
42453                    const declaration = memberSymbol.valueDeclaration;
42454                    if (declaration !== member) {
42455                        if (declaration && isBlockScopedNameDeclaredBeforeUse(declaration, member) && isEnumDeclaration(declaration.parent)) {
42456                            return getEnumMemberValue(declaration as EnumMember);
42457                        }
42458                        error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums);
42459                        return 0;
42460                    }
42461                    else {
42462                        error(expr, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(memberSymbol));
42463                    }
42464                }
42465                return undefined;
42466            }
42467        }
42468
42469        function isConstantMemberAccess(node: Expression): node is AccessExpression {
42470            const type = getTypeOfExpression(node);
42471            if (type === errorType) {
42472                return false;
42473            }
42474
42475            return node.kind === SyntaxKind.Identifier ||
42476                node.kind === SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((node as PropertyAccessExpression).expression) ||
42477                node.kind === SyntaxKind.ElementAccessExpression && isConstantMemberAccess((node as ElementAccessExpression).expression) &&
42478                    isStringLiteralLike((node as ElementAccessExpression).argumentExpression);
42479        }
42480
42481        function checkEnumDeclaration(node: EnumDeclaration) {
42482            addLazyDiagnostic(() => checkEnumDeclarationWorker(node));
42483        }
42484
42485        function checkEnumDeclarationWorker(node: EnumDeclaration) {
42486            // Grammar checking
42487            checkGrammarDecoratorsAndModifiers(node);
42488
42489            checkCollisionsForDeclarationName(node, node.name);
42490            checkExportsOnMergedDeclarations(node);
42491            node.members.forEach(checkEnumMember);
42492
42493            computeEnumMemberValues(node);
42494
42495            // Spec 2014 - Section 9.3:
42496            // It isn't possible for one enum declaration to continue the automatic numbering sequence of another,
42497            // and when an enum type has multiple declarations, only one declaration is permitted to omit a value
42498            // for the first member.
42499            //
42500            // Only perform this check once per symbol
42501            const enumSymbol = getSymbolOfNode(node);
42502            const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind);
42503            if (node === firstDeclaration) {
42504                if (enumSymbol.declarations && enumSymbol.declarations.length > 1) {
42505                    const enumIsConst = isEnumConst(node);
42506                    // check that const is placed\omitted on all enum declarations
42507                    forEach(enumSymbol.declarations, decl => {
42508                        if (isEnumDeclaration(decl) && isEnumConst(decl) !== enumIsConst) {
42509                            error(getNameOfDeclaration(decl), Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
42510                        }
42511                    });
42512                }
42513
42514                let seenEnumMissingInitialInitializer = false;
42515                forEach(enumSymbol.declarations, declaration => {
42516                    // return true if we hit a violation of the rule, false otherwise
42517                    if (declaration.kind !== SyntaxKind.EnumDeclaration) {
42518                        return false;
42519                    }
42520
42521                    const enumDeclaration = declaration as EnumDeclaration;
42522                    if (!enumDeclaration.members.length) {
42523                        return false;
42524                    }
42525
42526                    const firstEnumMember = enumDeclaration.members[0];
42527                    if (!firstEnumMember.initializer) {
42528                        if (seenEnumMissingInitialInitializer) {
42529                            error(firstEnumMember.name, Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element);
42530                        }
42531                        else {
42532                            seenEnumMissingInitialInitializer = true;
42533                        }
42534                    }
42535                });
42536            }
42537        }
42538
42539        function checkEnumMember(node: EnumMember) {
42540            if (isPrivateIdentifier(node.name)) {
42541                error(node, Diagnostics.An_enum_member_cannot_be_named_with_a_private_identifier);
42542            }
42543        }
42544
42545        function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration | undefined {
42546            const declarations = symbol.declarations;
42547            if (declarations) {
42548                for (const declaration of declarations) {
42549                    if ((declaration.kind === SyntaxKind.ClassDeclaration ||
42550                        (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((declaration as FunctionLikeDeclaration).body))) &&
42551                        !(declaration.flags & NodeFlags.Ambient)) {
42552                        return declaration;
42553                    }
42554                }
42555            }
42556            return undefined;
42557        }
42558
42559        function inSameLexicalScope(node1: Node, node2: Node) {
42560            const container1 = getEnclosingBlockScopeContainer(node1);
42561            const container2 = getEnclosingBlockScopeContainer(node2);
42562            if (isGlobalSourceFile(container1)) {
42563                return isGlobalSourceFile(container2);
42564            }
42565            else if (isGlobalSourceFile(container2)) {
42566                return false;
42567            }
42568            else {
42569                return container1 === container2;
42570            }
42571        }
42572
42573        function checkModuleDeclaration(node: ModuleDeclaration) {
42574            if (node.body) {
42575                checkSourceElement(node.body);
42576                if (!isGlobalScopeAugmentation(node)) {
42577                    registerForUnusedIdentifiersCheck(node);
42578                }
42579            }
42580
42581            addLazyDiagnostic(checkModuleDeclarationDiagnostics);
42582
42583            function checkModuleDeclarationDiagnostics() {
42584                // Grammar checking
42585                const isGlobalAugmentation = isGlobalScopeAugmentation(node);
42586                const inAmbientContext = node.flags & NodeFlags.Ambient;
42587                if (isGlobalAugmentation && !inAmbientContext) {
42588                    error(node.name, Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context);
42589                }
42590
42591                const isAmbientExternalModule: boolean = isAmbientModule(node);
42592                const contextErrorMessage = isAmbientExternalModule
42593                    ? Diagnostics.An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file
42594                    : Diagnostics.A_namespace_declaration_is_only_allowed_at_the_top_level_of_a_namespace_or_module;
42595                if (checkGrammarModuleElementContext(node, contextErrorMessage)) {
42596                    // If we hit a module declaration in an illegal context, just bail out to avoid cascading errors.
42597                    return;
42598                }
42599
42600                if (!checkGrammarDecoratorsAndModifiers(node)) {
42601                    if (!inAmbientContext && node.name.kind === SyntaxKind.StringLiteral) {
42602                        grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names);
42603                    }
42604                }
42605
42606                if (isIdentifier(node.name)) {
42607                    checkCollisionsForDeclarationName(node, node.name);
42608                }
42609
42610                checkExportsOnMergedDeclarations(node);
42611                const symbol = getSymbolOfNode(node);
42612
42613                // The following checks only apply on a non-ambient instantiated module declaration.
42614                if (symbol.flags & SymbolFlags.ValueModule
42615                    && !inAmbientContext
42616                    && symbol.declarations
42617                    && symbol.declarations.length > 1
42618                    && isInstantiatedModule(node, shouldPreserveConstEnums(compilerOptions))) {
42619                    const firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
42620                    if (firstNonAmbientClassOrFunc) {
42621                        if (getSourceFileOfNode(node) !== getSourceFileOfNode(firstNonAmbientClassOrFunc)) {
42622                            error(node.name, Diagnostics.A_namespace_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
42623                        }
42624                        else if (node.pos < firstNonAmbientClassOrFunc.pos) {
42625                            error(node.name, Diagnostics.A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
42626                        }
42627                    }
42628
42629                    // if the module merges with a class declaration in the same lexical scope,
42630                    // we need to track this to ensure the correct emit.
42631                    const mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);
42632                    if (mergedClass &&
42633                        inSameLexicalScope(node, mergedClass)) {
42634                        getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass;
42635                    }
42636                }
42637
42638                if (isAmbientExternalModule) {
42639                    if (isExternalModuleAugmentation(node)) {
42640                        // body of the augmentation should be checked for consistency only if augmentation was applied to its target (either global scope or module)
42641                        // otherwise we'll be swamped in cascading errors.
42642                        // We can detect if augmentation was applied using following rules:
42643                        // - augmentation for a global scope is always applied
42644                        // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module).
42645                        const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Transient);
42646                        if (checkBody && node.body) {
42647                            for (const statement of node.body.statements) {
42648                                checkModuleAugmentationElement(statement, isGlobalAugmentation);
42649                            }
42650                        }
42651                    }
42652                    else if (isGlobalSourceFile(node.parent)) {
42653                        if (isGlobalAugmentation) {
42654                            error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations);
42655                        }
42656                        else if (isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(node.name))) {
42657                            error(node.name, Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name);
42658                        }
42659                    }
42660                    else {
42661                        if (isGlobalAugmentation) {
42662                            error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations);
42663                        }
42664                        else {
42665                            // Node is not an augmentation and is not located on the script level.
42666                            // This means that this is declaration of ambient module that is located in other module or namespace which is prohibited.
42667                            error(node.name, Diagnostics.Ambient_modules_cannot_be_nested_in_other_modules_or_namespaces);
42668                        }
42669                    }
42670                }
42671            }
42672        }
42673
42674        function checkModuleAugmentationElement(node: Node, isGlobalAugmentation: boolean): void {
42675            switch (node.kind) {
42676                case SyntaxKind.VariableStatement:
42677                    // error each individual name in variable statement instead of marking the entire variable statement
42678                    for (const decl of (node as VariableStatement).declarationList.declarations) {
42679                        checkModuleAugmentationElement(decl, isGlobalAugmentation);
42680                    }
42681                    break;
42682                case SyntaxKind.ExportAssignment:
42683                case SyntaxKind.ExportDeclaration:
42684                    grammarErrorOnFirstToken(node, Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations);
42685                    break;
42686                case SyntaxKind.ImportEqualsDeclaration:
42687                case SyntaxKind.ImportDeclaration:
42688                    grammarErrorOnFirstToken(node, Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module);
42689                    break;
42690                case SyntaxKind.BindingElement:
42691                case SyntaxKind.VariableDeclaration:
42692                    const name = (node as VariableDeclaration | BindingElement).name;
42693                    if (isBindingPattern(name)) {
42694                        for (const el of name.elements) {
42695                            // mark individual names in binding pattern
42696                            checkModuleAugmentationElement(el, isGlobalAugmentation);
42697                        }
42698                        break;
42699                    }
42700                    // falls through
42701                case SyntaxKind.ClassDeclaration:
42702                case SyntaxKind.EnumDeclaration:
42703                case SyntaxKind.FunctionDeclaration:
42704                case SyntaxKind.InterfaceDeclaration:
42705                case SyntaxKind.ModuleDeclaration:
42706                case SyntaxKind.TypeAliasDeclaration:
42707                    if (isGlobalAugmentation) {
42708                        return;
42709                    }
42710                    break;
42711            }
42712        }
42713
42714        function getFirstNonModuleExportsIdentifier(node: EntityNameOrEntityNameExpression): Identifier {
42715            switch (node.kind) {
42716                case SyntaxKind.Identifier:
42717                    return node;
42718                case SyntaxKind.QualifiedName:
42719                    do {
42720                        node = node.left;
42721                    } while (node.kind !== SyntaxKind.Identifier);
42722                    return node;
42723                case SyntaxKind.PropertyAccessExpression:
42724                    do {
42725                        if (isModuleExportsAccessExpression(node.expression) && !isPrivateIdentifier(node.name)) {
42726                            return node.name;
42727                        }
42728                        node = node.expression;
42729                    } while (node.kind !== SyntaxKind.Identifier);
42730                    return node;
42731            }
42732        }
42733
42734        function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean {
42735            const moduleName = getExternalModuleName(node);
42736            if (!moduleName || nodeIsMissing(moduleName)) {
42737                // Should be a parse error.
42738                return false;
42739            }
42740            if (!isStringLiteral(moduleName)) {
42741                error(moduleName, Diagnostics.String_literal_expected);
42742                return false;
42743            }
42744            const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent);
42745            if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) {
42746                error(moduleName, node.kind === SyntaxKind.ExportDeclaration ?
42747                    Diagnostics.Export_declarations_are_not_permitted_in_a_namespace :
42748                    Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module);
42749                return false;
42750            }
42751            if (inAmbientExternalModule && isExternalModuleNameRelative(moduleName.text)) {
42752                // we have already reported errors on top level imports/exports in external module augmentations in checkModuleDeclaration
42753                // no need to do this again.
42754                if (!isTopLevelInExternalModuleAugmentation(node)) {
42755                    // TypeScript 1.0 spec (April 2013): 12.1.6
42756                    // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference
42757                    // other external modules only through top - level external module names.
42758                    // Relative external module names are not permitted.
42759                    error(node, Diagnostics.Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name);
42760                    return false;
42761                }
42762            }
42763            if (!isImportEqualsDeclaration(node) && node.assertClause) {
42764                let hasError = false;
42765                for (const clause of node.assertClause.elements) {
42766                    if (!isStringLiteral(clause.value)) {
42767                        hasError = true;
42768                        error(clause.value, Diagnostics.Import_assertion_values_must_be_string_literal_expressions);
42769                    }
42770                }
42771                return !hasError;
42772            }
42773            return true;
42774        }
42775
42776        function checkAliasSymbol(node: ImportEqualsDeclaration | VariableDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier | NamespaceExport | BindingElement) {
42777            let symbol = getSymbolOfNode(node);
42778            const target = resolveAlias(symbol);
42779
42780            if (target !== unknownSymbol) {
42781                // For external modules, `symbol` represents the local symbol for an alias.
42782                // This local symbol will merge any other local declarations (excluding other aliases)
42783                // and symbol.flags will contains combined representation for all merged declaration.
42784                // Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have,
42785                // otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export*
42786                // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names).
42787                symbol = getMergedSymbol(symbol.exportSymbol || symbol);
42788
42789                // A type-only import/export will already have a grammar error in a JS file, so no need to issue more errors within
42790                if (isInJSFile(node) && !(target.flags & SymbolFlags.Value) && !isTypeOnlyImportOrExportDeclaration(node)) {
42791                    const errorNode =
42792                        isImportOrExportSpecifier(node) ? node.propertyName || node.name :
42793                        isNamedDeclaration(node) ? node.name :
42794                        node;
42795
42796                    Debug.assert(node.kind !== SyntaxKind.NamespaceExport);
42797                    if (node.kind === SyntaxKind.ExportSpecifier) {
42798                        const diag = error(errorNode, Diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files);
42799                        const alreadyExportedSymbol = getSourceFileOfNode(node).symbol?.exports?.get((node.propertyName || node.name).escapedText);
42800                        if (alreadyExportedSymbol === target) {
42801                            const exportingDeclaration = alreadyExportedSymbol.declarations?.find(isJSDocNode);
42802                            if (exportingDeclaration) {
42803                                addRelatedInfo(diag, createDiagnosticForNode(
42804                                    exportingDeclaration,
42805                                    Diagnostics._0_is_automatically_exported_here,
42806                                    unescapeLeadingUnderscores(alreadyExportedSymbol.escapedName)));
42807                            }
42808                        }
42809                    }
42810                    else {
42811                        Debug.assert(node.kind !== SyntaxKind.VariableDeclaration);
42812                        const importDeclaration = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration));
42813                        const moduleSpecifier = (importDeclaration && tryGetModuleSpecifierFromDeclaration(importDeclaration)?.text) ?? "...";
42814                        const importedIdentifier = unescapeLeadingUnderscores(isIdentifier(errorNode) ? errorNode.escapedText : symbol.escapedName);
42815                        error(
42816                            errorNode,
42817                            Diagnostics._0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation,
42818                            importedIdentifier,
42819                            `import("${moduleSpecifier}").${importedIdentifier}`);
42820                    }
42821                    return;
42822                }
42823
42824                const targetFlags = getAllSymbolFlags(target);
42825                const excludedMeanings =
42826                    (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) |
42827                    (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
42828                    (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0);
42829                if (targetFlags & excludedMeanings) {
42830                    const message = node.kind === SyntaxKind.ExportSpecifier ?
42831                        Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 :
42832                        Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0;
42833                    error(node, message, symbolToString(symbol));
42834                }
42835
42836                if (compilerOptions.isolatedModules
42837                    && !isTypeOnlyImportOrExportDeclaration(node)
42838                    && !(node.flags & NodeFlags.Ambient)) {
42839                    const typeOnlyAlias = getTypeOnlyAliasDeclaration(symbol);
42840                    const isType = !(targetFlags & SymbolFlags.Value);
42841                    if (isType || typeOnlyAlias) {
42842                        switch (node.kind) {
42843                            case SyntaxKind.ImportClause:
42844                            case SyntaxKind.ImportSpecifier:
42845                            case SyntaxKind.ImportEqualsDeclaration: {
42846                                if (compilerOptions.preserveValueImports) {
42847                                    Debug.assertIsDefined(node.name, "An ImportClause with a symbol should have a name");
42848                                    const message = isType
42849                                        ? Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled
42850                                        : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled;
42851                                    const name = idText(node.kind === SyntaxKind.ImportSpecifier ? node.propertyName || node.name : node.name);
42852                                    addTypeOnlyDeclarationRelatedInfo(
42853                                        error(node, message, name),
42854                                        isType ? undefined : typeOnlyAlias,
42855                                        name
42856                                    );
42857                                }
42858                                if (isType && node.kind === SyntaxKind.ImportEqualsDeclaration && hasEffectiveModifier(node, ModifierFlags.Export)) {
42859                                    error(node, Diagnostics.Cannot_use_export_import_on_a_type_or_type_only_namespace_when_the_isolatedModules_flag_is_provided);
42860                                }
42861                                break;
42862                            }
42863                            case SyntaxKind.ExportSpecifier: {
42864                                // Don't allow re-exporting an export that will be elided when `--isolatedModules` is set.
42865                                // The exception is that `import type { A } from './a'; export { A }` is allowed
42866                                // because single-file analysis can determine that the export should be dropped.
42867                                if (getSourceFileOfNode(typeOnlyAlias) !== getSourceFileOfNode(node)) {
42868                                    const message = isType
42869                                        ? Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type
42870                                        : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_isolatedModules_is_enabled;
42871                                    const name = idText(node.propertyName || node.name);
42872                                    addTypeOnlyDeclarationRelatedInfo(
42873                                        error(node, message, name),
42874                                        isType ? undefined : typeOnlyAlias,
42875                                        name
42876                                    );
42877                                    return;
42878                                }
42879                            }
42880                        }
42881                    }
42882                }
42883
42884                if (isImportSpecifier(node)) {
42885                    const targetSymbol = checkDeprecatedAliasedSymbol(symbol, node);
42886                    if (isDeprecatedAliasedSymbol(targetSymbol) && targetSymbol.declarations) {
42887                        addDeprecatedSuggestion(node, targetSymbol.declarations, targetSymbol.escapedName as string);
42888                    }
42889                }
42890
42891                if ((isImportSpecifier(node) || isExportSpecifier(node))) {
42892                    if (targetFlags & SymbolFlags.Annotation) {
42893                        getNodeLinks(node).exportOrImportRefersToAnnotation = true;
42894                        if (node.propertyName) {
42895                            error(node, Diagnostics.Annotation_cannot_be_renamed_in_import_or_export);
42896                        }
42897                    }
42898                }
42899
42900                if (!isVariableDeclaration(node) && !isBindingElement(node)) {
42901                    if (targetFlags & SymbolFlags.ConstEnum) {
42902                        checkConstEnumRelate(node, target);
42903                    }
42904                }
42905            }
42906        }
42907
42908        function isDeprecatedAliasedSymbol(symbol: Symbol) {
42909            return !!symbol.declarations && every(symbol.declarations, d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated));
42910        }
42911
42912        function checkDeprecatedAliasedSymbol(symbol: Symbol, location: Node) {
42913            if (!(symbol.flags & SymbolFlags.Alias)) return symbol;
42914
42915            const targetSymbol = resolveAlias(symbol);
42916            if (targetSymbol === unknownSymbol) return targetSymbol;
42917
42918            while (symbol.flags & SymbolFlags.Alias) {
42919                const target = getImmediateAliasedSymbol(symbol);
42920                if (target) {
42921                    if (target === targetSymbol) break;
42922                    if (target.declarations && length(target.declarations)) {
42923                        if (isDeprecatedAliasedSymbol(target)) {
42924                            addDeprecatedSuggestion(location, target.declarations, target.escapedName as string);
42925                            break;
42926                        }
42927                        else {
42928                            if (symbol === targetSymbol) break;
42929                            symbol = target;
42930                        }
42931                    }
42932                }
42933                else {
42934                    break;
42935                }
42936            }
42937            return targetSymbol;
42938        }
42939
42940        function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
42941            checkCollisionsForDeclarationName(node, node.name);
42942            checkAliasSymbol(node);
42943            if (node.kind === SyntaxKind.ImportSpecifier &&
42944                idText(node.propertyName || node.name) === "default" &&
42945                getESModuleInterop(compilerOptions) &&
42946                moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) {
42947                checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault);
42948            }
42949        }
42950
42951        function checkAssertClause(declaration: ImportDeclaration | ExportDeclaration) {
42952            if (declaration.assertClause) {
42953                const validForTypeAssertions = isExclusivelyTypeOnlyImportOrExport(declaration);
42954                const override = getResolutionModeOverrideForClause(declaration.assertClause, validForTypeAssertions ? grammarErrorOnNode : undefined);
42955                if (validForTypeAssertions && override) {
42956                    if (!isNightly()) {
42957                        grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next);
42958                    }
42959
42960                    if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) {
42961                        return grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext);
42962                    }
42963                    return; // Other grammar checks do not apply to type-only imports with resolution mode assertions
42964                }
42965
42966                const mode = (moduleKind === ModuleKind.NodeNext) && declaration.moduleSpecifier && getUsageModeForExpression(declaration.moduleSpecifier);
42967                if (mode !== ModuleKind.ESNext && moduleKind !== ModuleKind.ESNext) {
42968                    return grammarErrorOnNode(declaration.assertClause,
42969                        moduleKind === ModuleKind.NodeNext
42970                            ? Diagnostics.Import_assertions_are_not_allowed_on_statements_that_transpile_to_commonjs_require_calls
42971                            : Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_or_nodenext);
42972                }
42973
42974                if (isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly) {
42975                    return grammarErrorOnNode(declaration.assertClause, Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports);
42976                }
42977
42978                if (override) {
42979                    return grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_can_only_be_set_for_type_only_imports);
42980                }
42981            }
42982        }
42983
42984        function checkImportDeclaration(node: ImportDeclaration) {
42985            if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) {
42986                // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
42987                return;
42988            }
42989            if (!checkGrammarDecoratorsAndModifiers(node) && hasEffectiveModifiers(node)) {
42990                grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
42991            }
42992            if (checkExternalImportOrExportDeclaration(node)) {
42993                const importClause = node.importClause;
42994                if (importClause && !checkGrammarImportClause(importClause)) {
42995                    if (importClause.name) {
42996                        checkImportBinding(importClause);
42997                    }
42998                    if (importClause.namedBindings) {
42999                        if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
43000                            checkImportBinding(importClause.namedBindings);
43001                            if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && getESModuleInterop(compilerOptions)) {
43002                                // import * as ns from "foo";
43003                                checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar);
43004                            }
43005                        }
43006                        else {
43007                            const moduleExisted = resolveExternalModuleName(node, node.moduleSpecifier);
43008                            if (moduleExisted) {
43009                                forEach(importClause.namedBindings.elements, checkImportBinding);
43010                            }
43011                        }
43012                    }
43013                }
43014            }
43015            checkAssertClause(node);
43016        }
43017
43018        function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) {
43019            if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) {
43020                // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
43021                return;
43022            }
43023
43024            checkGrammarDecoratorsAndModifiers(node);
43025            if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
43026                checkImportBinding(node);
43027                if (hasSyntacticModifier(node, ModifierFlags.Export)) {
43028                    markExportAsReferenced(node);
43029                }
43030                if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) {
43031                    const target = resolveAlias(getSymbolOfNode(node));
43032                    if (target !== unknownSymbol) {
43033                        const targetFlags = getAllSymbolFlags(target);
43034                        if (targetFlags & SymbolFlags.Value) {
43035                            // Target is a value symbol, check that it is not hidden by a local declaration with the same name
43036                            const moduleName = getFirstIdentifier(node.moduleReference);
43037                            if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace)!.flags & SymbolFlags.Namespace)) {
43038                                error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName));
43039                            }
43040                        }
43041                        if (targetFlags & SymbolFlags.Type) {
43042                            checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0);
43043                        }
43044                    }
43045                    if (node.isTypeOnly) {
43046                        grammarErrorOnNode(node, Diagnostics.An_import_alias_cannot_use_import_type);
43047                    }
43048                }
43049                else {
43050                    if (moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) {
43051                        // Import equals declaration is deprecated in es6 or above
43052                        grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead);
43053                    }
43054                }
43055            }
43056        }
43057
43058        function checkExportDeclaration(node: ExportDeclaration) {
43059            if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) {
43060                // If we hit an export in an illegal context, just bail out to avoid cascading errors.
43061                return;
43062            }
43063
43064            if (!checkGrammarDecoratorsAndModifiers(node) && hasSyntacticModifiers(node)) {
43065                grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers);
43066            }
43067
43068            if (node.moduleSpecifier && node.exportClause && isNamedExports(node.exportClause) && length(node.exportClause.elements) && languageVersion === ScriptTarget.ES3) {
43069                checkExternalEmitHelpers(node, ExternalEmitHelpers.CreateBinding);
43070            }
43071
43072            checkGrammarExportDeclaration(node);
43073            if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) {
43074                if (node.exportClause && !isNamespaceExport(node.exportClause)) {
43075                    // export { x, y }
43076                    // export { x, y } from "foo"
43077                    forEach(node.exportClause.elements, checkExportSpecifier);
43078                    const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent);
43079                    const inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === SyntaxKind.ModuleBlock &&
43080                        !node.moduleSpecifier && node.flags & NodeFlags.Ambient;
43081                    if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) {
43082                        error(node, Diagnostics.Export_declarations_are_not_permitted_in_a_namespace);
43083                    }
43084                }
43085                else {
43086                    // export * from "foo"
43087                    // export * as ns from "foo";
43088                    const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier!);
43089                    if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) {
43090                        error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
43091                    }
43092                    else if (node.exportClause) {
43093                        checkAliasSymbol(node.exportClause);
43094                    }
43095                    if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) {
43096                        if (node.exportClause) {
43097                            // export * as ns from "foo";
43098                            // For ES2015 modules, we emit it as a pair of `import * as a_1 ...; export { a_1 as ns }` and don't need the helper.
43099                            // We only use the helper here when in esModuleInterop
43100                            if (getESModuleInterop(compilerOptions)) {
43101                                checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar);
43102                            }
43103                        }
43104                        else {
43105                            // export * from "foo"
43106                            checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar);
43107                        }
43108                    }
43109                }
43110            }
43111            checkAssertClause(node);
43112        }
43113
43114        function checkGrammarExportDeclaration(node: ExportDeclaration): boolean {
43115            if (node.isTypeOnly) {
43116                if (node.exportClause?.kind === SyntaxKind.NamedExports) {
43117                    return checkGrammarNamedImportsOrExports(node.exportClause);
43118                }
43119                else {
43120                    return grammarErrorOnNode(node, Diagnostics.Only_named_exports_may_use_export_type);
43121                }
43122            }
43123            return false;
43124        }
43125
43126        function checkGrammarModuleElementContext(node: Statement, errorMessage: DiagnosticMessage): boolean {
43127            const isInAppropriateContext = node.parent.kind === SyntaxKind.SourceFile || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration;
43128            if (!isInAppropriateContext) {
43129                grammarErrorOnFirstToken(node, errorMessage);
43130            }
43131            return !isInAppropriateContext;
43132        }
43133
43134        function importClauseContainsReferencedImport(importClause: ImportClause) {
43135            return forEachImportClauseDeclaration(importClause, declaration => {
43136                return !!getSymbolOfNode(declaration).isReferenced;
43137            });
43138        }
43139
43140        function importClauseContainsConstEnumUsedAsValue(importClause: ImportClause) {
43141            return forEachImportClauseDeclaration(importClause, declaration => {
43142                return !!getSymbolLinks(getSymbolOfNode(declaration)).constEnumReferenced;
43143            });
43144        }
43145
43146        function canConvertImportDeclarationToTypeOnly(statement: Statement) {
43147            return isImportDeclaration(statement) &&
43148                statement.importClause &&
43149                !statement.importClause.isTypeOnly &&
43150                importClauseContainsReferencedImport(statement.importClause) &&
43151                !isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true) &&
43152                !importClauseContainsConstEnumUsedAsValue(statement.importClause);
43153        }
43154
43155        function canConvertImportEqualsDeclarationToTypeOnly(statement: Statement) {
43156            return isImportEqualsDeclaration(statement) &&
43157                isExternalModuleReference(statement.moduleReference) &&
43158                !statement.isTypeOnly &&
43159                getSymbolOfNode(statement).isReferenced &&
43160                !isReferencedAliasDeclaration(statement, /*checkChildren*/ false) &&
43161                !getSymbolLinks(getSymbolOfNode(statement)).constEnumReferenced;
43162        }
43163
43164        function checkImportsForTypeOnlyConversion(sourceFile: SourceFile) {
43165            for (const statement of sourceFile.statements) {
43166                if (canConvertImportDeclarationToTypeOnly(statement) || canConvertImportEqualsDeclarationToTypeOnly(statement)) {
43167                    error(
43168                        statement,
43169                        Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error);
43170                }
43171            }
43172        }
43173
43174        function checkExportSpecifier(node: ExportSpecifier) {
43175            checkAliasSymbol(node);
43176            if (getEmitDeclarations(compilerOptions)) {
43177                collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true);
43178            }
43179            if (!node.parent.parent.moduleSpecifier) {
43180                const exportedName = node.propertyName || node.name;
43181                // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases)
43182                const symbol = resolveName(exportedName, exportedName.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias,
43183                    /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
43184                if (symbol && (symbol === undefinedSymbol || symbol === globalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) {
43185                    error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName));
43186                }
43187                else {
43188                    if (!node.isTypeOnly && !node.parent.parent.isTypeOnly) {
43189                        markExportAsReferenced(node);
43190                    }
43191                    const target = symbol && (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol);
43192                    if (!target || getAllSymbolFlags(target) & SymbolFlags.Value) {
43193                        checkExpressionCached(node.propertyName || node.name);
43194                    }
43195                }
43196            }
43197            else {
43198                if (getESModuleInterop(compilerOptions) &&
43199                    moduleKind !== ModuleKind.System &&
43200                    (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) &&
43201                    idText(node.propertyName || node.name) === "default") {
43202                    checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault);
43203                }
43204            }
43205        }
43206
43207        function checkAnnotationInExportAssignment(node: ExportAssignment) {
43208            let ident;
43209            switch (node.expression.kind) {
43210                case SyntaxKind.Identifier:
43211                    ident = node.expression as Identifier;
43212                    break;
43213                case SyntaxKind.PropertyAccessExpression:
43214                    ident = node.expression as PropertyAccessExpression;
43215                    break;
43216                default:
43217                    return;
43218            }
43219            if (!ident) {
43220                return;
43221            }
43222            const symbol = getSymbolOfNameOrPropertyAccessExpression(ident, /*ignoreErrors*/ true);
43223            if (!symbol) {
43224                return;
43225            }
43226            if (getAllSymbolFlags(symbol) & SymbolFlags.Annotation) {
43227                getNodeLinks(node).exportOrImportRefersToAnnotation = true;
43228                if (node.isExportEquals === undefined) {
43229                    error(node, Diagnostics.Annotation_cannot_be_exported_as_default);
43230                }
43231            }
43232        }
43233
43234        function checkExportAssignment(node: ExportAssignment) {
43235            const illegalContextMessage = node.isExportEquals
43236                ? Diagnostics.An_export_assignment_must_be_at_the_top_level_of_a_file_or_module_declaration
43237                : Diagnostics.A_default_export_must_be_at_the_top_level_of_a_file_or_module_declaration;
43238            if (checkGrammarModuleElementContext(node, illegalContextMessage)) {
43239                // If we hit an export assignment in an illegal context, just bail out to avoid cascading errors.
43240                return;
43241            }
43242
43243            const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent as ModuleDeclaration;
43244            if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) {
43245                if (node.isExportEquals) {
43246                    error(node, Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace);
43247                }
43248                else {
43249                    error(node, Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module);
43250                }
43251
43252                return;
43253            }
43254            // Grammar checking
43255            if (!checkGrammarDecoratorsAndModifiers(node) && hasEffectiveModifiers(node)) {
43256                grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
43257            }
43258
43259            const typeAnnotationNode = getEffectiveTypeAnnotationNode(node);
43260            if (typeAnnotationNode) {
43261                checkTypeAssignableTo(checkExpressionCached(node.expression), getTypeFromTypeNode(typeAnnotationNode), node.expression);
43262            }
43263
43264            if (node.expression.kind === SyntaxKind.Identifier) {
43265                const id = node.expression as Identifier;
43266                const sym = resolveEntityName(id, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node);
43267                if (sym) {
43268                    markAliasReferenced(sym, id);
43269                    // If not a value, we're interpreting the identifier as a type export, along the lines of (`export { Id as default }`)
43270                    const target = sym.flags & SymbolFlags.Alias ? resolveAlias(sym) : sym;
43271                    if (getAllSymbolFlags(target) & SymbolFlags.Value) {
43272                        // However if it is a value, we need to check it's being used correctly
43273                        checkExpressionCached(node.expression);
43274                    }
43275                }
43276                else {
43277                    checkExpressionCached(node.expression); // doesn't resolve, check as expression to mark as error
43278                }
43279
43280                if (getEmitDeclarations(compilerOptions)) {
43281                    collectLinkedAliases(node.expression as Identifier, /*setVisibility*/ true);
43282                }
43283            }
43284            else {
43285                checkExpressionCached(node.expression);
43286            }
43287
43288            checkAnnotationInExportAssignment(node);
43289
43290            checkExternalModuleExports(container);
43291
43292            if ((node.flags & NodeFlags.Ambient) && !isEntityNameExpression(node.expression)) {
43293                grammarErrorOnNode(node.expression, Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context);
43294            }
43295
43296            if (node.isExportEquals && !(node.flags & NodeFlags.Ambient)) {
43297                if (moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.CommonJS) {
43298                    // export assignment is not supported in es6 modules
43299                    grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead);
43300                }
43301                else if (moduleKind === ModuleKind.System) {
43302                    // system modules does not support export assignment
43303                    grammarErrorOnNode(node, Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system);
43304                }
43305            }
43306        }
43307
43308        function hasExportedMembers(moduleSymbol: Symbol) {
43309            return forEachEntry(moduleSymbol.exports!, (_, id) => id !== "export=");
43310        }
43311
43312        function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) {
43313            const moduleSymbol = getSymbolOfNode(node);
43314            const links = getSymbolLinks(moduleSymbol);
43315            if (!links.exportsChecked) {
43316                const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String);
43317                if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) {
43318                    const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
43319                    if (declaration && !isTopLevelInExternalModuleAugmentation(declaration) && !isInJSFile(declaration)) {
43320                        error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
43321                    }
43322                }
43323                // Checks for export * conflicts
43324                const exports = getExportsOfModule(moduleSymbol);
43325                if (exports) {
43326                    exports.forEach(({ declarations, flags }, id) => {
43327                        if (id === "__export") {
43328                            return;
43329                        }
43330                        // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
43331                        // (TS Exceptions: namespaces, function overloads, enums, and interfaces)
43332                        if (flags & (SymbolFlags.Namespace | SymbolFlags.Enum)) {
43333                            return;
43334                        }
43335                        const exportedDeclarationsCount = countWhere(declarations, and(isNotOverloadAndNotAccessor, not(isInterfaceDeclaration)));
43336                        if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) {
43337                            // it is legal to merge type alias with other values
43338                            // so count should be either 1 (just type alias) or 2 (type alias + merged value)
43339                            return;
43340                        }
43341                        if (exportedDeclarationsCount > 1) {
43342                            if (!isDuplicatedCommonJSExport(declarations)) {
43343                                for (const declaration of declarations!) {
43344                                    if (isNotOverload(declaration)) {
43345                                        diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id)));
43346                                    }
43347                                }
43348                            }
43349                        }
43350                    });
43351                }
43352                links.exportsChecked = true;
43353            }
43354        }
43355
43356        function isDuplicatedCommonJSExport(declarations: Declaration[] | undefined) {
43357            return declarations
43358                && declarations.length > 1
43359                && declarations.every(d => isInJSFile(d) && isAccessExpression(d) && (isExportsIdentifier(d.expression) || isModuleExportsAccessExpression(d.expression)));
43360        }
43361
43362        function checkSourceElement(node: Node | undefined): void {
43363            if (node) {
43364                const saveCurrentNode = currentNode;
43365                currentNode = node;
43366                instantiationCount = 0;
43367                checkSourceElementWorker(node);
43368                currentNode = saveCurrentNode;
43369            }
43370        }
43371
43372        function checkSourceElementWorker(node: Node): void {
43373            forEach((node as JSDocContainer).jsDoc, ({ comment, tags }) => {
43374                checkJSDocCommentWorker(comment);
43375                forEach(tags, tag => {
43376                    checkJSDocCommentWorker(tag.comment);
43377                    if (isInJSFile(node)) {
43378                        checkSourceElement(tag);
43379                    }
43380                });
43381            });
43382
43383            const kind = node.kind;
43384            if (cancellationToken) {
43385                // Only bother checking on a few construct kinds.  We don't want to be excessively
43386                // hitting the cancellation token on every node we check.
43387                switch (kind) {
43388                    case SyntaxKind.ModuleDeclaration:
43389                    case SyntaxKind.ClassDeclaration:
43390                    case SyntaxKind.InterfaceDeclaration:
43391                    case SyntaxKind.FunctionDeclaration:
43392                        cancellationToken.throwIfCancellationRequested();
43393                }
43394            }
43395            if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && node.flowNode && !isReachableFlowNode(node.flowNode)) {
43396                errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, Diagnostics.Unreachable_code_detected);
43397            }
43398
43399            switch (kind) {
43400                case SyntaxKind.TypeParameter:
43401                    return checkTypeParameter(node as TypeParameterDeclaration);
43402                case SyntaxKind.Parameter:
43403                    return checkParameter(node as ParameterDeclaration);
43404                case SyntaxKind.PropertyDeclaration:
43405                    return checkPropertyDeclaration(node as PropertyDeclaration);
43406                case SyntaxKind.PropertySignature:
43407                    return checkPropertySignature(node as PropertySignature);
43408                case SyntaxKind.AnnotationPropertyDeclaration:
43409                    return checkPropertyDeclaration(node as AnnotationPropertyDeclaration);
43410                case SyntaxKind.ConstructorType:
43411                case SyntaxKind.FunctionType:
43412                case SyntaxKind.CallSignature:
43413                case SyntaxKind.ConstructSignature:
43414                case SyntaxKind.IndexSignature:
43415                    return checkSignatureDeclaration(node as SignatureDeclaration);
43416                case SyntaxKind.MethodDeclaration:
43417                case SyntaxKind.MethodSignature:
43418                    return checkMethodDeclaration(node as MethodDeclaration | MethodSignature);
43419                case SyntaxKind.ClassStaticBlockDeclaration:
43420                    return checkClassStaticBlockDeclaration(node as ClassStaticBlockDeclaration);
43421                case SyntaxKind.Constructor:
43422                    return checkConstructorDeclaration(node as ConstructorDeclaration);
43423                case SyntaxKind.GetAccessor:
43424                case SyntaxKind.SetAccessor:
43425                    return checkAccessorDeclaration(node as AccessorDeclaration);
43426                case SyntaxKind.TypeReference:
43427                    return checkTypeReferenceNode(node as TypeReferenceNode);
43428                case SyntaxKind.TypePredicate:
43429                    return checkTypePredicate(node as TypePredicateNode);
43430                case SyntaxKind.TypeQuery:
43431                    return checkTypeQuery(node as TypeQueryNode);
43432                case SyntaxKind.TypeLiteral:
43433                    return checkTypeLiteral(node as TypeLiteralNode);
43434                case SyntaxKind.ArrayType:
43435                    return checkArrayType(node as ArrayTypeNode);
43436                case SyntaxKind.TupleType:
43437                    return checkTupleType(node as TupleTypeNode);
43438                case SyntaxKind.UnionType:
43439                case SyntaxKind.IntersectionType:
43440                    return checkUnionOrIntersectionType(node as UnionOrIntersectionTypeNode);
43441                case SyntaxKind.ParenthesizedType:
43442                case SyntaxKind.OptionalType:
43443                case SyntaxKind.RestType:
43444                    return checkSourceElement((node as ParenthesizedTypeNode | OptionalTypeNode | RestTypeNode).type);
43445                case SyntaxKind.ThisType:
43446                    return checkThisType(node as ThisTypeNode);
43447                case SyntaxKind.TypeOperator:
43448                    return checkTypeOperator(node as TypeOperatorNode);
43449                case SyntaxKind.ConditionalType:
43450                    return checkConditionalType(node as ConditionalTypeNode);
43451                case SyntaxKind.InferType:
43452                    return checkInferType(node as InferTypeNode);
43453                case SyntaxKind.TemplateLiteralType:
43454                    return checkTemplateLiteralType(node as TemplateLiteralTypeNode);
43455                case SyntaxKind.ImportType:
43456                    return checkImportType(node as ImportTypeNode);
43457                case SyntaxKind.NamedTupleMember:
43458                    return checkNamedTupleMember(node as NamedTupleMember);
43459                case SyntaxKind.JSDocAugmentsTag:
43460                    return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
43461                case SyntaxKind.JSDocImplementsTag:
43462                    return checkJSDocImplementsTag(node as JSDocImplementsTag);
43463                case SyntaxKind.JSDocTypedefTag:
43464                case SyntaxKind.JSDocCallbackTag:
43465                case SyntaxKind.JSDocEnumTag:
43466                    return checkJSDocTypeAliasTag(node as JSDocTypedefTag);
43467                case SyntaxKind.JSDocTemplateTag:
43468                    return checkJSDocTemplateTag(node as JSDocTemplateTag);
43469                case SyntaxKind.JSDocTypeTag:
43470                    return checkJSDocTypeTag(node as JSDocTypeTag);
43471                case SyntaxKind.JSDocLink:
43472                case SyntaxKind.JSDocLinkCode:
43473                case SyntaxKind.JSDocLinkPlain:
43474                    return checkJSDocLinkLikeTag(node as JSDocLink | JSDocLinkCode | JSDocLinkPlain);
43475                case SyntaxKind.JSDocParameterTag:
43476                    return checkJSDocParameterTag(node as JSDocParameterTag);
43477                case SyntaxKind.JSDocPropertyTag:
43478                    return checkJSDocPropertyTag(node as JSDocPropertyTag);
43479                case SyntaxKind.JSDocFunctionType:
43480                    checkJSDocFunctionType(node as JSDocFunctionType);
43481                    // falls through
43482                case SyntaxKind.JSDocNonNullableType:
43483                case SyntaxKind.JSDocNullableType:
43484                case SyntaxKind.JSDocAllType:
43485                case SyntaxKind.JSDocUnknownType:
43486                case SyntaxKind.JSDocTypeLiteral:
43487                    checkJSDocTypeIsInJsFile(node);
43488                    forEachChild(node, checkSourceElement);
43489                    return;
43490                case SyntaxKind.JSDocVariadicType:
43491                    checkJSDocVariadicType(node as JSDocVariadicType);
43492                    return;
43493                case SyntaxKind.JSDocTypeExpression:
43494                    return checkSourceElement((node as JSDocTypeExpression).type);
43495                case SyntaxKind.JSDocPublicTag:
43496                case SyntaxKind.JSDocProtectedTag:
43497                case SyntaxKind.JSDocPrivateTag:
43498                    return checkJSDocAccessibilityModifiers(node as JSDocPublicTag | JSDocProtectedTag | JSDocPrivateTag);
43499                case SyntaxKind.IndexedAccessType:
43500                    return checkIndexedAccessType(node as IndexedAccessTypeNode);
43501                case SyntaxKind.MappedType:
43502                    return checkMappedType(node as MappedTypeNode);
43503                case SyntaxKind.FunctionDeclaration:
43504                    return checkFunctionDeclaration(node as FunctionDeclaration);
43505                case SyntaxKind.Block:
43506                case SyntaxKind.ModuleBlock:
43507                    return checkBlock(node as Block);
43508                case SyntaxKind.VariableStatement:
43509                    return checkVariableStatement(node as VariableStatement);
43510                case SyntaxKind.ExpressionStatement:
43511                    return checkExpressionStatement(node as ExpressionStatement);
43512                case SyntaxKind.IfStatement:
43513                    return checkIfStatement(node as IfStatement);
43514                case SyntaxKind.DoStatement:
43515                    return checkDoStatement(node as DoStatement);
43516                case SyntaxKind.WhileStatement:
43517                    return checkWhileStatement(node as WhileStatement);
43518                case SyntaxKind.ForStatement:
43519                    return checkForStatement(node as ForStatement);
43520                case SyntaxKind.ForInStatement:
43521                    return checkForInStatement(node as ForInStatement);
43522                case SyntaxKind.ForOfStatement:
43523                    return checkForOfStatement(node as ForOfStatement);
43524                case SyntaxKind.ContinueStatement:
43525                case SyntaxKind.BreakStatement:
43526                    return checkBreakOrContinueStatement(node as BreakOrContinueStatement);
43527                case SyntaxKind.ReturnStatement:
43528                    return checkReturnStatement(node as ReturnStatement);
43529                case SyntaxKind.WithStatement:
43530                    return checkWithStatement(node as WithStatement);
43531                case SyntaxKind.SwitchStatement:
43532                    return checkSwitchStatement(node as SwitchStatement);
43533                case SyntaxKind.LabeledStatement:
43534                    return checkLabeledStatement(node as LabeledStatement);
43535                case SyntaxKind.ThrowStatement:
43536                    return checkThrowStatement(node as ThrowStatement);
43537                case SyntaxKind.TryStatement:
43538                    return checkTryStatement(node as TryStatement);
43539                case SyntaxKind.VariableDeclaration:
43540                    return checkVariableDeclaration(node as VariableDeclaration);
43541                case SyntaxKind.BindingElement:
43542                    return checkBindingElement(node as BindingElement);
43543                case SyntaxKind.ClassDeclaration:
43544                    return checkClassDeclaration(node as ClassDeclaration);
43545                case SyntaxKind.StructDeclaration:
43546                    return checkStructDeclaration(node as StructDeclaration);
43547                case SyntaxKind.AnnotationDeclaration:
43548                    return checkAnnotationDeclaration(node as AnnotationDeclaration);
43549                case SyntaxKind.InterfaceDeclaration:
43550                    return checkInterfaceDeclaration(node as InterfaceDeclaration);
43551                case SyntaxKind.TypeAliasDeclaration:
43552                    return checkTypeAliasDeclaration(node as TypeAliasDeclaration);
43553                case SyntaxKind.EnumDeclaration:
43554                    return checkEnumDeclaration(node as EnumDeclaration);
43555                case SyntaxKind.ModuleDeclaration:
43556                    return checkModuleDeclaration(node as ModuleDeclaration);
43557                case SyntaxKind.ImportDeclaration:
43558                    return checkImportDeclaration(node as ImportDeclaration);
43559                case SyntaxKind.ImportEqualsDeclaration:
43560                    return checkImportEqualsDeclaration(node as ImportEqualsDeclaration);
43561                case SyntaxKind.ExportDeclaration:
43562                    return checkExportDeclaration(node as ExportDeclaration);
43563                case SyntaxKind.ExportAssignment:
43564                    return checkExportAssignment(node as ExportAssignment);
43565                case SyntaxKind.EmptyStatement:
43566                case SyntaxKind.DebuggerStatement:
43567                    checkGrammarStatementInAmbientContext(node);
43568                    return;
43569                case SyntaxKind.MissingDeclaration:
43570                    return checkMissingDeclaration(node);
43571            }
43572        }
43573
43574        function checkJSDocCommentWorker(node: string | readonly JSDocComment[] | undefined) {
43575            if (isArray(node)) {
43576                forEach(node, tag => {
43577                    if (isJSDocLinkLike(tag)) {
43578                        checkSourceElement(tag);
43579                    }
43580                });
43581            }
43582        }
43583
43584        function checkJSDocTypeIsInJsFile(node: Node): void {
43585            if (!isInJSFile(node)) {
43586                grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
43587            }
43588        }
43589
43590        function checkJSDocVariadicType(node: JSDocVariadicType): void {
43591            checkJSDocTypeIsInJsFile(node);
43592            checkSourceElement(node.type);
43593
43594            // Only legal location is in the *last* parameter tag or last parameter of a JSDoc function.
43595            const { parent } = node;
43596            if (isParameter(parent) && isJSDocFunctionType(parent.parent)) {
43597                if (last(parent.parent.parameters) !== parent) {
43598                    error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
43599                }
43600                return;
43601            }
43602
43603            if (!isJSDocTypeExpression(parent)) {
43604                error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature);
43605            }
43606
43607            const paramTag = node.parent.parent;
43608            if (!isJSDocParameterTag(paramTag)) {
43609                error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature);
43610                return;
43611            }
43612
43613            const param = getParameterSymbolFromJSDoc(paramTag);
43614            if (!param) {
43615                // We will error in `checkJSDocParameterTag`.
43616                return;
43617            }
43618
43619            const host = getHostSignatureFromJSDoc(paramTag);
43620            if (!host || last(host.parameters).symbol !== param) {
43621                error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
43622            }
43623        }
43624
43625        function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type {
43626            const type = getTypeFromTypeNode(node.type);
43627            const { parent } = node;
43628            const paramTag = node.parent.parent;
43629            if (isJSDocTypeExpression(node.parent) && isJSDocParameterTag(paramTag)) {
43630                // Else we will add a diagnostic, see `checkJSDocVariadicType`.
43631                const host = getHostSignatureFromJSDoc(paramTag);
43632                const isCallbackTag = isJSDocCallbackTag(paramTag.parent.parent);
43633                if (host || isCallbackTag) {
43634                    /*
43635                    Only return an array type if the corresponding parameter is marked as a rest parameter, or if there are no parameters.
43636                    So in the following situation we will not create an array type:
43637                        /** @param {...number} a * /
43638                        function f(a) {}
43639                    Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type.
43640                    */
43641                    const lastParamDeclaration = isCallbackTag
43642                        ? lastOrUndefined((paramTag.parent.parent as unknown as JSDocCallbackTag).typeExpression.parameters)
43643                        : lastOrUndefined(host!.parameters);
43644                    const symbol = getParameterSymbolFromJSDoc(paramTag);
43645                    if (!lastParamDeclaration ||
43646                        symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration)) {
43647                        return createArrayType(type);
43648                    }
43649                }
43650            }
43651            if (isParameter(parent) && isJSDocFunctionType(parent.parent)) {
43652                return createArrayType(type);
43653            }
43654            return addOptionality(type);
43655        }
43656
43657        // Function and class expression bodies are checked after all statements in the enclosing body. This is
43658        // to ensure constructs like the following are permitted:
43659        //     const foo = function () {
43660        //        const s = foo();
43661        //        return "hello";
43662        //     }
43663        // Here, performing a full type check of the body of the function expression whilst in the process of
43664        // determining the type of foo would cause foo to be given type any because of the recursive reference.
43665        // Delaying the type check of the body ensures foo has been assigned a type.
43666        function checkNodeDeferred(node: Node) {
43667            const enclosingFile = getSourceFileOfNode(node);
43668            const links = getNodeLinks(enclosingFile);
43669            if (!(links.flags & NodeCheckFlags.TypeChecked)) {
43670                links.deferredNodes ||= new Set();
43671                links.deferredNodes.add(node);
43672            }
43673        }
43674
43675        function checkDeferredNodes(context: SourceFile) {
43676            const links = getNodeLinks(context);
43677            if (links.deferredNodes) {
43678                links.deferredNodes.forEach(checkDeferredNode);
43679            }
43680        }
43681
43682        function checkDeferredNode(node: Node) {
43683            tracing?.push(tracing.Phase.Check, "checkDeferredNode", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath });
43684            const saveCurrentNode = currentNode;
43685            currentNode = node;
43686            instantiationCount = 0;
43687            switch (node.kind) {
43688                case SyntaxKind.CallExpression:
43689                case SyntaxKind.NewExpression:
43690                case SyntaxKind.TaggedTemplateExpression:
43691                case SyntaxKind.Decorator:
43692                case SyntaxKind.JsxOpeningElement:
43693                    // These node kinds are deferred checked when overload resolution fails
43694                    // To save on work, we ensure the arguments are checked just once, in
43695                    // a deferred way
43696                    resolveUntypedCall(node as CallLikeExpression);
43697                    break;
43698                case SyntaxKind.FunctionExpression:
43699                case SyntaxKind.ArrowFunction:
43700                case SyntaxKind.MethodDeclaration:
43701                case SyntaxKind.MethodSignature:
43702                    checkFunctionExpressionOrObjectLiteralMethodDeferred(node as FunctionExpression);
43703                    break;
43704                case SyntaxKind.GetAccessor:
43705                case SyntaxKind.SetAccessor:
43706                    checkAccessorDeclaration(node as AccessorDeclaration);
43707                    break;
43708                case SyntaxKind.ClassExpression:
43709                    checkClassExpressionDeferred(node as ClassExpression);
43710                    break;
43711                case SyntaxKind.TypeParameter:
43712                    checkTypeParameterDeferred(node as TypeParameterDeclaration);
43713                    break;
43714                case SyntaxKind.JsxSelfClosingElement:
43715                    checkJsxSelfClosingElementDeferred(node as JsxSelfClosingElement);
43716                    break;
43717                case SyntaxKind.JsxElement:
43718                    checkJsxElementDeferred(node as JsxElement);
43719                    break;
43720            }
43721            currentNode = saveCurrentNode;
43722            tracing?.pop();
43723        }
43724
43725        function checkSourceFile(node: SourceFile) {
43726            tracing?.push(tracing.Phase.Check, "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true);
43727            const recordInfo = MemoryDotting.recordStage(MemoryDotting.CHECK_SOURCE_FILE);
43728            performance.mark("beforeCheck");
43729            if (host.getFileCheckedModuleInfo) {
43730                jsDocFileCheckInfo = host.getFileCheckedModuleInfo(node.fileName);
43731                jsDocFileCheckInfo.currentFileName = node.fileName;
43732            }
43733            checkSourceFileWorker(node);
43734            performance.mark("afterCheck");
43735            MemoryDotting.stopRecordStage(recordInfo);
43736            performance.measure("Check", "beforeCheck", "afterCheck");
43737            tracing?.pop();
43738        }
43739
43740        function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean {
43741            if (isAmbient) {
43742                return false;
43743            }
43744            switch (kind) {
43745                case UnusedKind.Local:
43746                    return !!compilerOptions.noUnusedLocals;
43747                case UnusedKind.Parameter:
43748                    return !!compilerOptions.noUnusedParameters;
43749                default:
43750                    return Debug.assertNever(kind);
43751            }
43752        }
43753
43754        function getPotentiallyUnusedIdentifiers(sourceFile: SourceFile): readonly PotentiallyUnusedIdentifier[] {
43755            return allPotentiallyUnusedIdentifiers.get(sourceFile.path) || emptyArray;
43756        }
43757
43758        // Fully type check a source file and collect the relevant diagnostics.
43759        function checkSourceFileWorker(node: SourceFile) {
43760            const links = getNodeLinks(node);
43761            if (!(links.flags & NodeCheckFlags.TypeChecked)) {
43762                if (skipTypeChecking(node, compilerOptions, host)) {
43763                    return;
43764                }
43765
43766                // clear constEnumRelate
43767                constEnumRelate.set(node.resolvedPath, new Map());
43768
43769                // Grammar checking
43770                checkGrammarSourceFile(node);
43771
43772                clear(potentialThisCollisions);
43773                clear(potentialNewTargetCollisions);
43774                clear(potentialWeakMapSetCollisions);
43775                clear(potentialReflectCollisions);
43776                clear(potentialUnusedRenamedBindingElementsInTypes);
43777
43778                forEach(node.statements, node => {
43779                    if (!node.skipCheck) {
43780                        checkSourceElement(node);
43781                    }
43782                });
43783                checkSourceElement(node.endOfFileToken);
43784
43785                checkDeferredNodes(node);
43786
43787                if (isExternalOrCommonJsModule(node)) {
43788                    registerForUnusedIdentifiersCheck(node);
43789                }
43790
43791                addLazyDiagnostic(() => {
43792                    // This relies on the results of other lazy diagnostics, so must be computed after them
43793                    if (!node.isDeclarationFile && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters)) {
43794                        checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (containingNode, kind, diag) => {
43795                            if (!containsParseError(containingNode) && unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) {
43796                                diagnostics.add(diag);
43797                            }
43798                        });
43799                    }
43800                    if (!node.isDeclarationFile) {
43801                        checkPotentialUncheckedRenamedBindingElementsInTypes();
43802                    }
43803                });
43804
43805                if (compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error &&
43806                    !node.isDeclarationFile &&
43807                    isExternalModule(node)
43808                ) {
43809                    checkImportsForTypeOnlyConversion(node);
43810                }
43811
43812                if (isExternalOrCommonJsModule(node)) {
43813                    checkExternalModuleExports(node);
43814                }
43815
43816                if (potentialThisCollisions.length) {
43817                    forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
43818                    clear(potentialThisCollisions);
43819                }
43820
43821                if (potentialNewTargetCollisions.length) {
43822                    forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope);
43823                    clear(potentialNewTargetCollisions);
43824                }
43825
43826                if (potentialWeakMapSetCollisions.length) {
43827                    forEach(potentialWeakMapSetCollisions, checkWeakMapSetCollision);
43828                    clear(potentialWeakMapSetCollisions);
43829                }
43830
43831                if (potentialReflectCollisions.length) {
43832                    forEach(potentialReflectCollisions, checkReflectCollision);
43833                    clear(potentialReflectCollisions);
43834                }
43835
43836                links.flags |= NodeCheckFlags.TypeChecked;
43837            }
43838        }
43839
43840        function getDiagnostics(sourceFile: SourceFile, ct: CancellationToken): Diagnostic[] {
43841            try {
43842                // Record the cancellation token so it can be checked later on during checkSourceElement.
43843                // Do this in a finally block so we can ensure that it gets reset back to nothing after
43844                // this call is done.
43845                cancellationToken = ct;
43846                return getDiagnosticsWorker(sourceFile);
43847            }
43848            finally {
43849                cancellationToken = undefined;
43850            }
43851        }
43852
43853        function ensurePendingDiagnosticWorkComplete() {
43854            // Invoke any existing lazy diagnostics to add them, clear the backlog of diagnostics
43855            for (const cb of deferredDiagnosticsCallbacks) {
43856                cb();
43857            }
43858            deferredDiagnosticsCallbacks = [];
43859        }
43860
43861        function checkSourceFileWithEagerDiagnostics(sourceFile: SourceFile) {
43862            ensurePendingDiagnosticWorkComplete();
43863            // then setup diagnostics for immediate invocation (as we are about to collect them, and
43864            // this avoids the overhead of longer-lived callbacks we don't need to allocate)
43865            // This also serves to make the shift to possibly lazy diagnostics transparent to serial command-line scenarios
43866            // (as in those cases, all the diagnostics will still be computed as the appropriate place in the tree,
43867            // thus much more likely retaining the same union ordering as before we had lazy diagnostics)
43868            const oldAddLazyDiagnostics = addLazyDiagnostic;
43869            addLazyDiagnostic = cb => cb();
43870            checkSourceFile(sourceFile);
43871            addLazyDiagnostic = oldAddLazyDiagnostics;
43872        }
43873
43874        function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] {
43875            if (sourceFile) {
43876                ensurePendingDiagnosticWorkComplete();
43877                // Some global diagnostics are deferred until they are needed and
43878                // may not be reported in the first call to getGlobalDiagnostics.
43879                // We should catch these changes and report them.
43880                const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
43881                const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length;
43882
43883                checkSourceFileWithEagerDiagnostics(sourceFile);
43884
43885                const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName);
43886                const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics();
43887                if (currentGlobalDiagnostics !== previousGlobalDiagnostics) {
43888                    // If the arrays are not the same reference, new diagnostics were added.
43889                    const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics);
43890                    return concatenate(deferredGlobalDiagnostics, semanticDiagnostics);
43891                }
43892                else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) {
43893                    // If the arrays are the same reference, but the length has changed, a single
43894                    // new diagnostic was added as DiagnosticCollection attempts to reuse the
43895                    // same array.
43896                    return concatenate(currentGlobalDiagnostics, semanticDiagnostics);
43897                }
43898
43899                return semanticDiagnostics;
43900            }
43901
43902            // Global diagnostics are always added when a file is not provided to
43903            // getDiagnostics
43904            forEach(host.getSourceFiles(), checkSourceFileWithEagerDiagnostics);
43905            return diagnostics.getDiagnostics();
43906        }
43907
43908        function getGlobalDiagnostics(): Diagnostic[] {
43909            ensurePendingDiagnosticWorkComplete();
43910            return diagnostics.getGlobalDiagnostics();
43911        }
43912
43913        // Language service support
43914
43915        function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] {
43916            if (location.flags & NodeFlags.InWithStatement) {
43917                // We cannot answer semantic questions within a with block, do not proceed any further
43918                return [];
43919            }
43920
43921            const symbols = createSymbolTable();
43922            let isStaticSymbol = false;
43923
43924            populateSymbols();
43925
43926            symbols.delete(InternalSymbolName.This); // Not a symbol, a keyword
43927            return symbolsToArray(symbols);
43928
43929            function populateSymbols() {
43930                while (location) {
43931                    if (location.locals && !isGlobalSourceFile(location)) {
43932                        copySymbols(location.locals, meaning);
43933                    }
43934
43935                    switch (location.kind) {
43936                        case SyntaxKind.SourceFile:
43937                            if (!isExternalModule(location as SourceFile)) break;
43938                            // falls through
43939                        case SyntaxKind.ModuleDeclaration:
43940                            copyLocallyVisibleExportSymbols(getSymbolOfNode(location as ModuleDeclaration | SourceFile).exports!, meaning & SymbolFlags.ModuleMember);
43941                            break;
43942                        case SyntaxKind.EnumDeclaration:
43943                            copySymbols(getSymbolOfNode(location as EnumDeclaration).exports!, meaning & SymbolFlags.EnumMember);
43944                            break;
43945                        case SyntaxKind.ClassExpression:
43946                            const className = (location as ClassExpression).name;
43947                            if (className) {
43948                                copySymbol(location.symbol, meaning);
43949                            }
43950
43951                        // this fall-through is necessary because we would like to handle
43952                        // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration.
43953                        // falls through
43954                        case SyntaxKind.ClassDeclaration:
43955                        case SyntaxKind.InterfaceDeclaration:
43956                            // If we didn't come from static member of class or interface,
43957                            // add the type parameters into the symbol table
43958                            // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol.
43959                            // Note: that the memberFlags come from previous iteration.
43960                            if (!isStaticSymbol) {
43961                                copySymbols(getMembersOfSymbol(getSymbolOfNode(location as ClassDeclaration | InterfaceDeclaration)), meaning & SymbolFlags.Type);
43962                            }
43963                            break;
43964                        case SyntaxKind.FunctionExpression:
43965                            const funcName = (location as FunctionExpression).name;
43966                            if (funcName) {
43967                                copySymbol(location.symbol, meaning);
43968                            }
43969                            break;
43970                    }
43971
43972                    if (introducesArgumentsExoticObject(location)) {
43973                        copySymbol(argumentsSymbol, meaning);
43974                    }
43975
43976                    isStaticSymbol = isStatic(location);
43977                    location = location.parent;
43978                }
43979
43980                copySymbols(globals, meaning);
43981            }
43982
43983            /**
43984             * Copy the given symbol into symbol tables if the symbol has the given meaning
43985             * and it doesn't already existed in the symbol table
43986             * @param key a key for storing in symbol table; if undefined, use symbol.name
43987             * @param symbol the symbol to be added into symbol table
43988             * @param meaning meaning of symbol to filter by before adding to symbol table
43989             */
43990            function copySymbol(symbol: Symbol, meaning: SymbolFlags): void {
43991                if (getCombinedLocalAndExportSymbolFlags(symbol) & meaning) {
43992                    const id = symbol.escapedName;
43993                    // We will copy all symbol regardless of its reserved name because
43994                    // symbolsToArray will check whether the key is a reserved name and
43995                    // it will not copy symbol with reserved name to the array
43996                    if (!symbols.has(id)) {
43997                        symbols.set(id, symbol);
43998                    }
43999                }
44000            }
44001
44002            function copySymbols(source: SymbolTable, meaning: SymbolFlags): void {
44003                if (meaning) {
44004                    source.forEach(symbol => {
44005                        copySymbol(symbol, meaning);
44006                    });
44007                }
44008            }
44009
44010            function copyLocallyVisibleExportSymbols(source: SymbolTable, meaning: SymbolFlags): void {
44011                if (meaning) {
44012                    source.forEach(symbol => {
44013                        // Similar condition as in `resolveNameHelper`
44014                        if (!getDeclarationOfKind(symbol, SyntaxKind.ExportSpecifier) && !getDeclarationOfKind(symbol, SyntaxKind.NamespaceExport)) {
44015                            copySymbol(symbol, meaning);
44016                        }
44017                    });
44018                }
44019            }
44020        }
44021
44022        function isTypeDeclarationName(name: Node): boolean {
44023            return name.kind === SyntaxKind.Identifier &&
44024                isTypeDeclaration(name.parent) &&
44025                getNameOfDeclaration(name.parent) === name;
44026        }
44027
44028        // True if the given identifier is part of a type reference
44029        function isTypeReferenceIdentifier(node: EntityName): boolean {
44030            while (node.parent.kind === SyntaxKind.QualifiedName) {
44031                node = node.parent as QualifiedName;
44032            }
44033
44034            return node.parent.kind === SyntaxKind.TypeReference;
44035        }
44036
44037        function isHeritageClauseElementIdentifier(node: Node): boolean {
44038            while (node.parent.kind === SyntaxKind.PropertyAccessExpression) {
44039                node = node.parent;
44040            }
44041
44042            return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments;
44043        }
44044
44045        function forEachEnclosingClass<T>(node: Node, callback: (node: Node) => T | undefined): T | undefined {
44046            let result: T | undefined;
44047
44048            while (true) {
44049                node = getContainingClass(node)!;
44050                if (!node) break;
44051                if (result = callback(node)) break;
44052            }
44053
44054            return result;
44055        }
44056
44057        function isNodeUsedDuringClassInitialization(node: Node) {
44058            return !!findAncestor(node, element => {
44059                if (isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) {
44060                    return true;
44061                }
44062                else if (isClassLike(element) || isFunctionLikeDeclaration(element)) {
44063                    return "quit";
44064                }
44065
44066                return false;
44067            });
44068        }
44069
44070        function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) {
44071            return !!forEachEnclosingClass(node, n => n === classDeclaration);
44072        }
44073
44074        function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment | undefined {
44075            while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) {
44076                nodeOnRightSide = nodeOnRightSide.parent as QualifiedName;
44077            }
44078
44079            if (nodeOnRightSide.parent.kind === SyntaxKind.ImportEqualsDeclaration) {
44080                return (nodeOnRightSide.parent as ImportEqualsDeclaration).moduleReference === nodeOnRightSide ? nodeOnRightSide.parent as ImportEqualsDeclaration : undefined;
44081            }
44082
44083            if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) {
44084                return (nodeOnRightSide.parent as ExportAssignment).expression === nodeOnRightSide as Node ? nodeOnRightSide.parent as ExportAssignment : undefined;
44085            }
44086
44087            return undefined;
44088        }
44089
44090        function isInRightSideOfImportOrExportAssignment(node: EntityName) {
44091            return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
44092        }
44093
44094        function getSpecialPropertyAssignmentSymbolFromEntityName(entityName: EntityName | PropertyAccessExpression) {
44095            const specialPropertyAssignmentKind = getAssignmentDeclarationKind(entityName.parent.parent as BinaryExpression);
44096            switch (specialPropertyAssignmentKind) {
44097                case AssignmentDeclarationKind.ExportsProperty:
44098                case AssignmentDeclarationKind.PrototypeProperty:
44099                    return getSymbolOfNode(entityName.parent);
44100                case AssignmentDeclarationKind.ThisProperty:
44101                case AssignmentDeclarationKind.ModuleExports:
44102                case AssignmentDeclarationKind.Property:
44103                    return getSymbolOfNode(entityName.parent.parent);
44104            }
44105        }
44106
44107        function isImportTypeQualifierPart(node: EntityName): ImportTypeNode | undefined {
44108            let parent = node.parent;
44109            while (isQualifiedName(parent)) {
44110                node = parent;
44111                parent = parent.parent;
44112            }
44113            if (parent && parent.kind === SyntaxKind.ImportType && (parent as ImportTypeNode).qualifier === node) {
44114                return parent as ImportTypeNode;
44115            }
44116            return undefined;
44117        }
44118
44119        function getSymbolOfNameOrPropertyAccessExpression(name: EntityName | PrivateIdentifier | PropertyAccessExpression | JSDocMemberName, ignoreErrors?: boolean): Symbol | undefined {
44120            if (isDeclarationName(name)) {
44121                return getSymbolOfNode(name.parent);
44122            }
44123
44124            if (isInJSFile(name) &&
44125                name.parent.kind === SyntaxKind.PropertyAccessExpression &&
44126                name.parent === (name.parent.parent as BinaryExpression).left) {
44127                // Check if this is a special property assignment
44128                if (!isPrivateIdentifier(name) && !isJSDocMemberName(name)) {
44129                    const specialPropertyAssignmentSymbol = getSpecialPropertyAssignmentSymbolFromEntityName(name);
44130                    if (specialPropertyAssignmentSymbol) {
44131                        return specialPropertyAssignmentSymbol;
44132                    }
44133                }
44134            }
44135
44136            if (name.parent.kind === SyntaxKind.ExportAssignment && isEntityNameExpression(name)) {
44137                // Even an entity name expression that doesn't resolve as an entityname may still typecheck as a property access expression
44138                const success = resolveEntityName(name,
44139                    /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*ignoreErrors*/ true);
44140                if (success && success !== unknownSymbol) {
44141                    return success;
44142                }
44143            }
44144            else if (isEntityName(name) && isInRightSideOfImportOrExportAssignment(name)) {
44145                // Since we already checked for ExportAssignment, this really could only be an Import
44146                const importEqualsDeclaration = getAncestor(name, SyntaxKind.ImportEqualsDeclaration);
44147                Debug.assert(importEqualsDeclaration !== undefined);
44148                return getSymbolOfPartOfRightHandSideOfImportEquals(name, /*dontResolveAlias*/ true);
44149            }
44150
44151            if (isEntityName(name)) {
44152                const possibleImportNode = isImportTypeQualifierPart(name);
44153                if (possibleImportNode) {
44154                    getTypeFromTypeNode(possibleImportNode);
44155                    const sym = getNodeLinks(name).resolvedSymbol;
44156                    return sym === unknownSymbol ? undefined : sym;
44157                }
44158            }
44159
44160            while (isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName(name)) {
44161                name = name.parent as QualifiedName | PropertyAccessEntityNameExpression | JSDocMemberName;
44162            }
44163
44164            if (isHeritageClauseElementIdentifier(name)) {
44165                let meaning = SymbolFlags.None;
44166                // In an interface or class, we're definitely interested in a type.
44167                if (name.parent.kind === SyntaxKind.ExpressionWithTypeArguments) {
44168                    meaning = SymbolFlags.Type;
44169
44170                    // In a class 'extends' clause we are also looking for a value.
44171                    if (isExpressionWithTypeArgumentsInClassExtendsClause(name.parent)) {
44172                        meaning |= SymbolFlags.Value;
44173                    }
44174                }
44175                else {
44176                    meaning = SymbolFlags.Namespace;
44177                }
44178
44179                meaning |= SymbolFlags.Alias;
44180                const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning) : undefined;
44181                if (entityNameSymbol) {
44182                    return entityNameSymbol;
44183                }
44184            }
44185
44186            if (name.parent.kind === SyntaxKind.JSDocParameterTag) {
44187                return getParameterSymbolFromJSDoc(name.parent as JSDocParameterTag);
44188            }
44189
44190            if (name.parent.kind === SyntaxKind.TypeParameter && name.parent.parent.kind === SyntaxKind.JSDocTemplateTag) {
44191                Debug.assert(!isInJSFile(name)); // Otherwise `isDeclarationName` would have been true.
44192                const typeParameter = getTypeParameterFromJsDoc(name.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag });
44193                return typeParameter && typeParameter.symbol;
44194            }
44195
44196            if (isExpressionNode(name)) {
44197                if (nodeIsMissing(name)) {
44198                    // Missing entity name.
44199                    return undefined;
44200                }
44201
44202                const isJSDoc = findAncestor(name, or(isJSDocLinkLike, isJSDocNameReference, isJSDocMemberName));
44203                const meaning = isJSDoc ? SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value : SymbolFlags.Value;
44204                if (name.kind === SyntaxKind.Identifier) {
44205                    if (isJSXTagName(name) && isJsxIntrinsicIdentifier(name)) {
44206                        const symbol = getIntrinsicTagSymbol(name.parent as JsxOpeningLikeElement);
44207                        return symbol === unknownSymbol ? undefined : symbol;
44208                    }
44209                    const result = resolveEntityName(name, meaning, /*ignoreErrors*/ ignoreErrors, /* dontResolveAlias */ true, getHostSignatureFromJSDoc(name));
44210                    if (!result && isJSDoc) {
44211                        const container = findAncestor(name, or(isClassLike, isInterfaceDeclaration));
44212                        if (container) {
44213                            return resolveJSDocMemberName(name, /*ignoreErrors*/ false, getSymbolOfNode(container));
44214                        }
44215                    }
44216                    if (result && isJSDoc) {
44217                        const container = getJSDocHost(name);
44218                        if (container && isEnumMember(container) && container === result.valueDeclaration) {
44219                            return resolveEntityName(name, meaning, /*ignoreErrors*/ true, /* dontResolveAlias */ true, getSourceFileOfNode(container)) || result;
44220                        }
44221                    }
44222                    return result;
44223                }
44224                else if (isPrivateIdentifier(name)) {
44225                    return getSymbolForPrivateIdentifierExpression(name);
44226                }
44227                else if (name.kind === SyntaxKind.PropertyAccessExpression || name.kind === SyntaxKind.QualifiedName) {
44228                    const links = getNodeLinks(name);
44229                    if (links.resolvedSymbol) {
44230                        return links.resolvedSymbol;
44231                    }
44232
44233                    if (name.kind === SyntaxKind.PropertyAccessExpression) {
44234                        checkPropertyAccessExpression(name, CheckMode.Normal);
44235                        if (!links.resolvedSymbol) {
44236                            const expressionType = checkExpressionCached(name.expression);
44237                            const infos = getApplicableIndexInfos(expressionType, getLiteralTypeFromPropertyName(name.name));
44238                            if (infos.length && (expressionType as ObjectType).members) {
44239                                const resolved = resolveStructuredTypeMembers(expressionType as ObjectType);
44240                                const symbol = resolved.members.get(InternalSymbolName.Index);
44241                                if (infos === getIndexInfosOfType(expressionType)) {
44242                                    links.resolvedSymbol = symbol;
44243                                }
44244                                else if (symbol) {
44245                                    const symbolLinks = getSymbolLinks(symbol);
44246                                    const declarationList = mapDefined(infos, i => i.declaration);
44247                                    const nodeListId = map(declarationList, getNodeId).join(",");
44248                                    if (!symbolLinks.filteredIndexSymbolCache) {
44249                                        symbolLinks.filteredIndexSymbolCache = new Map();
44250                                    }
44251                                    if (symbolLinks.filteredIndexSymbolCache.has(nodeListId)) {
44252                                        links.resolvedSymbol = symbolLinks.filteredIndexSymbolCache.get(nodeListId)!;
44253                                    }
44254                                    else {
44255                                        const copy = createSymbol(SymbolFlags.Signature, InternalSymbolName.Index);
44256                                        copy.declarations = mapDefined(infos, i => i.declaration);
44257                                        copy.parent = expressionType.aliasSymbol ? expressionType.aliasSymbol : expressionType.symbol ? expressionType.symbol : getSymbolAtLocation(copy.declarations[0].parent);
44258                                        symbolLinks.filteredIndexSymbolCache.set(nodeListId, copy);
44259                                        links.resolvedSymbol = symbolLinks.filteredIndexSymbolCache.get(nodeListId)!;
44260                                    }
44261                                }
44262                            }
44263                        }
44264                    }
44265                    else {
44266                        checkQualifiedName(name, CheckMode.Normal);
44267                    }
44268                    if (!links.resolvedSymbol && isJSDoc && isQualifiedName(name)) {
44269                        return resolveJSDocMemberName(name);
44270                    }
44271                    return links.resolvedSymbol;
44272                }
44273                else if (isJSDocMemberName(name)) {
44274                    return resolveJSDocMemberName(name);
44275                }
44276            }
44277            else if (isTypeReferenceIdentifier(name as EntityName)) {
44278                const meaning = name.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
44279                const symbol = resolveEntityName(name as EntityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true);
44280                return symbol && symbol !== unknownSymbol ? symbol : getUnresolvedSymbolForEntityName(name as EntityName);
44281            }
44282            if (name.parent.kind === SyntaxKind.TypePredicate) {
44283                return resolveEntityName(name as Identifier, /*meaning*/ SymbolFlags.FunctionScopedVariable);
44284            }
44285
44286            return undefined;
44287        }
44288
44289        /**
44290         * Recursively resolve entity names and jsdoc instance references:
44291         * 1. K#m as K.prototype.m for a class (or other value) K
44292         * 2. K.m as K.prototype.m
44293         * 3. I.m as I.m for a type I, or any other I.m that fails to resolve in (1) or (2)
44294         *
44295         * For unqualified names, a container K may be provided as a second argument.
44296         */
44297        function resolveJSDocMemberName(name: EntityName | JSDocMemberName, ignoreErrors?: boolean, container?: Symbol): Symbol | undefined {
44298            if (isEntityName(name)) {
44299                // resolve static values first
44300                const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value;
44301                let symbol = resolveEntityName(name, meaning, ignoreErrors, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name));
44302                if (!symbol && isIdentifier(name) && container) {
44303                    symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(container), name.escapedText, meaning));
44304                }
44305                if (symbol) {
44306                    return symbol;
44307                }
44308            }
44309            const left = isIdentifier(name) ? container : resolveJSDocMemberName(name.left, ignoreErrors, container);
44310            const right = isIdentifier(name) ? name.escapedText : name.right.escapedText;
44311            if (left) {
44312                const proto = left.flags & SymbolFlags.Value && getPropertyOfType(getTypeOfSymbol(left), "prototype" as __String);
44313                const t = proto ? getTypeOfSymbol(proto) : getDeclaredTypeOfSymbol(left);
44314                return getPropertyOfType(t, right);
44315            }
44316        }
44317
44318        function getSymbolAtLocation(node: Node, ignoreErrors?: boolean): Symbol | undefined {
44319            if (node.kind === SyntaxKind.SourceFile) {
44320                return isExternalModule(node as SourceFile) ? getMergedSymbol(node.symbol) : undefined;
44321            }
44322            const { parent } = node;
44323            const grandParent = parent.parent;
44324
44325            if (node.flags & NodeFlags.InWithStatement) {
44326                // We cannot answer semantic questions within a with block, do not proceed any further
44327                return undefined;
44328            }
44329
44330            if (isDeclarationNameOrImportPropertyName(node)) {
44331                // This is a declaration, call getSymbolOfNode
44332                const parentSymbol = getSymbolOfNode(parent)!;
44333                return isImportOrExportSpecifier(node.parent) && node.parent.propertyName === node
44334                    ? getImmediateAliasedSymbol(parentSymbol)
44335                    : parentSymbol;
44336            }
44337            else if (isLiteralComputedPropertyDeclarationName(node)) {
44338                return getSymbolOfNode(parent.parent);
44339            }
44340
44341            if (node.kind === SyntaxKind.Identifier) {
44342                if (isInRightSideOfImportOrExportAssignment(node as Identifier)) {
44343                    return getSymbolOfNameOrPropertyAccessExpression(node as Identifier);
44344                }
44345                else if (parent.kind === SyntaxKind.BindingElement &&
44346                    grandParent.kind === SyntaxKind.ObjectBindingPattern &&
44347                    node === (parent as BindingElement).propertyName) {
44348                    const typeOfPattern = getTypeOfNode(grandParent);
44349                    const propertyDeclaration = getPropertyOfType(typeOfPattern, (node as Identifier).escapedText);
44350
44351                    if (propertyDeclaration) {
44352                        return propertyDeclaration;
44353                    }
44354                }
44355                else if (isMetaProperty(parent) && parent.name === node) {
44356                    if (parent.keywordToken === SyntaxKind.NewKeyword && idText(node as Identifier) === "target") {
44357                        // `target` in `new.target`
44358                        return checkNewTargetMetaProperty(parent).symbol;
44359                    }
44360                    // The `meta` in `import.meta` could be given `getTypeOfNode(parent).symbol` (the `ImportMeta` interface symbol), but
44361                    // we have a fake expression type made for other reasons already, whose transient `meta`
44362                    // member should more exactly be the kind of (declarationless) symbol we want.
44363                    // (See #44364 and #45031 for relevant implementation PRs)
44364                    if (parent.keywordToken === SyntaxKind.ImportKeyword && idText(node as Identifier) === "meta") {
44365                        return getGlobalImportMetaExpressionType().members!.get("meta" as __String);
44366                    }
44367                    // no other meta properties are valid syntax, thus no others should have symbols
44368                    return undefined;
44369                }
44370            }
44371
44372            switch (node.kind) {
44373                case SyntaxKind.Identifier:
44374                case SyntaxKind.PrivateIdentifier:
44375                case SyntaxKind.PropertyAccessExpression:
44376                case SyntaxKind.QualifiedName:
44377                    if (!isThisInTypeQuery(node)) {
44378                        return getSymbolOfNameOrPropertyAccessExpression(node as EntityName | PrivateIdentifier | PropertyAccessExpression);
44379                    }
44380                    // falls through
44381
44382                case SyntaxKind.ThisKeyword:
44383                    const container = getThisContainer(node, /*includeArrowFunctions*/ false);
44384                    if (isFunctionLike(container)) {
44385                        const sig = getSignatureFromDeclaration(container);
44386                        if (sig.thisParameter) {
44387                            return sig.thisParameter;
44388                        }
44389                    }
44390                    if (isInExpressionContext(node)) {
44391                        return checkExpression(node as Expression).symbol;
44392                    }
44393                    // falls through
44394
44395                case SyntaxKind.ThisType:
44396                    return getTypeFromThisTypeNode(node as ThisExpression | ThisTypeNode).symbol;
44397
44398                case SyntaxKind.SuperKeyword:
44399                    return checkExpression(node as Expression).symbol;
44400
44401                case SyntaxKind.ConstructorKeyword:
44402                    // constructor keyword for an overload, should take us to the definition if it exist
44403                    const constructorDeclaration = node.parent;
44404                    if (constructorDeclaration && constructorDeclaration.kind === SyntaxKind.Constructor) {
44405                        return (constructorDeclaration.parent as ClassDeclaration).symbol;
44406                    }
44407                    return undefined;
44408
44409                case SyntaxKind.StringLiteral:
44410                case SyntaxKind.NoSubstitutionTemplateLiteral:
44411                    // 1). import x = require("./mo/*gotToDefinitionHere*/d")
44412                    // 2). External module name in an import declaration
44413                    // 3). Dynamic import call or require in javascript
44414                    // 4). type A = import("./f/*gotToDefinitionHere*/oo")
44415                    if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) ||
44416                        ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent as ImportDeclaration).moduleSpecifier === node) ||
44417                        ((isInJSFile(node) && isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || isImportCall(node.parent)) ||
44418                        (isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent)
44419                    ) {
44420                        return resolveExternalModuleName(node, node as LiteralExpression, ignoreErrors);
44421                    }
44422                    if (isCallExpression(parent) && isBindableObjectDefinePropertyCall(parent) && parent.arguments[1] === node) {
44423                        return getSymbolOfNode(parent);
44424                    }
44425                    // falls through
44426
44427                case SyntaxKind.NumericLiteral:
44428                    // index access
44429                    const objectType = isElementAccessExpression(parent)
44430                        ? parent.argumentExpression === node ? getTypeOfExpression(parent.expression) : undefined
44431                        : isLiteralTypeNode(parent) && isIndexedAccessTypeNode(grandParent)
44432                            ? getTypeFromTypeNode(grandParent.objectType)
44433                            : undefined;
44434                    return objectType && getPropertyOfType(objectType, escapeLeadingUnderscores((node as StringLiteral | NumericLiteral).text));
44435
44436                case SyntaxKind.DefaultKeyword:
44437                case SyntaxKind.FunctionKeyword:
44438                case SyntaxKind.EqualsGreaterThanToken:
44439                case SyntaxKind.ClassKeyword:
44440                    return getSymbolOfNode(node.parent);
44441                case SyntaxKind.ImportType:
44442                    return isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal, ignoreErrors) : undefined;
44443
44444                case SyntaxKind.ExportKeyword:
44445                    return isExportAssignment(node.parent) ? Debug.checkDefined(node.parent.symbol) : undefined;
44446
44447                case SyntaxKind.ImportKeyword:
44448                case SyntaxKind.NewKeyword:
44449                    return isMetaProperty(node.parent) ? checkMetaPropertyKeyword(node.parent).symbol : undefined;
44450                case SyntaxKind.MetaProperty:
44451                    return checkExpression(node as Expression).symbol;
44452
44453                default:
44454                    return undefined;
44455            }
44456        }
44457
44458        function getIndexInfosAtLocation(node: Node): readonly IndexInfo[] | undefined {
44459            if (isIdentifier(node) && isPropertyAccessExpression(node.parent) && node.parent.name === node) {
44460                const keyType = getLiteralTypeFromPropertyName(node);
44461                const objectType = getTypeOfExpression(node.parent.expression);
44462                const objectTypes = objectType.flags & TypeFlags.Union ? (objectType as UnionType).types : [objectType];
44463                return flatMap(objectTypes, t => filter(getIndexInfosOfType(t), info => isApplicableIndexType(keyType, info.keyType)));
44464            }
44465            return undefined;
44466        }
44467
44468        function getShorthandAssignmentValueSymbol(location: Node | undefined): Symbol | undefined {
44469            if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) {
44470                return resolveEntityName((location as ShorthandPropertyAssignment).name, SymbolFlags.Value | SymbolFlags.Alias);
44471            }
44472            return undefined;
44473        }
44474
44475        /** Returns the target of an export specifier without following aliases */
44476        function getExportSpecifierLocalTargetSymbol(node: ExportSpecifier | Identifier): Symbol | undefined {
44477            if (isExportSpecifier(node)) {
44478                return node.parent.parent.moduleSpecifier ?
44479                    getExternalModuleMember(node.parent.parent, node) :
44480                    resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
44481            }
44482            else {
44483                return resolveEntityName(node, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
44484            }
44485        }
44486
44487        function getTypeOfNode(node: Node): Type {
44488            if (isSourceFile(node) && !isExternalModule(node)) {
44489                return errorType;
44490            }
44491
44492            if (node.flags & NodeFlags.InWithStatement) {
44493                // We cannot answer semantic questions within a with block, do not proceed any further
44494                return errorType;
44495            }
44496
44497            const classDecl = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node);
44498            const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(classDecl.class));
44499            if (isPartOfTypeNode(node)) {
44500                const typeFromTypeNode = getTypeFromTypeNode(node as TypeNode);
44501                return classType ? getTypeWithThisArgument(typeFromTypeNode, classType.thisType) : typeFromTypeNode;
44502            }
44503
44504            if (isExpressionNode(node)) {
44505                return getRegularTypeOfExpression(node as Expression);
44506            }
44507
44508            if (classType && !classDecl.isImplements) {
44509                // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the
44510                // extends clause of a class. We handle that case here.
44511                const baseType = firstOrUndefined(getBaseTypes(classType));
44512                return baseType ? getTypeWithThisArgument(baseType, classType.thisType) : errorType;
44513            }
44514
44515            if (isTypeDeclaration(node)) {
44516                // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration
44517                const symbol = getSymbolOfNode(node);
44518                return getDeclaredTypeOfSymbol(symbol);
44519            }
44520
44521            if (isTypeDeclarationName(node)) {
44522                const symbol = getSymbolAtLocation(node);
44523                return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType;
44524            }
44525
44526            if (isDeclaration(node)) {
44527                // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration
44528                const symbol = getSymbolOfNode(node);
44529                return symbol ? getTypeOfSymbol(symbol) : errorType;
44530            }
44531
44532            if (isDeclarationNameOrImportPropertyName(node)) {
44533                const symbol = getSymbolAtLocation(node);
44534                if (symbol) {
44535                    return getTypeOfSymbol(symbol);
44536                }
44537                return errorType;
44538            }
44539
44540            if (isBindingPattern(node)) {
44541                return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true, CheckMode.Normal) || errorType;
44542            }
44543
44544            if (isInRightSideOfImportOrExportAssignment(node as Identifier)) {
44545                const symbol = getSymbolAtLocation(node);
44546                if (symbol) {
44547                    const declaredType = getDeclaredTypeOfSymbol(symbol);
44548                    return !isErrorType(declaredType) ? declaredType : getTypeOfSymbol(symbol);
44549                }
44550            }
44551
44552            if (isMetaProperty(node.parent) && node.parent.keywordToken === node.kind) {
44553                return checkMetaPropertyKeyword(node.parent);
44554            }
44555
44556            return errorType;
44557        }
44558
44559        function tryGetTypeOfNodeWithoutCheck(node: Node): Type {
44560            if (isSourceFile(node) && !isExternalModule(node)) {
44561                return errorType;
44562            }
44563
44564            if (node.flags & NodeFlags.InWithStatement) {
44565                // We cannot answer semantic questions within a with block, do not proceed any further
44566                return errorType;
44567            }
44568
44569            const classDecl = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node);
44570            const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(classDecl.class));
44571            if (isPartOfTypeNode(node)) {
44572                const typeFromTypeNode = getTypeFromTypeNode(<TypeNode>node);
44573                return classType ? getTypeWithThisArgument(typeFromTypeNode, classType.thisType) : typeFromTypeNode;
44574            }
44575
44576            if (isExpressionNode(node)) {
44577                return getRegularTypeOfExpression(<Expression>node, CheckMode.SkipEtsComponentBody);
44578            }
44579
44580            return getTypeOfNode(node);
44581        }
44582
44583        // Gets the type of object literal or array literal of destructuring assignment.
44584        // { a } from
44585        //     for ( { a } of elems) {
44586        //     }
44587        // [ a ] from
44588        //     [a] = [ some array ...]
44589        function getTypeOfAssignmentPattern(expr: AssignmentPattern): Type | undefined {
44590            Debug.assert(expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression);
44591            // If this is from "for of"
44592            //     for ( { a } of elems) {
44593            //     }
44594            if (expr.parent.kind === SyntaxKind.ForOfStatement) {
44595                const iteratedType = checkRightHandSideOfForOf(expr.parent as ForOfStatement);
44596                return checkDestructuringAssignment(expr, iteratedType || errorType);
44597            }
44598            // If this is from "for" initializer
44599            //     for ({a } = elems[0];.....) { }
44600            if (expr.parent.kind === SyntaxKind.BinaryExpression) {
44601                const iteratedType = getTypeOfExpression((expr.parent as BinaryExpression).right);
44602                return checkDestructuringAssignment(expr, iteratedType || errorType);
44603            }
44604            // If this is from nested object binding pattern
44605            //     for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) {
44606            if (expr.parent.kind === SyntaxKind.PropertyAssignment) {
44607                const node = cast(expr.parent.parent, isObjectLiteralExpression);
44608                const typeOfParentObjectLiteral = getTypeOfAssignmentPattern(node) || errorType;
44609                const propertyIndex = indexOfNode(node.properties, expr.parent);
44610                return checkObjectLiteralDestructuringPropertyAssignment(node, typeOfParentObjectLiteral, propertyIndex);
44611            }
44612            // Array literal assignment - array destructuring pattern
44613            const node = cast(expr.parent, isArrayLiteralExpression);
44614            //    [{ property1: p1, property2 }] = elems;
44615            const typeOfArrayLiteral = getTypeOfAssignmentPattern(node) || errorType;
44616            const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring, typeOfArrayLiteral, undefinedType, expr.parent) || errorType;
44617            return checkArrayLiteralDestructuringElementAssignment(node, typeOfArrayLiteral, node.elements.indexOf(expr), elementType);
44618        }
44619
44620        // Gets the property symbol corresponding to the property in destructuring assignment
44621        // 'property1' from
44622        //     for ( { property1: a } of elems) {
44623        //     }
44624        // 'property1' at location 'a' from:
44625        //     [a] = [ property1, property2 ]
44626        function getPropertySymbolOfDestructuringAssignment(location: Identifier) {
44627            // Get the type of the object or array literal and then look for property of given name in the type
44628            const typeOfObjectLiteral = getTypeOfAssignmentPattern(cast(location.parent.parent, isAssignmentPattern));
44629            return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.escapedText);
44630        }
44631
44632        function getRegularTypeOfExpression(expr: Expression, checkMode?: CheckMode): Type {
44633            if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
44634                expr = expr.parent as Expression;
44635            }
44636            return getRegularTypeOfLiteralType(getTypeOfExpression(expr, checkMode));
44637        }
44638
44639        /**
44640         * Gets either the static or instance type of a class element, based on
44641         * whether the element is declared as "static".
44642         */
44643        function getParentTypeOfClassElement(node: ClassElement) {
44644            const classSymbol = getSymbolOfNode(node.parent)!;
44645            return isStatic(node)
44646                ? getTypeOfSymbol(classSymbol)
44647                : getDeclaredTypeOfSymbol(classSymbol);
44648        }
44649
44650        function getClassElementPropertyKeyType(element: ClassElement) {
44651            const name = element.name!;
44652            switch (name.kind) {
44653                case SyntaxKind.Identifier:
44654                    return getStringLiteralType(idText(name));
44655                case SyntaxKind.NumericLiteral:
44656                case SyntaxKind.StringLiteral:
44657                    return getStringLiteralType(name.text);
44658                case SyntaxKind.ComputedPropertyName:
44659                    const nameType = checkComputedPropertyName(name);
44660                    return isTypeAssignableToKind(nameType, TypeFlags.ESSymbolLike) ? nameType : stringType;
44661                default:
44662                    return Debug.fail("Unsupported property name.");
44663            }
44664        }
44665
44666        // Return the list of properties of the given type, augmented with properties from Function
44667        // if the type has call or construct signatures
44668        function getAugmentedPropertiesOfType(type: Type): Symbol[] {
44669            type = getApparentType(type);
44670            const propsByName = createSymbolTable(getPropertiesOfType(type));
44671            const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType :
44672                getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType :
44673                undefined;
44674            if (functionType) {
44675                forEach(getPropertiesOfType(functionType), p => {
44676                    if (!propsByName.has(p.escapedName)) {
44677                        propsByName.set(p.escapedName, p);
44678                    }
44679                });
44680            }
44681            return getNamedMembers(propsByName);
44682        }
44683
44684        function typeHasCallOrConstructSignatures(type: Type): boolean {
44685            return ts.typeHasCallOrConstructSignatures(type, checker);
44686        }
44687
44688        function getRootSymbols(symbol: Symbol): readonly Symbol[] {
44689            const roots = getImmediateRootSymbols(symbol);
44690            return roots ? flatMap(roots, getRootSymbols) : [symbol];
44691        }
44692        function getImmediateRootSymbols(symbol: Symbol): readonly Symbol[] | undefined {
44693            if (getCheckFlags(symbol) & CheckFlags.Synthetic) {
44694                return mapDefined(getSymbolLinks(symbol).containingType!.types, type => getPropertyOfType(type, symbol.escapedName));
44695            }
44696            else if (symbol.flags & SymbolFlags.Transient) {
44697                const { leftSpread, rightSpread, syntheticOrigin } = symbol as TransientSymbol;
44698                return leftSpread ? [leftSpread, rightSpread!]
44699                    : syntheticOrigin ? [syntheticOrigin]
44700                    : singleElementArray(tryGetTarget(symbol));
44701            }
44702            return undefined;
44703        }
44704        function tryGetTarget(symbol: Symbol): Symbol | undefined {
44705            let target: Symbol | undefined;
44706            let next: Symbol | undefined = symbol;
44707            while (next = getSymbolLinks(next).target) {
44708                target = next;
44709            }
44710            return target;
44711        }
44712
44713        // Emitter support
44714
44715        function isArgumentsLocalBinding(nodeIn: Identifier): boolean {
44716            // Note: does not handle isShorthandPropertyAssignment (and probably a few more)
44717            if (isGeneratedIdentifier(nodeIn)) return false;
44718            const node = getParseTreeNode(nodeIn, isIdentifier);
44719            if (!node) return false;
44720            const parent = node.parent;
44721            if (!parent) return false;
44722            const isPropertyName = ((isPropertyAccessExpression(parent)
44723                                     || isPropertyAssignment(parent))
44724                                    && parent.name === node);
44725            return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol;
44726        }
44727
44728        function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
44729            let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
44730            if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) {
44731                // If the module is not found or is shorthand, assume that it may export a value.
44732                return true;
44733            }
44734
44735            const hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol);
44736            // if module has export assignment then 'resolveExternalModuleSymbol' will return resolved symbol for export assignment
44737            // otherwise it will return moduleSymbol itself
44738            moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
44739
44740            const symbolLinks = getSymbolLinks(moduleSymbol);
44741            if (symbolLinks.exportsSomeValue === undefined) {
44742                // for export assignments - check if resolved symbol for RHS is itself a value
44743                // otherwise - check if at least one export is value
44744                symbolLinks.exportsSomeValue = hasExportAssignment
44745                    ? !!(moduleSymbol.flags & SymbolFlags.Value)
44746                    : forEachEntry(getExportsOfModule(moduleSymbol), isValue);
44747            }
44748
44749            return symbolLinks.exportsSomeValue!;
44750
44751            function isValue(s: Symbol): boolean {
44752                s = resolveSymbol(s);
44753                return s && !!(getAllSymbolFlags(s) & SymbolFlags.Value);
44754            }
44755        }
44756
44757        function isNameOfModuleOrEnumDeclaration(node: Identifier) {
44758            return isModuleOrEnumDeclaration(node.parent) && node === node.parent.name;
44759        }
44760
44761        // When resolved as an expression identifier, if the given node references an exported entity, return the declaration
44762        // node of the exported entity's container. Otherwise, return undefined.
44763        function getReferencedExportContainer(nodeIn: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined {
44764            const node = getParseTreeNode(nodeIn, isIdentifier);
44765            if (node) {
44766                // When resolving the export container for the name of a module or enum
44767                // declaration, we need to start resolution at the declaration's container.
44768                // Otherwise, we could incorrectly resolve the export container as the
44769                // declaration if it contains an exported member with the same name.
44770                let symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node));
44771                if (symbol) {
44772                    if (symbol.flags & SymbolFlags.ExportValue) {
44773                        // If we reference an exported entity within the same module declaration, then whether
44774                        // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
44775                        // kinds that we do NOT prefix.
44776                        const exportSymbol = getMergedSymbol(symbol.exportSymbol!);
44777                        if (!prefixLocals && exportSymbol.flags & SymbolFlags.ExportHasLocal && !(exportSymbol.flags & SymbolFlags.Variable)) {
44778                            return undefined;
44779                        }
44780                        symbol = exportSymbol;
44781                    }
44782                    const parentSymbol = getParentOfSymbol(symbol);
44783                    if (parentSymbol) {
44784                        if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration?.kind === SyntaxKind.SourceFile) {
44785                            const symbolFile = parentSymbol.valueDeclaration as SourceFile;
44786                            const referenceFile = getSourceFileOfNode(node);
44787                            // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined.
44788                            const symbolIsUmdExport = symbolFile !== referenceFile;
44789                            return symbolIsUmdExport ? undefined : symbolFile;
44790                        }
44791                        return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol);
44792                    }
44793                }
44794            }
44795        }
44796
44797        // When resolved as an expression identifier, if the given node references an import, return the declaration of
44798        // that import. Otherwise, return undefined.
44799        function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined {
44800            if (nodeIn.generatedImportReference) {
44801                return nodeIn.generatedImportReference;
44802            }
44803            const node = getParseTreeNode(nodeIn, isIdentifier);
44804            if (node) {
44805                const symbol = getReferencedValueOrAliasSymbol(node);
44806
44807                // We should only get the declaration of an alias if there isn't a local value
44808                // declaration for the symbol
44809                if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) {
44810                    return getDeclarationOfAliasSymbol(symbol);
44811                }
44812            }
44813
44814            return undefined;
44815        }
44816
44817        function isSymbolOfDestructuredElementOfCatchBinding(symbol: Symbol) {
44818            return symbol.valueDeclaration
44819                && isBindingElement(symbol.valueDeclaration)
44820                && walkUpBindingElementsAndPatterns(symbol.valueDeclaration).parent.kind === SyntaxKind.CatchClause;
44821        }
44822
44823        function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean {
44824            if (symbol.flags & SymbolFlags.BlockScoped && symbol.valueDeclaration && !isSourceFile(symbol.valueDeclaration)) {
44825                const links = getSymbolLinks(symbol);
44826                if (links.isDeclarationWithCollidingName === undefined) {
44827                    const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
44828                    if (isStatementWithLocals(container) || isSymbolOfDestructuredElementOfCatchBinding(symbol)) {
44829                        const nodeLinks = getNodeLinks(symbol.valueDeclaration);
44830                        if (resolveName(container.parent, symbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) {
44831                            // redeclaration - always should be renamed
44832                            links.isDeclarationWithCollidingName = true;
44833                        }
44834                        else if (nodeLinks.flags & NodeCheckFlags.CapturedBlockScopedBinding) {
44835                            // binding is captured in the function
44836                            // should be renamed if:
44837                            // - binding is not top level - top level bindings never collide with anything
44838                            // AND
44839                            //   - binding is not declared in loop, should be renamed to avoid name reuse across siblings
44840                            //     let a, b
44841                            //     { let x = 1; a = () => x; }
44842                            //     { let x = 100; b = () => x; }
44843                            //     console.log(a()); // should print '1'
44844                            //     console.log(b()); // should print '100'
44845                            //     OR
44846                            //   - binding is declared inside loop but not in inside initializer of iteration statement or directly inside loop body
44847                            //     * variables from initializer are passed to rewritten loop body as parameters so they are not captured directly
44848                            //     * variables that are declared immediately in loop body will become top level variable after loop is rewritten and thus
44849                            //       they will not collide with anything
44850                            const isDeclaredInLoop = nodeLinks.flags & NodeCheckFlags.BlockScopedBindingInLoop;
44851                            const inLoopInitializer = isIterationStatement(container, /*lookInLabeledStatements*/ false);
44852                            const inLoopBodyBlock = container.kind === SyntaxKind.Block && isIterationStatement(container.parent, /*lookInLabeledStatements*/ false);
44853
44854                            links.isDeclarationWithCollidingName = !isBlockScopedContainerTopLevel(container) && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock));
44855                        }
44856                        else {
44857                            links.isDeclarationWithCollidingName = false;
44858                        }
44859                    }
44860                }
44861                return links.isDeclarationWithCollidingName!;
44862            }
44863            return false;
44864        }
44865
44866        // When resolved as an expression identifier, if the given node references a nested block scoped entity with
44867        // a name that either hides an existing name or might hide it when compiled downlevel,
44868        // return the declaration of that entity. Otherwise, return undefined.
44869        function getReferencedDeclarationWithCollidingName(nodeIn: Identifier): Declaration | undefined {
44870            if (!isGeneratedIdentifier(nodeIn)) {
44871                const node = getParseTreeNode(nodeIn, isIdentifier);
44872                if (node) {
44873                    const symbol = getReferencedValueSymbol(node);
44874                    if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) {
44875                        return symbol.valueDeclaration;
44876                    }
44877                }
44878            }
44879
44880            return undefined;
44881        }
44882
44883        // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an
44884        // existing name or might hide a name when compiled downlevel
44885        function isDeclarationWithCollidingName(nodeIn: Declaration): boolean {
44886            const node = getParseTreeNode(nodeIn, isDeclaration);
44887            if (node) {
44888                const symbol = getSymbolOfNode(node);
44889                if (symbol) {
44890                    return isSymbolOfDeclarationWithCollidingName(symbol);
44891                }
44892            }
44893
44894            return false;
44895        }
44896
44897        function isValueAliasDeclaration(node: Node): boolean {
44898            switch (node.kind) {
44899                case SyntaxKind.ImportEqualsDeclaration:
44900                    return isAliasResolvedToValue(getSymbolOfNode(node));
44901                case SyntaxKind.ImportClause:
44902                case SyntaxKind.NamespaceImport:
44903                case SyntaxKind.ImportSpecifier:
44904                case SyntaxKind.ExportSpecifier:
44905                    const symbol = getSymbolOfNode(node);
44906                    return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value);
44907                case SyntaxKind.ExportDeclaration:
44908                    const exportClause = (node as ExportDeclaration).exportClause;
44909                    return !!exportClause && (
44910                        isNamespaceExport(exportClause) ||
44911                        some(exportClause.elements, isValueAliasDeclaration)
44912                    );
44913                case SyntaxKind.ExportAssignment:
44914                    return (node as ExportAssignment).expression && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier ?
44915                        isAliasResolvedToValue(getSymbolOfNode(node)) :
44916                        true;
44917            }
44918            return false;
44919        }
44920
44921        function isTopLevelValueImportEqualsWithEntityName(nodeIn: ImportEqualsDeclaration): boolean {
44922            const node = getParseTreeNode(nodeIn, isImportEqualsDeclaration);
44923            if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) {
44924                // parent is not source file or it is not reference to internal module
44925                return false;
44926            }
44927
44928            const isValue = isAliasResolvedToValue(getSymbolOfNode(node));
44929            return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference);
44930        }
44931
44932        function isAliasResolvedToValue(symbol: Symbol | undefined): boolean {
44933            if (!symbol) {
44934                return false;
44935            }
44936            const target = getExportSymbolOfValueSymbolIfExported(resolveAlias(symbol));
44937            if (target === unknownSymbol) {
44938                return true;
44939            }
44940            // const enums and modules that contain only const enums are not considered values from the emit perspective
44941            // unless 'preserveConstEnums' option is set to true
44942            return !!((getAllSymbolFlags(target) ?? -1) & SymbolFlags.Value) &&
44943                (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target));
44944        }
44945
44946        function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean {
44947            return isConstEnumSymbol(s) || !!s.constEnumOnlyModule;
44948        }
44949
44950        function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
44951            if (isAliasSymbolDeclaration(node)) {
44952                const symbol = getSymbolOfNode(node);
44953                const links = symbol && getSymbolLinks(symbol);
44954                if (links?.referenced) {
44955                    return true;
44956                }
44957                const target = getSymbolLinks(symbol!).aliasTarget; // TODO: GH#18217
44958                if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export &&
44959                    getAllSymbolFlags(target) & SymbolFlags.Value &&
44960                    (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) {
44961                    // An `export import ... =` of a value symbol is always considered referenced
44962                    return true;
44963                }
44964            }
44965
44966            if (checkChildren) {
44967                return !!forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren));
44968            }
44969            return false;
44970        }
44971
44972        function isReferenced(node: Node): boolean {
44973            const symbol = getSymbolOfNode(node);
44974            return !!symbol?.isReferenced;
44975        }
44976
44977        function isImplementationOfOverload(node: SignatureDeclaration) {
44978            if (nodeIsPresent((node as FunctionLikeDeclaration).body)) {
44979                if (isGetAccessor(node) || isSetAccessor(node)) return false; // Get or set accessors can never be overload implementations, but can have up to 2 signatures
44980                const symbol = getSymbolOfNode(node);
44981                const signaturesOfSymbol = getSignaturesOfSymbol(symbol);
44982                // If this function body corresponds to function with multiple signature, it is implementation of overload
44983                // e.g.: function foo(a: string): string;
44984                //       function foo(a: number): number;
44985                //       function foo(a: any) { // This is implementation of the overloads
44986                //           return a;
44987                //       }
44988                return signaturesOfSymbol.length > 1 ||
44989                    // If there is single signature for the symbol, it is overload if that signature isn't coming from the node
44990                    // e.g.: function foo(a: string): string;
44991                    //       function foo(a: any) { // This is implementation of the overloads
44992                    //           return a;
44993                    //       }
44994                    (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node);
44995            }
44996            return false;
44997        }
44998
44999        function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag): boolean {
45000            return !!strictNullChecks &&
45001                !isOptionalParameter(parameter) &&
45002                !isJSDocParameterTag(parameter) &&
45003                !!parameter.initializer &&
45004                !hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier);
45005        }
45006
45007        function isOptionalUninitializedParameterProperty(parameter: ParameterDeclaration) {
45008            return strictNullChecks &&
45009                isOptionalParameter(parameter) &&
45010                !parameter.initializer &&
45011                hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier);
45012        }
45013
45014        function isExpandoFunctionDeclaration(node: Declaration): boolean {
45015            const declaration = getParseTreeNode(node, isFunctionDeclaration);
45016            if (!declaration) {
45017                return false;
45018            }
45019            const symbol = getSymbolOfNode(declaration);
45020            if (!symbol || !(symbol.flags & SymbolFlags.Function)) {
45021                return false;
45022            }
45023            return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && p.valueDeclaration && isPropertyAccessExpression(p.valueDeclaration));
45024        }
45025
45026        function getPropertiesOfContainerFunction(node: Declaration): Symbol[] {
45027            const declaration = getParseTreeNode(node, isFunctionDeclaration);
45028            if (!declaration) {
45029                return emptyArray;
45030            }
45031            const symbol = getSymbolOfNode(declaration);
45032            return symbol && getPropertiesOfType(getTypeOfSymbol(symbol)) || emptyArray;
45033        }
45034
45035        function getNodeCheckFlags(node: Node): NodeCheckFlags {
45036            const nodeId = node.id || 0;
45037            if (nodeId < 0 || nodeId >= nodeLinks.length) return 0;
45038            return nodeLinks[nodeId]?.flags || 0;
45039        }
45040
45041        function getEnumMemberValue(node: EnumMember): string | number | undefined {
45042            computeEnumMemberValues(node.parent);
45043            return getNodeLinks(node).enumMemberValue;
45044        }
45045
45046        function canHaveConstantValue(node: Node): node is EnumMember | AccessExpression {
45047            switch (node.kind) {
45048                case SyntaxKind.EnumMember:
45049                case SyntaxKind.PropertyAccessExpression:
45050                case SyntaxKind.ElementAccessExpression:
45051                    return true;
45052            }
45053            return false;
45054        }
45055
45056        function getConstantValue(node: EnumMember | AccessExpression): string | number | undefined {
45057            if (node.kind === SyntaxKind.EnumMember) {
45058                return getEnumMemberValue(node);
45059            }
45060
45061            const symbol = getNodeLinks(node).resolvedSymbol;
45062            if (symbol && (symbol.flags & SymbolFlags.EnumMember)) {
45063                // inline property\index accesses only for const enums
45064                const member = symbol.valueDeclaration as EnumMember;
45065                if (isEnumConst(member.parent)) {
45066                    return getEnumMemberValue(member);
45067                }
45068            }
45069
45070            return undefined;
45071        }
45072
45073        function isFunctionType(type: Type): boolean {
45074            return !!(type.flags & TypeFlags.Object) && getSignaturesOfType(type, SignatureKind.Call).length > 0;
45075        }
45076
45077        function getTypeReferenceSerializationKind(typeNameIn: EntityName, location?: Node): TypeReferenceSerializationKind {
45078            // ensure both `typeName` and `location` are parse tree nodes.
45079            const typeName = getParseTreeNode(typeNameIn, isEntityName);
45080            if (!typeName) return TypeReferenceSerializationKind.Unknown;
45081
45082            if (location) {
45083                location = getParseTreeNode(location);
45084                if (!location) return TypeReferenceSerializationKind.Unknown;
45085            }
45086
45087            // Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
45088            let isTypeOnly = false;
45089            if (isQualifiedName(typeName)) {
45090                const rootValueSymbol = resolveEntityName(getFirstIdentifier(typeName), SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location);
45091                isTypeOnly = !!rootValueSymbol?.declarations?.every(isTypeOnlyImportOrExportDeclaration);
45092            }
45093            const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location);
45094            const resolvedSymbol = valueSymbol && valueSymbol.flags & SymbolFlags.Alias ? resolveAlias(valueSymbol) : valueSymbol;
45095            isTypeOnly ||= !!valueSymbol?.declarations?.every(isTypeOnlyImportOrExportDeclaration);
45096
45097            // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer.
45098            const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
45099            if (resolvedSymbol && resolvedSymbol === typeSymbol) {
45100                const globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false);
45101                if (globalPromiseSymbol && resolvedSymbol === globalPromiseSymbol) {
45102                    return TypeReferenceSerializationKind.Promise;
45103                }
45104
45105                const constructorType = getTypeOfSymbol(resolvedSymbol);
45106                if (constructorType && isConstructorType(constructorType)) {
45107                    return isTypeOnly ? TypeReferenceSerializationKind.TypeWithCallSignature : TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
45108                }
45109            }
45110
45111            // We might not be able to resolve type symbol so use unknown type in that case (eg error case)
45112            if (!typeSymbol) {
45113                return isTypeOnly ? TypeReferenceSerializationKind.ObjectType : TypeReferenceSerializationKind.Unknown;
45114            }
45115            const type = getDeclaredTypeOfSymbol(typeSymbol);
45116            if (isErrorType(type)) {
45117                return isTypeOnly ? TypeReferenceSerializationKind.ObjectType : TypeReferenceSerializationKind.Unknown;
45118            }
45119            else if (type.flags & TypeFlags.AnyOrUnknown) {
45120                return TypeReferenceSerializationKind.ObjectType;
45121            }
45122            else if (isTypeAssignableToKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
45123                return TypeReferenceSerializationKind.VoidNullableOrNeverType;
45124            }
45125            else if (isTypeAssignableToKind(type, TypeFlags.BooleanLike)) {
45126                return TypeReferenceSerializationKind.BooleanType;
45127            }
45128            else if (isTypeAssignableToKind(type, TypeFlags.NumberLike)) {
45129                return TypeReferenceSerializationKind.NumberLikeType;
45130            }
45131            else if (isTypeAssignableToKind(type, TypeFlags.BigIntLike)) {
45132                return TypeReferenceSerializationKind.BigIntLikeType;
45133            }
45134            else if (isTypeAssignableToKind(type, TypeFlags.StringLike)) {
45135                return TypeReferenceSerializationKind.StringLikeType;
45136            }
45137            else if (isTupleType(type)) {
45138                return TypeReferenceSerializationKind.ArrayLikeType;
45139            }
45140            else if (isTypeAssignableToKind(type, TypeFlags.ESSymbolLike)) {
45141                return TypeReferenceSerializationKind.ESSymbolType;
45142            }
45143            else if (isFunctionType(type)) {
45144                return TypeReferenceSerializationKind.TypeWithCallSignature;
45145            }
45146            else if (isArrayType(type)) {
45147                return TypeReferenceSerializationKind.ArrayLikeType;
45148            }
45149            else {
45150                return TypeReferenceSerializationKind.ObjectType;
45151            }
45152        }
45153
45154        function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) {
45155            const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor);
45156            if (!declaration) {
45157                return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode;
45158            }
45159            // Get type of the symbol if this is the valid symbol otherwise get type at location
45160            const symbol = getSymbolOfNode(declaration);
45161            let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
45162                ? getWidenedLiteralType(getTypeOfSymbol(symbol))
45163                : errorType;
45164            if (type.flags & TypeFlags.UniqueESSymbol &&
45165                type.symbol === symbol) {
45166                flags |= NodeBuilderFlags.AllowUniqueESSymbolType;
45167            }
45168            if (addUndefined) {
45169                type = getOptionalType(type);
45170            }
45171            return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
45172        }
45173
45174        function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) {
45175            const signatureDeclaration = getParseTreeNode(signatureDeclarationIn, isFunctionLike);
45176            if (!signatureDeclaration) {
45177                return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode;
45178            }
45179            const signature = getSignatureFromDeclaration(signatureDeclaration);
45180            return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
45181        }
45182
45183        function createTypeOfExpression(exprIn: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) {
45184            const expr = getParseTreeNode(exprIn, isExpression);
45185            if (!expr) {
45186                return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode;
45187            }
45188            const type = getWidenedType(getRegularTypeOfExpression(expr));
45189            return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker);
45190        }
45191
45192        function hasGlobalName(name: string): boolean {
45193            return globals.has(escapeLeadingUnderscores(name));
45194        }
45195
45196        function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol | undefined {
45197            const resolvedSymbol = getNodeLinks(reference).resolvedSymbol;
45198            if (resolvedSymbol) {
45199                return resolvedSymbol;
45200            }
45201
45202            let location: Node = reference;
45203            if (startInDeclarationContainer) {
45204                // When resolving the name of a declaration as a value, we need to start resolution
45205                // at a point outside of the declaration.
45206                const parent = reference.parent;
45207                if (isDeclaration(parent) && reference === parent.name) {
45208                    location = getDeclarationContainer(parent);
45209                }
45210            }
45211
45212            return resolveName(location, reference.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
45213        }
45214
45215        /**
45216         * Get either a value-meaning symbol or an alias symbol.
45217         * Unlike `getReferencedValueSymbol`, if the cached resolved symbol is the unknown symbol,
45218         * we call `resolveName` to find a symbol.
45219         * This is because when caching the resolved symbol, we only consider value symbols, but here
45220         * we want to also get an alias symbol if one exists.
45221         */
45222        function getReferencedValueOrAliasSymbol(reference: Identifier): Symbol | undefined {
45223            const resolvedSymbol = getNodeLinks(reference).resolvedSymbol;
45224            if (resolvedSymbol && resolvedSymbol !== unknownSymbol) {
45225                return resolvedSymbol;
45226            }
45227
45228            return resolveName(
45229                reference,
45230                reference.escapedText,
45231                SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias,
45232                /*nodeNotFoundMessage*/ undefined,
45233                /*nameArg*/ undefined,
45234                /*isUse*/ true,
45235                /*excludeGlobals*/ undefined,
45236                /*getSpellingSuggestions*/ undefined);
45237        }
45238
45239        function getReferencedValueDeclaration(referenceIn: Identifier): Declaration | undefined {
45240            if (!isGeneratedIdentifier(referenceIn)) {
45241                const reference = getParseTreeNode(referenceIn, isIdentifier);
45242                if (reference) {
45243                    const symbol = getReferencedValueSymbol(reference);
45244                    if (symbol) {
45245                        return getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration;
45246                    }
45247                }
45248            }
45249
45250            return undefined;
45251        }
45252
45253        function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean {
45254            if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node)) {
45255                return isFreshLiteralType(getTypeOfSymbol(getSymbolOfNode(node)));
45256            }
45257            return false;
45258        }
45259
45260        function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
45261            const enumResult = type.flags & TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker)
45262                : type === trueType ? factory.createTrue() : type === falseType && factory.createFalse();
45263            if (enumResult) return enumResult;
45264            const literalValue = (type as LiteralType).value;
45265            return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) :
45266                typeof literalValue === "number" ? factory.createNumericLiteral(literalValue) :
45267                factory.createStringLiteral(literalValue);
45268        }
45269
45270        function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker) {
45271            const type = getTypeOfSymbol(getSymbolOfNode(node));
45272            return literalTypeToNode(type as FreshableType, node, tracker);
45273        }
45274
45275        function getJsxFactoryEntity(location: Node): EntityName | undefined {
45276            return location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity;
45277        }
45278
45279        function getJsxFragmentFactoryEntity(location: Node): EntityName | undefined {
45280            if (location) {
45281                const file = getSourceFileOfNode(location);
45282                if (file) {
45283                    if (file.localJsxFragmentFactory) {
45284                        return file.localJsxFragmentFactory;
45285                    }
45286                    const jsxFragPragmas = file.pragmas.get("jsxfrag");
45287                    const jsxFragPragma = isArray(jsxFragPragmas) ? jsxFragPragmas[0] : jsxFragPragmas;
45288                    if (jsxFragPragma) {
45289                        file.localJsxFragmentFactory = parseIsolatedEntityName(jsxFragPragma.arguments.factory, languageVersion);
45290                        return file.localJsxFragmentFactory;
45291                    }
45292                }
45293            }
45294
45295            if (compilerOptions.jsxFragmentFactory) {
45296                return parseIsolatedEntityName(compilerOptions.jsxFragmentFactory, languageVersion);
45297            }
45298        }
45299
45300        function createResolver(): EmitResolver {
45301            // this variable and functions that use it are deliberately moved here from the outer scope
45302            // to avoid scope pollution
45303            const resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives();
45304            let fileToDirective: ESMap<string, [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined]>;
45305            if (resolvedTypeReferenceDirectives) {
45306                // populate reverse mapping: file path -> type reference directive that was resolved to this file
45307                fileToDirective = new Map<string, [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined]>();
45308                resolvedTypeReferenceDirectives.forEach((resolvedDirective, key, mode) => {
45309                    if (!resolvedDirective || !resolvedDirective.resolvedFileName) {
45310                        return;
45311                    }
45312                    const file = host.getSourceFile(resolvedDirective.resolvedFileName);
45313                    if (file) {
45314                        // Add the transitive closure of path references loaded by this file (as long as they are not)
45315                        // part of an existing type reference.
45316                        addReferencedFilesToTypeDirective(file, key, mode);
45317                    }
45318                });
45319            }
45320
45321            return {
45322                getReferencedExportContainer,
45323                getReferencedImportDeclaration,
45324                getReferencedDeclarationWithCollidingName,
45325                isDeclarationWithCollidingName,
45326                isValueAliasDeclaration: nodeIn => {
45327                    const node = getParseTreeNode(nodeIn);
45328                    // Synthesized nodes are always treated like values.
45329                    return node ? isValueAliasDeclaration(node) : true;
45330                },
45331                hasGlobalName,
45332                isReferencedAliasDeclaration: (nodeIn, checkChildren?) => {
45333                    const node = getParseTreeNode(nodeIn);
45334                    // Synthesized nodes are always treated as referenced.
45335                    return node ? isReferencedAliasDeclaration(node, checkChildren) : true;
45336                },
45337                isReferenced: (nodeIn: Node | undefined): boolean => {
45338                    const node = getParseTreeNode(nodeIn);
45339                    return node ? isReferenced(node) : false;
45340                },
45341                getNodeCheckFlags: nodeIn => {
45342                    const node = getParseTreeNode(nodeIn);
45343                    return node ? getNodeCheckFlags(node) : 0;
45344                },
45345                isTopLevelValueImportEqualsWithEntityName,
45346                isDeclarationVisible,
45347                isImplementationOfOverload,
45348                isRequiredInitializedParameter,
45349                isOptionalUninitializedParameterProperty,
45350                isExpandoFunctionDeclaration,
45351                getPropertiesOfContainerFunction,
45352                createTypeOfDeclaration,
45353                createReturnTypeOfSignatureDeclaration,
45354                createTypeOfExpression,
45355                createLiteralConstValue,
45356                isSymbolAccessible,
45357                isEntityNameVisible,
45358                getConstantValue: nodeIn => {
45359                    const node = getParseTreeNode(nodeIn, canHaveConstantValue);
45360                    return node ? getConstantValue(node) : undefined;
45361                },
45362                collectLinkedAliases,
45363                getReferencedValueDeclaration,
45364                getTypeReferenceSerializationKind,
45365                isOptionalParameter,
45366                moduleExportsSomeValue,
45367                isArgumentsLocalBinding,
45368                getExternalModuleFileFromDeclaration: nodeIn => {
45369                    const node = getParseTreeNode(nodeIn, hasPossibleExternalModuleReference);
45370                    return node && getExternalModuleFileFromDeclaration(node);
45371                },
45372                getTypeReferenceDirectivesForEntityName,
45373                getTypeReferenceDirectivesForSymbol,
45374                isLiteralConstDeclaration,
45375                isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
45376                    const node = getParseTreeNode(nodeIn, isDeclaration);
45377                    const symbol = node && getSymbolOfNode(node);
45378                    return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late);
45379                },
45380                getJsxFactoryEntity,
45381                getJsxFragmentFactoryEntity,
45382                getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations {
45383                    accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217
45384                    const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor;
45385                    const otherAccessor = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(accessor), otherKind);
45386                    const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor;
45387                    const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor;
45388                    const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration;
45389                    const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor as GetAccessorDeclaration;
45390                    return {
45391                        firstAccessor,
45392                        secondAccessor,
45393                        setAccessor,
45394                        getAccessor
45395                    };
45396                },
45397                getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined),
45398                isBindingCapturedByNode: (node, decl) => {
45399                    const parseNode = getParseTreeNode(node);
45400                    const parseDecl = getParseTreeNode(decl);
45401                    return !!parseNode && !!parseDecl && (isVariableDeclaration(parseDecl) || isBindingElement(parseDecl)) && isBindingCapturedByNode(parseNode, parseDecl);
45402                },
45403                getDeclarationStatementsForSourceFile: (node, flags, tracker, bundled) => {
45404                    const n = getParseTreeNode(node) as SourceFile;
45405                    Debug.assert(n && n.kind === SyntaxKind.SourceFile, "Non-sourcefile node passed into getDeclarationsForSourceFile");
45406                    const sym = getSymbolOfNode(node);
45407                    if (!sym) {
45408                        return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled);
45409                    }
45410                    return !sym.exports ? [] : nodeBuilder.symbolTableToDeclarationStatements(sym.exports, node, flags, tracker, bundled);
45411                },
45412                isImportRequiredByAugmentation,
45413                getAnnotationObjectLiteralEvaluatedProps: (node: Annotation): ESMap<__String, Expression> | undefined => {
45414                    return getNodeLinks(node).annotationObjectLiteralEvaluatedProps;
45415                },
45416                getAnnotationPropertyEvaluatedInitializer: (node: AnnotationPropertyDeclaration): Expression | undefined => {
45417                    return getNodeLinks(node).annotationPropertyEvaluatedInitializer;
45418                },
45419                getAnnotationPropertyInferredType: (node: AnnotationPropertyDeclaration): TypeNode | undefined => {
45420                    return getNodeLinks(node).annotationPropertyInferredType;
45421                },
45422                isReferredToAnnotation: (node: ImportSpecifier | ExportSpecifier | ExportAssignment): boolean | undefined => {
45423                    return getNodeLinks(node).exportOrImportRefersToAnnotation;
45424                }
45425            };
45426
45427            function isImportRequiredByAugmentation(node: ImportDeclaration) {
45428                const file = getSourceFileOfNode(node);
45429                if (!file.symbol) return false;
45430                const importTarget = getExternalModuleFileFromDeclaration(node);
45431                if (!importTarget) return false;
45432                if (importTarget === file) return false;
45433                const exports = getExportsOfModule(file.symbol);
45434                for (const s of arrayFrom(exports.values())) {
45435                    if (s.mergeId) {
45436                        const merged = getMergedSymbol(s);
45437                        if (merged.declarations) {
45438                            for (const d of merged.declarations) {
45439                                const declFile = getSourceFileOfNode(d);
45440                                if (declFile === importTarget) {
45441                                    return true;
45442                                }
45443                            }
45444                        }
45445                    }
45446                }
45447                return false;
45448            }
45449
45450            function isInHeritageClause(node: PropertyAccessEntityNameExpression) {
45451                return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause;
45452            }
45453
45454            // defined here to avoid outer scope pollution
45455            function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined {
45456                // program does not have any files with type reference directives - bail out
45457                if (!fileToDirective) {
45458                    return undefined;
45459                }
45460                // computed property name should use node as value
45461                // property access can only be used as values, or types when within an expression with type arguments inside a heritage clause
45462                // qualified names can only be used as types\namespaces
45463                // identifiers are treated as values only if they appear in type queries
45464                let meaning;
45465                if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
45466                    meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
45467                }
45468                else {
45469                    meaning = SymbolFlags.Type | SymbolFlags.Namespace;
45470                    if ((node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) {
45471                        meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
45472                    }
45473                }
45474
45475                const symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true);
45476                return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) : undefined;
45477            }
45478
45479            // defined here to avoid outer scope pollution
45480            function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined {
45481                // program does not have any files with type reference directives - bail out
45482                if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) {
45483                    return undefined;
45484                }
45485                // check what declarations in the symbol can contribute to the target meaning
45486                let typeReferenceDirectives: [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined;
45487                for (const decl of symbol.declarations!) {
45488                    // check meaning of the local symbol to see if declaration needs to be analyzed further
45489                    if (decl.symbol && decl.symbol.flags & meaning!) {
45490                        const file = getSourceFileOfNode(decl);
45491                        const typeReferenceDirective = fileToDirective.get(file.path);
45492                        if (typeReferenceDirective) {
45493                            (typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective);
45494                        }
45495                        else {
45496                            // found at least one entry that does not originate from type reference directive
45497                            return undefined;
45498                        }
45499                    }
45500                }
45501                return typeReferenceDirectives;
45502            }
45503
45504            function isSymbolFromTypeDeclarationFile(symbol: Symbol): boolean {
45505                // bail out if symbol does not have associated declarations (i.e. this is transient symbol created for property in binding pattern)
45506                if (!symbol.declarations) {
45507                    return false;
45508                }
45509
45510                // walk the parent chain for symbols to make sure that top level parent symbol is in the global scope
45511                // external modules cannot define or contribute to type declaration files
45512                let current = symbol;
45513                while (true) {
45514                    const parent = getParentOfSymbol(current);
45515                    if (parent) {
45516                        current = parent;
45517                    }
45518                    else {
45519                        break;
45520                    }
45521                }
45522
45523                if (current.valueDeclaration && current.valueDeclaration.kind === SyntaxKind.SourceFile && current.flags & SymbolFlags.ValueModule) {
45524                    return false;
45525                }
45526
45527                // check that at least one declaration of top level symbol originates from type declaration file
45528                for (const decl of symbol.declarations) {
45529                    const file = getSourceFileOfNode(decl);
45530                    if (fileToDirective.has(file.path)) {
45531                        return true;
45532                    }
45533                }
45534                return false;
45535            }
45536
45537            function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: SourceFile["impliedNodeFormat"] | undefined) {
45538                if (fileToDirective.has(file.path)) return;
45539                fileToDirective.set(file.path, [key, mode]);
45540                for (const { fileName, resolutionMode } of file.referencedFiles) {
45541                    const resolvedFile = resolveTripleslashReference(fileName, file.fileName);
45542                    const referencedFile = host.getSourceFile(resolvedFile);
45543                    if (referencedFile) {
45544                        addReferencedFilesToTypeDirective(referencedFile, key, resolutionMode || file.impliedNodeFormat);
45545                    }
45546                }
45547            }
45548        }
45549
45550        function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined {
45551            const specifier = declaration.kind === SyntaxKind.ModuleDeclaration ? tryCast(declaration.name, isStringLiteral) : getExternalModuleName(declaration);
45552            const moduleSymbol = resolveExternalModuleNameWorker(specifier!, specifier!, /*moduleNotFoundError*/ undefined); // TODO: GH#18217
45553            if (!moduleSymbol) {
45554                return undefined;
45555            }
45556            return getDeclarationOfKind(moduleSymbol, SyntaxKind.SourceFile);
45557        }
45558
45559        function initializeTypeChecker() {
45560            // Bind all source files and propagate errors
45561            for (const file of host.getSourceFiles()) {
45562                bindSourceFile(file, compilerOptions);
45563            }
45564
45565            amalgamatedDuplicates = new Map();
45566
45567            // Initialize global symbol table
45568            let augmentations: (readonly (StringLiteral | Identifier)[])[] | undefined;
45569            for (const file of host.getSourceFiles()) {
45570                if (file.redirectInfo) {
45571                    continue;
45572                }
45573                if (!isExternalOrCommonJsModule(file)) {
45574                    // It is an error for a non-external-module (i.e. script) to declare its own `globalThis`.
45575                    // We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files.
45576                    const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String);
45577                    if (fileGlobalThisSymbol?.declarations) {
45578                        for (const declaration of fileGlobalThisSymbol.declarations) {
45579                            diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis"));
45580                        }
45581                    }
45582                    mergeSymbolTable(globals, file.locals!);
45583                }
45584                if (file.jsGlobalAugmentations) {
45585                    mergeSymbolTable(globals, file.jsGlobalAugmentations);
45586                }
45587                if (file.patternAmbientModules && file.patternAmbientModules.length) {
45588                    patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules);
45589                }
45590                if (file.moduleAugmentations.length) {
45591                    (augmentations || (augmentations = [])).push(file.moduleAugmentations);
45592                }
45593                if (file.symbol && file.symbol.globalExports) {
45594                    // Merge in UMD exports with first-in-wins semantics (see #9771)
45595                    const source = file.symbol.globalExports;
45596                    source.forEach((sourceSymbol, id) => {
45597                        if (!globals.has(id)) {
45598                            globals.set(id, sourceSymbol);
45599                        }
45600                    });
45601                }
45602            }
45603
45604            // We do global augmentations separately from module augmentations (and before creating global types) because they
45605            //  1. Affect global types. We won't have the correct global types until global augmentations are merged. Also,
45606            //  2. Module augmentation instantiation requires creating the type of a module, which, in turn, can require
45607            //       checking for an export or property on the module (if export=) which, in turn, can fall back to the
45608            //       apparent type of the module - either globalObjectType or globalFunctionType - which wouldn't exist if we
45609            //       did module augmentations prior to finalizing the global types.
45610            if (augmentations) {
45611                // merge _global_ module augmentations.
45612                // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
45613                for (const list of augmentations) {
45614                    for (const augmentation of list) {
45615                        if (!isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)) continue;
45616                        mergeModuleAugmentation(augmentation);
45617                    }
45618                }
45619            }
45620
45621            // Setup global builtins
45622            addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
45623
45624            getSymbolLinks(undefinedSymbol).type = undefinedWideningType;
45625            getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true);
45626            getSymbolLinks(unknownSymbol).type = errorType;
45627            getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol);
45628
45629            // Initialize special types
45630            globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true);
45631            globalObjectType = getGlobalType("Object" as __String, /*arity*/ 0, /*reportErrors*/ true);
45632            globalFunctionType = getGlobalType("Function" as __String, /*arity*/ 0, /*reportErrors*/ true);
45633            globalCallableFunctionType = strictBindCallApply && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType;
45634            globalNewableFunctionType = strictBindCallApply && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType;
45635            globalStringType = getGlobalType("String" as __String, /*arity*/ 0, /*reportErrors*/ true);
45636            globalNumberType = getGlobalType("Number" as __String, /*arity*/ 0, /*reportErrors*/ true);
45637            globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true);
45638            globalRegExpType = getGlobalType("RegExp" as __String, /*arity*/ 0, /*reportErrors*/ true);
45639            anyArrayType = createArrayType(anyType);
45640
45641            autoArrayType = createArrayType(autoType);
45642            if (autoArrayType === emptyObjectType) {
45643                // autoArrayType is used as a marker, so even if global Array type is not defined, it needs to be a unique type
45644                autoArrayType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray);
45645            }
45646
45647            globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1) as GenericType || globalArrayType;
45648            anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
45649            globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1) as GenericType;
45650
45651            if (augmentations) {
45652                // merge _nonglobal_ module augmentations.
45653                // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
45654                for (const list of augmentations) {
45655                    for (const augmentation of list) {
45656                        if (isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)) continue;
45657                        mergeModuleAugmentation(augmentation);
45658                    }
45659                }
45660            }
45661
45662            amalgamatedDuplicates.forEach(({ firstFile, secondFile, conflictingSymbols }) => {
45663                // If not many things conflict, issue individual errors
45664                if (conflictingSymbols.size < 8) {
45665                    conflictingSymbols.forEach(({ isBlockScoped, firstFileLocations, secondFileLocations }, symbolName) => {
45666                        const message = isBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0;
45667                        for (const node of firstFileLocations) {
45668                            addDuplicateDeclarationError(node, message, symbolName, secondFileLocations);
45669                        }
45670                        for (const node of secondFileLocations) {
45671                            addDuplicateDeclarationError(node, message, symbolName, firstFileLocations);
45672                        }
45673                    });
45674                }
45675                else {
45676                    // Otherwise issue top-level error since the files appear very identical in terms of what they contain
45677                    const list = arrayFrom(conflictingSymbols.keys()).join(", ");
45678                    diagnostics.add(addRelatedInfo(
45679                        createDiagnosticForNode(firstFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list),
45680                        createDiagnosticForNode(secondFile, Diagnostics.Conflicts_are_in_this_file)
45681                    ));
45682                    diagnostics.add(addRelatedInfo(
45683                        createDiagnosticForNode(secondFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list),
45684                        createDiagnosticForNode(firstFile, Diagnostics.Conflicts_are_in_this_file)
45685                    ));
45686                }
45687            });
45688            amalgamatedDuplicates = undefined;
45689        }
45690
45691        function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) {
45692            if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) {
45693                const sourceFile = getSourceFileOfNode(location);
45694                if (isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & NodeFlags.Ambient)) {
45695                    const helpersModule = resolveHelpersModule(sourceFile, location);
45696                    if (helpersModule !== unknownSymbol) {
45697                        const uncheckedHelpers = helpers & ~requestedExternalEmitHelpers;
45698                        for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) {
45699                            if (uncheckedHelpers & helper) {
45700                                const name = getHelperName(helper);
45701                                const symbol = getSymbol(helpersModule.exports!, escapeLeadingUnderscores(name), SymbolFlags.Value);
45702                                if (!symbol) {
45703                                    error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name);
45704                                }
45705                                else if (helper & ExternalEmitHelpers.ClassPrivateFieldGet) {
45706                                    if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) {
45707                                        error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 4);
45708                                    }
45709                                }
45710                                else if (helper & ExternalEmitHelpers.ClassPrivateFieldSet) {
45711                                    if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) {
45712                                        error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 5);
45713                                    }
45714                                }
45715                                else if (helper & ExternalEmitHelpers.SpreadArray) {
45716                                    if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 2)) {
45717                                        error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 3);
45718                                    }
45719                                }
45720                            }
45721                        }
45722                    }
45723                    requestedExternalEmitHelpers |= helpers;
45724                }
45725            }
45726        }
45727
45728        function getHelperName(helper: ExternalEmitHelpers) {
45729            switch (helper) {
45730                case ExternalEmitHelpers.Extends: return "__extends";
45731                case ExternalEmitHelpers.Assign: return "__assign";
45732                case ExternalEmitHelpers.Rest: return "__rest";
45733                case ExternalEmitHelpers.Decorate: return "__decorate";
45734                case ExternalEmitHelpers.Metadata: return "__metadata";
45735                case ExternalEmitHelpers.Param: return "__param";
45736                case ExternalEmitHelpers.Awaiter: return "__awaiter";
45737                case ExternalEmitHelpers.Generator: return "__generator";
45738                case ExternalEmitHelpers.Values: return "__values";
45739                case ExternalEmitHelpers.Read: return "__read";
45740                case ExternalEmitHelpers.SpreadArray: return "__spreadArray";
45741                case ExternalEmitHelpers.Await: return "__await";
45742                case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator";
45743                case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
45744                case ExternalEmitHelpers.AsyncValues: return "__asyncValues";
45745                case ExternalEmitHelpers.ExportStar: return "__exportStar";
45746                case ExternalEmitHelpers.ImportStar: return "__importStar";
45747                case ExternalEmitHelpers.ImportDefault: return "__importDefault";
45748                case ExternalEmitHelpers.MakeTemplateObject: return "__makeTemplateObject";
45749                case ExternalEmitHelpers.ClassPrivateFieldGet: return "__classPrivateFieldGet";
45750                case ExternalEmitHelpers.ClassPrivateFieldSet: return "__classPrivateFieldSet";
45751                case ExternalEmitHelpers.ClassPrivateFieldIn: return "__classPrivateFieldIn";
45752                case ExternalEmitHelpers.CreateBinding: return "__createBinding";
45753                default: return Debug.fail("Unrecognized helper");
45754            }
45755        }
45756
45757        function resolveHelpersModule(node: SourceFile, errorNode: Node) {
45758            if (!externalHelpersModule) {
45759                externalHelpersModule = resolveExternalModule(node, externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol;
45760            }
45761            return externalHelpersModule;
45762        }
45763
45764        // GRAMMAR CHECKING
45765        function checkGrammarDecoratorsAndModifiers(node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators): boolean {
45766            return checkGrammarDecorators(node) || checkGrammarModifiers(node);
45767        }
45768
45769        function checkGrammarDecorators(node: Node): boolean {
45770            if (canHaveIllegalDecorators(node) && some(node.illegalDecorators) && !isArkTsDecorator(node, compilerOptions)) {
45771                if (isSendableFunctionOrType(node)) {
45772                    return false;
45773                }
45774                return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here);
45775            }
45776            if (!canHaveDecorators(node) || !hasDecorators(node) && !(isFunctionDeclaration(node) && !isArkTsDecorator(node, compilerOptions))) {
45777                return false;
45778            }
45779            const decorators = getAllDecorators(node);
45780            if (getSourceFileOfNode(node).scriptKind === ScriptKind.ETS) {
45781                if (isTokenInsideBuilder(decorators, compilerOptions) && !isConstructorDeclaration(node)) {
45782                    return false;
45783                }
45784                if (hasEtsStylesDecoratorNames(decorators, compilerOptions) && !isConstructorDeclaration(node)) {
45785                    return true;
45786                }
45787                // const etsComponentDecoratorNames = getEtsExtendDecoratorsComponentNames(decorators, compilerOptions);
45788                // if (etsComponentDecoratorNames.length) {
45789                //     const filtedEtsComponentNames = filterEtsExtendDecoratorComponentNamesByOptions(etsComponentDecoratorNames, compilerOptions);
45790                //     if (filtedEtsComponentNames.length) {
45791                //         return false;
45792                //     }
45793                //     const sourceFile = getSourceFileOfNode(node);
45794                //     const span = getSpanOfTokenAtPosition(sourceFile, node.pos);
45795                //     diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.Decorator_name_must_be_one_of_ETS_Components));
45796                //     return true;
45797                // }
45798            }
45799
45800            if (!nodeCanBeDecorated(node, node.parent, node.parent.parent, compilerOptions)) {
45801                const isMethodDeclarationAndNodeIsNotPresent = node.kind === SyntaxKind.MethodDeclaration && ! nodeIsPresent(node.body);
45802                const message = isMethodDeclarationAndNodeIsNotPresent ? Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload : Diagnostics.Decorators_are_not_valid_here;
45803                for (const decorator of decorators) {
45804                    if (!grammarErrorOnNode(decorator, message)) {
45805                        return false;
45806                    }
45807                }
45808                return true;
45809            }
45810            else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
45811                const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node as AccessorDeclaration);
45812                if (hasDecorators(accessors.firstAccessor) && node === accessors.secondAccessor) {
45813                    return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name);
45814                }
45815            }
45816            return false;
45817        }
45818
45819        function checkGrammarModifiers(node: HasModifiers | HasIllegalModifiers): boolean {
45820            const quickResult = reportObviousModifierErrors(node);
45821            if (quickResult !== undefined) {
45822                return quickResult;
45823            }
45824
45825            let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastOverride: Node | undefined;
45826            let flags = ModifierFlags.None;
45827            for (const modifier of node.modifiers!) {
45828                if (isDecorator(modifier)) continue;
45829                if (modifier.kind !== SyntaxKind.ReadonlyKeyword) {
45830                    if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) {
45831                        return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_member, tokenToString(modifier.kind));
45832                    }
45833                    if (node.kind === SyntaxKind.IndexSignature && (modifier.kind !== SyntaxKind.StaticKeyword || !isClassLike(node.parent))) {
45834                        return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_index_signature, tokenToString(modifier.kind));
45835                    }
45836                }
45837                if (modifier.kind !== SyntaxKind.InKeyword && modifier.kind !== SyntaxKind.OutKeyword) {
45838                    if (node.kind === SyntaxKind.TypeParameter) {
45839                        return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_parameter, tokenToString(modifier.kind));
45840                    }
45841                }
45842                switch (modifier.kind) {
45843                    case SyntaxKind.ConstKeyword:
45844                        if (node.kind !== SyntaxKind.EnumDeclaration) {
45845                            return grammarErrorOnNode(node, Diagnostics.A_class_member_cannot_have_the_0_keyword, tokenToString(SyntaxKind.ConstKeyword));
45846                        }
45847                        break;
45848                    case SyntaxKind.OverrideKeyword:
45849                        // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property.
45850                        if (flags & ModifierFlags.Override) {
45851                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override");
45852                        }
45853                        else if (flags & ModifierFlags.Ambient) {
45854                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "override", "declare");
45855                        }
45856                        else if (flags & ModifierFlags.Readonly) {
45857                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "readonly");
45858                        }
45859                        else if (flags & ModifierFlags.Accessor) {
45860                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "accessor");
45861                        }
45862                        else if (flags & ModifierFlags.Async) {
45863                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async");
45864                        }
45865                        flags |= ModifierFlags.Override;
45866                        lastOverride = modifier;
45867                        break;
45868
45869                    case SyntaxKind.PublicKeyword:
45870                    case SyntaxKind.ProtectedKeyword:
45871                    case SyntaxKind.PrivateKeyword:
45872                        const text = visibilityToString(modifierToFlag(modifier.kind));
45873
45874                        if (flags & ModifierFlags.AccessibilityModifier) {
45875                            return grammarErrorOnNode(modifier, Diagnostics.Accessibility_modifier_already_seen);
45876                        }
45877                        else if (flags & ModifierFlags.Override) {
45878                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "override");
45879                        }
45880                        else if (flags & ModifierFlags.Static) {
45881                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
45882                        }
45883                        else if (flags & ModifierFlags.Accessor) {
45884                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "accessor");
45885                        }
45886                        else if (flags & ModifierFlags.Readonly) {
45887                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly");
45888                        }
45889                        else if (flags & ModifierFlags.Async) {
45890                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async");
45891                        }
45892                        else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
45893                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text);
45894                        }
45895                        else if (flags & ModifierFlags.Abstract) {
45896                            if (modifier.kind === SyntaxKind.PrivateKeyword) {
45897                                return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract");
45898                            }
45899                            else {
45900                                return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "abstract");
45901                            }
45902                        }
45903                        else if (isPrivateIdentifierClassElementDeclaration(node)) {
45904                            return grammarErrorOnNode(modifier, Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier);
45905                        }
45906                        flags |= modifierToFlag(modifier.kind);
45907                        break;
45908
45909                    case SyntaxKind.StaticKeyword:
45910                        if (flags & ModifierFlags.Static) {
45911                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static");
45912                        }
45913                        else if (flags & ModifierFlags.Readonly) {
45914                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly");
45915                        }
45916                        else if (flags & ModifierFlags.Async) {
45917                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async");
45918                        }
45919                        else if (flags & ModifierFlags.Accessor) {
45920                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "accessor");
45921                        }
45922                        else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
45923                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static");
45924                        }
45925                        else if (node.kind === SyntaxKind.Parameter) {
45926                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static");
45927                        }
45928                        else if (flags & ModifierFlags.Abstract) {
45929                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
45930                        }
45931                        else if (flags & ModifierFlags.Override) {
45932                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "override");
45933                        }
45934                        flags |= ModifierFlags.Static;
45935                        lastStatic = modifier;
45936                        break;
45937
45938                    case SyntaxKind.AccessorKeyword:
45939                        if (flags & ModifierFlags.Accessor) {
45940                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "accessor");
45941                        }
45942                        else if (flags & ModifierFlags.Readonly) {
45943                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "readonly");
45944                        }
45945                        else if (flags & ModifierFlags.Ambient) {
45946                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "declare");
45947                        }
45948                        else if (node.kind !== SyntaxKind.PropertyDeclaration) {
45949                            return grammarErrorOnNode(modifier, Diagnostics.accessor_modifier_can_only_appear_on_a_property_declaration);
45950                        }
45951
45952                        flags |= ModifierFlags.Accessor;
45953                        break;
45954
45955                    case SyntaxKind.ReadonlyKeyword:
45956                        if (flags & ModifierFlags.Readonly) {
45957                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly");
45958                        }
45959                        else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) {
45960                            // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property.
45961                            return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature);
45962                        }
45963                        flags |= ModifierFlags.Readonly;
45964                        break;
45965
45966                    case SyntaxKind.ExportKeyword:
45967                        if (flags & ModifierFlags.Export) {
45968                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "export");
45969                        }
45970                        else if (flags & ModifierFlags.Ambient) {
45971                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
45972                        }
45973                        else if (flags & ModifierFlags.Abstract) {
45974                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract");
45975                        }
45976                        else if (flags & ModifierFlags.Async) {
45977                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async");
45978                        }
45979                        else if (isClassLike(node.parent)) {
45980                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "export");
45981                        }
45982                        else if (node.kind === SyntaxKind.Parameter) {
45983                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export");
45984                        }
45985                        flags |= ModifierFlags.Export;
45986                        break;
45987                    case SyntaxKind.DefaultKeyword:
45988                        const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent;
45989                        if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) {
45990                            return grammarErrorOnNode(modifier, Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module);
45991                        }
45992                        else if (!(flags & ModifierFlags.Export)) {
45993                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "default");
45994                        }
45995
45996                        flags |= ModifierFlags.Default;
45997                        break;
45998                    case SyntaxKind.DeclareKeyword:
45999                        if (flags & ModifierFlags.Ambient) {
46000                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
46001                        }
46002                        else if (flags & ModifierFlags.Async) {
46003                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
46004                        }
46005                        else if (flags & ModifierFlags.Override) {
46006                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "override");
46007                        }
46008                        else if (isClassLike(node.parent) && !isPropertyDeclaration(node)) {
46009                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "declare");
46010                        }
46011                        else if (node.kind === SyntaxKind.Parameter) {
46012                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare");
46013                        }
46014                        else if ((node.parent.flags & NodeFlags.Ambient) && node.parent.kind === SyntaxKind.ModuleBlock) {
46015                            return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
46016                        }
46017                        else if (isPrivateIdentifierClassElementDeclaration(node)) {
46018                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "declare");
46019                        }
46020                        flags |= ModifierFlags.Ambient;
46021                        lastDeclare = modifier;
46022                        break;
46023
46024                    case SyntaxKind.AbstractKeyword:
46025                        if (flags & ModifierFlags.Abstract) {
46026                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract");
46027                        }
46028                        if (node.kind !== SyntaxKind.ClassDeclaration &&
46029                            node.kind !== SyntaxKind.ConstructorType) {
46030                            if (node.kind !== SyntaxKind.MethodDeclaration &&
46031                                node.kind !== SyntaxKind.PropertyDeclaration &&
46032                                node.kind !== SyntaxKind.GetAccessor &&
46033                                node.kind !== SyntaxKind.SetAccessor) {
46034                                return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration);
46035                            }
46036                            if (!(node.parent.kind === SyntaxKind.ClassDeclaration && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) {
46037                                return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class);
46038                            }
46039                            if (flags & ModifierFlags.Static) {
46040                                return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
46041                            }
46042                            if (flags & ModifierFlags.Private) {
46043                                return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract");
46044                            }
46045                            if (flags & ModifierFlags.Async && lastAsync) {
46046                                return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract");
46047                            }
46048                            if (flags & ModifierFlags.Override) {
46049                                return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "override");
46050                            }
46051                            if (flags & ModifierFlags.Accessor) {
46052                                return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "accessor");
46053                            }
46054                        }
46055                        if (isNamedDeclaration(node) && node.name.kind === SyntaxKind.PrivateIdentifier) {
46056                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "abstract");
46057                        }
46058
46059                        flags |= ModifierFlags.Abstract;
46060                        break;
46061
46062                    case SyntaxKind.AsyncKeyword:
46063                        if (flags & ModifierFlags.Async) {
46064                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async");
46065                        }
46066                        else if (flags & ModifierFlags.Ambient || node.parent.flags & NodeFlags.Ambient) {
46067                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
46068                        }
46069                        else if (node.kind === SyntaxKind.Parameter) {
46070                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async");
46071                        }
46072                        if (flags & ModifierFlags.Abstract) {
46073                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract");
46074                        }
46075                        flags |= ModifierFlags.Async;
46076                        lastAsync = modifier;
46077                        break;
46078
46079                    case SyntaxKind.InKeyword:
46080                    case SyntaxKind.OutKeyword:
46081                        const inOutFlag = modifier.kind === SyntaxKind.InKeyword ? ModifierFlags.In : ModifierFlags.Out;
46082                        const inOutText = modifier.kind === SyntaxKind.InKeyword ? "in" : "out";
46083                        if (node.kind !== SyntaxKind.TypeParameter || !(isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent))) {
46084                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_type_parameter_of_a_class_interface_or_type_alias, inOutText);
46085                        }
46086                        if (flags & inOutFlag) {
46087                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, inOutText);
46088                        }
46089                        if (inOutFlag & ModifierFlags.In && flags & ModifierFlags.Out) {
46090                            return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "in", "out");
46091                        }
46092                        flags |= inOutFlag;
46093                        break;
46094                }
46095            }
46096
46097            if (node.kind === SyntaxKind.Constructor) {
46098                if (flags & ModifierFlags.Static) {
46099                    return grammarErrorOnNode(lastStatic!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static");
46100                }
46101                if (flags & ModifierFlags.Override) {
46102                    return grammarErrorOnNode(lastOverride!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "override"); // TODO: GH#18217
46103                }
46104                if (flags & ModifierFlags.Async) {
46105                    return grammarErrorOnNode(lastAsync!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
46106                }
46107                return false;
46108            }
46109            else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) {
46110                return grammarErrorOnNode(lastDeclare!, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
46111            }
46112            else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern(node.name)) {
46113                return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern);
46114            }
46115            else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && node.dotDotDotToken) {
46116                return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter);
46117            }
46118            if (flags & ModifierFlags.Async) {
46119                return checkGrammarAsyncModifier(node, lastAsync!);
46120            }
46121            return false;
46122        }
46123
46124        /**
46125         * true | false: Early return this value from checkGrammarModifiers.
46126         * undefined: Need to do full checking on the modifiers.
46127         */
46128        function reportObviousModifierErrors(node: HasModifiers | HasIllegalModifiers): boolean | undefined {
46129            return !node.modifiers
46130                ? false
46131                : shouldReportBadModifier(node)
46132                    ? grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here)
46133                    : undefined;
46134        }
46135
46136        function shouldReportBadModifier(node: HasModifiers | HasIllegalModifiers): boolean {
46137            switch (node.kind) {
46138                case SyntaxKind.GetAccessor:
46139                case SyntaxKind.SetAccessor:
46140                case SyntaxKind.Constructor:
46141                case SyntaxKind.PropertyDeclaration:
46142                case SyntaxKind.PropertySignature:
46143                case SyntaxKind.MethodDeclaration:
46144                case SyntaxKind.MethodSignature:
46145                case SyntaxKind.IndexSignature:
46146                case SyntaxKind.ModuleDeclaration:
46147                case SyntaxKind.ImportDeclaration:
46148                case SyntaxKind.ImportEqualsDeclaration:
46149                case SyntaxKind.ExportDeclaration:
46150                case SyntaxKind.ExportAssignment:
46151                case SyntaxKind.FunctionExpression:
46152                case SyntaxKind.ArrowFunction:
46153                case SyntaxKind.Parameter:
46154                case SyntaxKind.TypeParameter:
46155                    return false;
46156                case SyntaxKind.ClassStaticBlockDeclaration:
46157                case SyntaxKind.PropertyAssignment:
46158                case SyntaxKind.ShorthandPropertyAssignment:
46159                case SyntaxKind.NamespaceExportDeclaration:
46160                case SyntaxKind.FunctionType:
46161                case SyntaxKind.MissingDeclaration:
46162                    return true;
46163                default:
46164                    if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
46165                        return false;
46166                    }
46167                    switch (node.kind) {
46168                        case SyntaxKind.FunctionDeclaration:
46169                            return nodeHasAnyModifiersExcept(node, SyntaxKind.AsyncKeyword);
46170                        case SyntaxKind.ClassDeclaration:
46171                        case SyntaxKind.StructDeclaration:
46172                        case SyntaxKind.AnnotationDeclaration:
46173                        case SyntaxKind.ConstructorType:
46174                            return nodeHasAnyModifiersExcept(node, SyntaxKind.AbstractKeyword);
46175                        case SyntaxKind.ClassExpression:
46176                        case SyntaxKind.InterfaceDeclaration:
46177                        case SyntaxKind.VariableStatement:
46178                        case SyntaxKind.TypeAliasDeclaration:
46179                            return true;
46180                        case SyntaxKind.EnumDeclaration:
46181                            return nodeHasAnyModifiersExcept(node, SyntaxKind.ConstKeyword);
46182                        default:
46183                            Debug.assertNever(node);
46184                    }
46185            }
46186        }
46187
46188        function nodeHasAnyModifiersExcept(node: HasModifiers, allowedModifier: SyntaxKind): boolean {
46189            for (const modifier of node.modifiers!) {
46190                if (isDecorator(modifier)) continue;
46191                return modifier.kind !== allowedModifier;
46192            }
46193            return false;
46194        }
46195
46196        function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
46197            switch (node.kind) {
46198                case SyntaxKind.MethodDeclaration:
46199                case SyntaxKind.FunctionDeclaration:
46200                case SyntaxKind.FunctionExpression:
46201                case SyntaxKind.ArrowFunction:
46202                    return false;
46203            }
46204
46205            return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async");
46206        }
46207
46208        function checkGrammarForDisallowedTrailingComma(list: NodeArray<Node> | undefined, diag = Diagnostics.Trailing_comma_not_allowed): boolean {
46209            if (list && list.hasTrailingComma) {
46210                return grammarErrorAtPos(list[0], list.end - ",".length, ",".length, diag);
46211            }
46212            return false;
46213        }
46214
46215        function checkGrammarTypeParameterList(typeParameters: NodeArray<TypeParameterDeclaration> | undefined, file: SourceFile): boolean {
46216            if (typeParameters && typeParameters.length === 0) {
46217                const start = typeParameters.pos - "<".length;
46218                const end = skipTrivia(file.text, typeParameters.end) + ">".length;
46219                return grammarErrorAtPos(file, start, end - start, Diagnostics.Type_parameter_list_cannot_be_empty);
46220            }
46221            return false;
46222        }
46223
46224        function checkGrammarParameterList(parameters: NodeArray<ParameterDeclaration>) {
46225            let seenOptionalParameter = false;
46226            const parameterCount = parameters.length;
46227
46228            for (let i = 0; i < parameterCount; i++) {
46229                const parameter = parameters[i];
46230                if (parameter.dotDotDotToken) {
46231                    if (i !== (parameterCount - 1)) {
46232                        return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
46233                    }
46234                    if (!(parameter.flags & NodeFlags.Ambient)) { // Allow `...foo,` in ambient declarations; see GH#23070
46235                        checkGrammarForDisallowedTrailingComma(parameters, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
46236                    }
46237
46238                    if (parameter.questionToken) {
46239                        return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_rest_parameter_cannot_be_optional);
46240                    }
46241
46242                    if (parameter.initializer) {
46243                        return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer);
46244                    }
46245                }
46246                else if (isOptionalParameter(parameter)) {
46247                    seenOptionalParameter = true;
46248                    if (parameter.questionToken && parameter.initializer) {
46249                        return grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer);
46250                    }
46251                }
46252                else if (seenOptionalParameter && !parameter.initializer) {
46253                    return grammarErrorOnNode(parameter.name, Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter);
46254                }
46255            }
46256        }
46257
46258        function getNonSimpleParameters(parameters: readonly ParameterDeclaration[]): readonly ParameterDeclaration[] {
46259            return filter(parameters, parameter => !!parameter.initializer || isBindingPattern(parameter.name) || isRestParameter(parameter));
46260        }
46261
46262        function checkGrammarForUseStrictSimpleParameterList(node: FunctionLikeDeclaration): boolean {
46263            if (languageVersion >= ScriptTarget.ES2016) {
46264                const useStrictDirective = node.body && isBlock(node.body) && findUseStrictPrologue(node.body.statements);
46265                if (useStrictDirective) {
46266                    const nonSimpleParameters = getNonSimpleParameters(node.parameters);
46267                    if (length(nonSimpleParameters)) {
46268                        forEach(nonSimpleParameters, parameter => {
46269                            addRelatedInfo(
46270                                error(parameter, Diagnostics.This_parameter_is_not_allowed_with_use_strict_directive),
46271                                createDiagnosticForNode(useStrictDirective, Diagnostics.use_strict_directive_used_here)
46272                            );
46273                        });
46274
46275                        const diagnostics = nonSimpleParameters.map((parameter, index) => (
46276                            index === 0 ? createDiagnosticForNode(parameter, Diagnostics.Non_simple_parameter_declared_here) : createDiagnosticForNode(parameter, Diagnostics.and_here)
46277                        )) as [DiagnosticWithLocation, ...DiagnosticWithLocation[]];
46278                        addRelatedInfo(error(useStrictDirective, Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list), ...diagnostics);
46279                        return true;
46280                    }
46281                }
46282            }
46283            return false;
46284        }
46285
46286        function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean {
46287            // Prevent cascading error by short-circuit
46288            const file = getSourceFileOfNode(node);
46289            return checkGrammarDecoratorsAndModifiers(node) ||
46290                checkGrammarTypeParameterList(node.typeParameters, file) ||
46291                checkGrammarParameterList(node.parameters) ||
46292                checkGrammarArrowFunction(node, file) ||
46293                (isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node));
46294        }
46295
46296        function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean {
46297            const file = getSourceFileOfNode(node);
46298            return checkGrammarClassDeclarationHeritageClauses(node) ||
46299                checkGrammarTypeParameterList(node.typeParameters, file);
46300        }
46301
46302        function checkGrammarArrowFunction(node: Node, file: SourceFile): boolean {
46303            if (!isArrowFunction(node)) {
46304                return false;
46305            }
46306
46307            if (node.typeParameters && !(length(node.typeParameters) > 1 || node.typeParameters.hasTrailingComma || node.typeParameters[0].constraint)) {
46308                if (file && fileExtensionIsOneOf(file.fileName, [Extension.Mts, Extension.Cts])) {
46309                    grammarErrorOnNode(node.typeParameters[0], Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailing_comma_or_explicit_constraint);
46310                }
46311            }
46312
46313            const { equalsGreaterThanToken } = node;
46314            const startLine = getLineAndCharacterOfPosition(file, equalsGreaterThanToken.pos).line;
46315            const endLine = getLineAndCharacterOfPosition(file, equalsGreaterThanToken.end).line;
46316            return startLine !== endLine && grammarErrorOnNode(equalsGreaterThanToken, Diagnostics.Line_terminator_not_permitted_before_arrow);
46317        }
46318
46319        function checkGrammarIndexSignatureParameters(node: SignatureDeclaration): boolean {
46320            const parameter = node.parameters[0];
46321            if (node.parameters.length !== 1) {
46322                if (parameter) {
46323                    return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_must_have_exactly_one_parameter);
46324                }
46325                else {
46326                    return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_exactly_one_parameter);
46327                }
46328            }
46329            checkGrammarForDisallowedTrailingComma(node.parameters, Diagnostics.An_index_signature_cannot_have_a_trailing_comma);
46330            if (parameter.dotDotDotToken) {
46331                return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter);
46332            }
46333            if (hasEffectiveModifiers(parameter)) {
46334                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier);
46335            }
46336            if (parameter.questionToken) {
46337                return grammarErrorOnNode(parameter.questionToken, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark);
46338            }
46339            if (parameter.initializer) {
46340                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_initializer);
46341            }
46342            if (!parameter.type) {
46343                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_must_have_a_type_annotation);
46344            }
46345            const type = getTypeFromTypeNode(parameter.type);
46346            if (someType(type, t => !!(t.flags & TypeFlags.StringOrNumberLiteralOrUnique)) || isGenericType(type)) {
46347                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead);
46348            }
46349            if (!everyType(type, isValidIndexKeyType)) {
46350                return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_must_be_string_number_symbol_or_a_template_literal_type);
46351            }
46352            if (!node.type) {
46353                return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_a_type_annotation);
46354            }
46355            return false;
46356        }
46357
46358        function checkGrammarIndexSignature(node: IndexSignatureDeclaration) {
46359            // Prevent cascading error by short-circuit
46360            return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node);
46361        }
46362
46363        function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray<TypeNode> | undefined): boolean {
46364            if (typeArguments && typeArguments.length === 0) {
46365                const sourceFile = getSourceFileOfNode(node);
46366                const start = typeArguments.pos - "<".length;
46367                const end = skipTrivia(sourceFile.text, typeArguments.end) + ">".length;
46368                return grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Type_argument_list_cannot_be_empty);
46369            }
46370            return false;
46371        }
46372
46373        function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray<TypeNode> | undefined): boolean {
46374            return checkGrammarForDisallowedTrailingComma(typeArguments) ||
46375                checkGrammarForAtLeastOneTypeArgument(node, typeArguments);
46376        }
46377
46378        function checkGrammarTaggedTemplateChain(node: TaggedTemplateExpression): boolean {
46379            if (node.questionDotToken || node.flags & NodeFlags.OptionalChain) {
46380                return grammarErrorOnNode(node.template, Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain);
46381            }
46382            return false;
46383        }
46384
46385        function checkGrammarHeritageClause(node: HeritageClause): boolean {
46386            const types = node.types;
46387            if (checkGrammarForDisallowedTrailingComma(types)) {
46388                return true;
46389            }
46390            if (types && types.length === 0) {
46391                const listType = tokenToString(node.token);
46392                return grammarErrorAtPos(node, types.pos, 0, Diagnostics._0_list_cannot_be_empty, listType);
46393            }
46394            return some(types, checkGrammarExpressionWithTypeArguments);
46395        }
46396
46397        function checkGrammarExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) {
46398            if (isExpressionWithTypeArguments(node) && isImportKeyword(node.expression) && node.typeArguments) {
46399                return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments);
46400            }
46401            return checkGrammarTypeArguments(node, node.typeArguments);
46402        }
46403
46404        function checkGrammarClassDeclarationHeritageClauses(node: ClassLikeDeclaration) {
46405            let seenExtendsClause = false;
46406            let seenImplementsClause = false;
46407
46408            if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) {
46409                for (const heritageClause of node.heritageClauses) {
46410                    if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
46411                        if (seenExtendsClause) {
46412                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_already_seen);
46413                        }
46414
46415                        if (seenImplementsClause) {
46416                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_must_precede_implements_clause);
46417                        }
46418
46419                        if (heritageClause.types.length > 1) {
46420                            return grammarErrorOnFirstToken(heritageClause.types[1], Diagnostics.Classes_can_only_extend_a_single_class);
46421                        }
46422
46423                        seenExtendsClause = true;
46424                    }
46425                    else {
46426                        Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword);
46427                        if (seenImplementsClause) {
46428                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.implements_clause_already_seen);
46429                        }
46430
46431                        seenImplementsClause = true;
46432                    }
46433
46434                    // Grammar checking heritageClause inside class declaration
46435                    checkGrammarHeritageClause(heritageClause);
46436                }
46437            }
46438        }
46439
46440        function checkGrammarInterfaceDeclaration(node: InterfaceDeclaration) {
46441            let seenExtendsClause = false;
46442
46443            if (node.heritageClauses) {
46444                for (const heritageClause of node.heritageClauses) {
46445                    if (heritageClause.token === SyntaxKind.ExtendsKeyword) {
46446                        if (seenExtendsClause) {
46447                            return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_already_seen);
46448                        }
46449
46450                        seenExtendsClause = true;
46451                    }
46452                    else {
46453                        Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword);
46454                        return grammarErrorOnFirstToken(heritageClause, Diagnostics.Interface_declaration_cannot_have_implements_clause);
46455                    }
46456
46457                    // Grammar checking heritageClause inside class declaration
46458                    checkGrammarHeritageClause(heritageClause);
46459                }
46460            }
46461            return false;
46462        }
46463
46464        function checkGrammarComputedPropertyName(node: Node): boolean {
46465            // If node is not a computedPropertyName, just skip the grammar checking
46466            if (node.kind !== SyntaxKind.ComputedPropertyName) {
46467                return false;
46468            }
46469
46470            const computedPropertyName = node as ComputedPropertyName;
46471            if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (computedPropertyName.expression as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken) {
46472                return grammarErrorOnNode(computedPropertyName.expression, Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name);
46473            }
46474            return false;
46475        }
46476
46477        function checkGrammarForGenerator(node: FunctionLikeDeclaration) {
46478            if (node.asteriskToken) {
46479                Debug.assert(
46480                    node.kind === SyntaxKind.FunctionDeclaration ||
46481                    node.kind === SyntaxKind.FunctionExpression ||
46482                    node.kind === SyntaxKind.MethodDeclaration);
46483                if (node.flags & NodeFlags.Ambient) {
46484                    return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_allowed_in_an_ambient_context);
46485                }
46486                if (!node.body) {
46487                    return grammarErrorOnNode(node.asteriskToken, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator);
46488                }
46489            }
46490        }
46491
46492        function checkGrammarForInvalidQuestionMark(questionToken: QuestionToken | undefined, message: DiagnosticMessage): boolean {
46493            return !!questionToken && grammarErrorOnNode(questionToken, message);
46494        }
46495
46496        function checkGrammarForInvalidExclamationToken(exclamationToken: ExclamationToken | undefined, message: DiagnosticMessage): boolean {
46497            return !!exclamationToken && grammarErrorOnNode(exclamationToken, message);
46498        }
46499
46500        function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) {
46501            const seen = new Map<__String, DeclarationMeaning>();
46502
46503            for (const prop of node.properties) {
46504                if (prop.kind === SyntaxKind.SpreadAssignment) {
46505                    if (inDestructuring) {
46506                        // a rest property cannot be destructured any further
46507                        const expression = skipParentheses(prop.expression);
46508                        if (isArrayLiteralExpression(expression) || isObjectLiteralExpression(expression)) {
46509                            return grammarErrorOnNode(prop.expression, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern);
46510                        }
46511                    }
46512                    continue;
46513                }
46514                const name = prop.name;
46515                if (name.kind === SyntaxKind.ComputedPropertyName) {
46516                    // If the name is not a ComputedPropertyName, the grammar checking will skip it
46517                    checkGrammarComputedPropertyName(name);
46518                }
46519
46520                if (prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && prop.objectAssignmentInitializer) {
46521                    // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern
46522                    // outside of destructuring it is a syntax error
46523                    grammarErrorOnNode(prop.equalsToken!, Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern);
46524                }
46525
46526                if (name.kind === SyntaxKind.PrivateIdentifier) {
46527                    grammarErrorOnNode(name, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
46528                }
46529
46530                // Modifiers are never allowed on properties except for 'async' on a method declaration
46531                if (canHaveModifiers(prop) && prop.modifiers) {
46532                    for (const mod of prop.modifiers) {
46533                        if (isModifier(mod) && (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration)) {
46534                            grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
46535                        }
46536                    }
46537                }
46538                else if (canHaveIllegalModifiers(prop) && prop.modifiers) {
46539                    for (const mod of prop.modifiers) {
46540                        grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
46541                    }
46542                }
46543
46544                // ECMA-262 11.1.5 Object Initializer
46545                // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
46546                // a.This production is contained in strict code and IsDataDescriptor(previous) is true and
46547                // IsDataDescriptor(propId.descriptor) is true.
46548                //    b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true.
46549                //    c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true.
46550                //    d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true
46551                // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields
46552                let currentKind: DeclarationMeaning;
46553                switch (prop.kind) {
46554                    case SyntaxKind.ShorthandPropertyAssignment:
46555                    case SyntaxKind.PropertyAssignment:
46556                        // Grammar checking for computedPropertyName and shorthandPropertyAssignment
46557                        checkGrammarForInvalidExclamationToken(prop.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context);
46558                        checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
46559                        if (name.kind === SyntaxKind.NumericLiteral) {
46560                            checkGrammarNumericLiteral(name);
46561                        }
46562                        currentKind = DeclarationMeaning.PropertyAssignment;
46563                        break;
46564                    case SyntaxKind.MethodDeclaration:
46565                        currentKind = DeclarationMeaning.Method;
46566                        break;
46567                    case SyntaxKind.GetAccessor:
46568                        currentKind = DeclarationMeaning.GetAccessor;
46569                        break;
46570                    case SyntaxKind.SetAccessor:
46571                        currentKind = DeclarationMeaning.SetAccessor;
46572                        break;
46573                    default:
46574                        throw Debug.assertNever(prop, "Unexpected syntax kind:" + (prop as Node).kind);
46575                }
46576
46577                if (!inDestructuring) {
46578                    const effectiveName = getPropertyNameForPropertyNameNode(name);
46579                    if (effectiveName === undefined) {
46580                        continue;
46581                    }
46582
46583                    const existingKind = seen.get(effectiveName);
46584                    if (!existingKind) {
46585                        seen.set(effectiveName, currentKind);
46586                    }
46587                    else {
46588                        if ((currentKind & DeclarationMeaning.Method) && (existingKind & DeclarationMeaning.Method)) {
46589                            grammarErrorOnNode(name, Diagnostics.Duplicate_identifier_0, getTextOfNode(name));
46590                        }
46591                        else if ((currentKind & DeclarationMeaning.PropertyAssignment) && (existingKind & DeclarationMeaning.PropertyAssignment)) {
46592                            grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, getTextOfNode(name));
46593                        }
46594                        else if ((currentKind & DeclarationMeaning.GetOrSetAccessor) && (existingKind & DeclarationMeaning.GetOrSetAccessor)) {
46595                            if (existingKind !== DeclarationMeaning.GetOrSetAccessor && currentKind !== existingKind) {
46596                                seen.set(effectiveName, currentKind | existingKind);
46597                            }
46598                            else {
46599                                return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
46600                            }
46601                        }
46602                        else {
46603                            return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
46604                        }
46605                    }
46606                }
46607            }
46608        }
46609
46610        function checkGrammarJsxElement(node: JsxOpeningLikeElement) {
46611            checkGrammarJsxName(node.tagName);
46612            checkGrammarTypeArguments(node, node.typeArguments);
46613            const seen = new Map<__String, boolean>();
46614
46615            for (const attr of node.attributes.properties) {
46616                if (attr.kind === SyntaxKind.JsxSpreadAttribute) {
46617                    continue;
46618                }
46619
46620                const { name, initializer } = attr;
46621                if (!seen.get(name.escapedText)) {
46622                    seen.set(name.escapedText, true);
46623                }
46624                else {
46625                    return grammarErrorOnNode(name, Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name);
46626                }
46627
46628                if (initializer && initializer.kind === SyntaxKind.JsxExpression && !initializer.expression) {
46629                    return grammarErrorOnNode(initializer, Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression);
46630                }
46631            }
46632        }
46633
46634        function checkGrammarJsxName(node: JsxTagNameExpression) {
46635            if (isPropertyAccessExpression(node)) {
46636                let propName: JsxTagNameExpression = node;
46637                do {
46638                    const check = checkGrammarJsxNestedIdentifier(propName.name);
46639                    if (check) {
46640                        return check;
46641                    }
46642                    propName = propName.expression;
46643                } while (isPropertyAccessExpression(propName));
46644                const check = checkGrammarJsxNestedIdentifier(propName);
46645                if (check) {
46646                    return check;
46647                }
46648            }
46649
46650            function checkGrammarJsxNestedIdentifier(name: MemberName | ThisExpression) {
46651                if (isIdentifier(name) && idText(name).indexOf(":") !== -1) {
46652                    return grammarErrorOnNode(name, Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names);
46653                }
46654            }
46655        }
46656
46657        function checkGrammarJsxExpression(node: JsxExpression) {
46658            if (node.expression && isCommaSequence(node.expression)) {
46659                return grammarErrorOnNode(node.expression, Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array);
46660            }
46661        }
46662
46663        function checkGrammarForInOrForOfStatement(forInOrOfStatement: ForInOrOfStatement): boolean {
46664            if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) {
46665                return true;
46666            }
46667
46668            if (forInOrOfStatement.kind === SyntaxKind.ForOfStatement && forInOrOfStatement.awaitModifier) {
46669                if (!(forInOrOfStatement.flags & NodeFlags.AwaitContext)) {
46670                    const sourceFile = getSourceFileOfNode(forInOrOfStatement);
46671                    if (isInTopLevelContext(forInOrOfStatement)) {
46672                        if (!hasParseDiagnostics(sourceFile)) {
46673                            if (!isEffectiveExternalModule(sourceFile, compilerOptions)) {
46674                                diagnostics.add(createDiagnosticForNode(forInOrOfStatement.awaitModifier,
46675                                    Diagnostics.for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module));
46676                            }
46677                            switch (moduleKind) {
46678                                case ModuleKind.Node16:
46679                                case ModuleKind.NodeNext:
46680                                    if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) {
46681                                        diagnostics.add(
46682                                            createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level)
46683                                        );
46684                                        break;
46685                                    }
46686                                    // fallthrough
46687                                case ModuleKind.ES2022:
46688                                case ModuleKind.ESNext:
46689                                case ModuleKind.System:
46690                                    if (languageVersion >= ScriptTarget.ES2017) {
46691                                        break;
46692                                    }
46693                                    // fallthrough
46694                                default:
46695                                    diagnostics.add(
46696                                        createDiagnosticForNode(forInOrOfStatement.awaitModifier,
46697                                            Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher
46698                                        )
46699                                    );
46700                                    break;
46701                            }
46702                        }
46703                    }
46704                    else {
46705                        // use of 'for-await-of' in non-async function
46706                        if (!hasParseDiagnostics(sourceFile)) {
46707                            const diagnostic = createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules);
46708                            const func = getContainingFunction(forInOrOfStatement);
46709                            if (func && func.kind !== SyntaxKind.Constructor) {
46710                                Debug.assert((getFunctionFlags(func) & FunctionFlags.Async) === 0, "Enclosing function should never be an async function.");
46711                                const relatedInfo = createDiagnosticForNode(func, Diagnostics.Did_you_mean_to_mark_this_function_as_async);
46712                                addRelatedInfo(diagnostic, relatedInfo);
46713                            }
46714                            diagnostics.add(diagnostic);
46715                            return true;
46716                        }
46717                    }
46718                    return false;
46719                }
46720            }
46721
46722            if (isForOfStatement(forInOrOfStatement) && !(forInOrOfStatement.flags & NodeFlags.AwaitContext) &&
46723                isIdentifier(forInOrOfStatement.initializer) && forInOrOfStatement.initializer.escapedText === "async") {
46724                grammarErrorOnNode(forInOrOfStatement.initializer, Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async);
46725                return false;
46726            }
46727
46728            if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
46729                const variableList = forInOrOfStatement.initializer as VariableDeclarationList;
46730                if (!checkGrammarVariableDeclarationList(variableList)) {
46731                    const declarations = variableList.declarations;
46732
46733                    // declarations.length can be zero if there is an error in variable declaration in for-of or for-in
46734                    // See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details
46735                    // For example:
46736                    //      var let = 10;
46737                    //      for (let of [1,2,3]) {} // this is invalid ES6 syntax
46738                    //      for (let in [1,2,3]) {} // this is invalid ES6 syntax
46739                    // We will then want to skip on grammar checking on variableList declaration
46740                    if (!declarations.length) {
46741                        return false;
46742                    }
46743
46744                    if (declarations.length > 1) {
46745                        const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
46746                            ? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement
46747                            : Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement;
46748                        return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic);
46749                    }
46750                    const firstDeclaration = declarations[0];
46751
46752                    if (firstDeclaration.initializer) {
46753                        const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
46754                            ? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer
46755                            : Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer;
46756                        return grammarErrorOnNode(firstDeclaration.name, diagnostic);
46757                    }
46758                    if (firstDeclaration.type) {
46759                        const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement
46760                            ? Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation
46761                            : Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation;
46762                        return grammarErrorOnNode(firstDeclaration, diagnostic);
46763                    }
46764                }
46765            }
46766
46767            return false;
46768        }
46769
46770        function checkGrammarAccessor(accessor: AccessorDeclaration): boolean {
46771            if (!(accessor.flags & NodeFlags.Ambient) && (accessor.parent.kind !== SyntaxKind.TypeLiteral) && (accessor.parent.kind !== SyntaxKind.InterfaceDeclaration)) {
46772                if (languageVersion < ScriptTarget.ES5) {
46773                    return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
46774                }
46775                if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) {
46776                    return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
46777                }
46778                if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
46779                    return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
46780                }
46781            }
46782            if (accessor.body) {
46783                if (hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
46784                    return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation);
46785                }
46786                if (accessor.parent.kind === SyntaxKind.TypeLiteral || accessor.parent.kind === SyntaxKind.InterfaceDeclaration) {
46787                    return grammarErrorOnNode(accessor.body, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
46788                }
46789            }
46790            if (accessor.typeParameters) {
46791                return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_have_type_parameters);
46792            }
46793            if (!doesAccessorHaveCorrectParameterCount(accessor)) {
46794                return grammarErrorOnNode(accessor.name,
46795                    accessor.kind === SyntaxKind.GetAccessor ?
46796                        Diagnostics.A_get_accessor_cannot_have_parameters :
46797                        Diagnostics.A_set_accessor_must_have_exactly_one_parameter);
46798            }
46799            if (accessor.kind === SyntaxKind.SetAccessor) {
46800                if (accessor.type) {
46801                    return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation);
46802                }
46803                const parameter = Debug.checkDefined(getSetAccessorValueParameter(accessor), "Return value does not match parameter count assertion.");
46804                if (parameter.dotDotDotToken) {
46805                    return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter);
46806                }
46807                if (parameter.questionToken) {
46808                    return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter);
46809                }
46810                if (parameter.initializer) {
46811                    return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer);
46812                }
46813            }
46814            return false;
46815        }
46816
46817        /** Does the accessor have the right number of parameters?
46818         * A get accessor has no parameters or a single `this` parameter.
46819         * A set accessor has one parameter or a `this` parameter and one more parameter.
46820         */
46821        function doesAccessorHaveCorrectParameterCount(accessor: AccessorDeclaration) {
46822            return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 0 : 1);
46823        }
46824
46825        function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration | undefined {
46826            if (accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 1 : 2)) {
46827                return getThisParameter(accessor);
46828            }
46829        }
46830
46831        function checkGrammarTypeOperatorNode(node: TypeOperatorNode) {
46832            if (node.operator === SyntaxKind.UniqueKeyword) {
46833                if (node.type.kind !== SyntaxKind.SymbolKeyword) {
46834                    return grammarErrorOnNode(node.type, Diagnostics._0_expected, tokenToString(SyntaxKind.SymbolKeyword));
46835                }
46836                let parent = walkUpParenthesizedTypes(node.parent);
46837                if (isInJSFile(parent) && isJSDocTypeExpression(parent)) {
46838                    const host = getJSDocHost(parent);
46839                    if (host) {
46840                        parent = getSingleVariableOfVariableStatement(host) || host;
46841                    }
46842                }
46843                switch (parent.kind) {
46844                    case SyntaxKind.VariableDeclaration:
46845                        const decl = parent as VariableDeclaration;
46846                        if (decl.name.kind !== SyntaxKind.Identifier) {
46847                            return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name);
46848                        }
46849                        if (!isVariableDeclarationInVariableStatement(decl)) {
46850                            return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement);
46851                        }
46852                        if (!(decl.parent.flags & NodeFlags.Const)) {
46853                            return grammarErrorOnNode((parent as VariableDeclaration).name, Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const);
46854                        }
46855                        break;
46856
46857                    case SyntaxKind.PropertyDeclaration:
46858                        if (!isStatic(parent) ||
46859                            !hasEffectiveReadonlyModifier(parent)) {
46860                            return grammarErrorOnNode((parent as PropertyDeclaration).name, Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly);
46861                        }
46862                        break;
46863
46864                    case SyntaxKind.PropertySignature:
46865                        if (!hasSyntacticModifier(parent, ModifierFlags.Readonly)) {
46866                            return grammarErrorOnNode((parent as PropertySignature).name, Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly);
46867                        }
46868                        break;
46869
46870                    default:
46871                        return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_here);
46872                }
46873            }
46874            else if (node.operator === SyntaxKind.ReadonlyKeyword) {
46875                if (node.type.kind !== SyntaxKind.ArrayType && node.type.kind !== SyntaxKind.TupleType) {
46876                    return grammarErrorOnFirstToken(node, Diagnostics.readonly_type_modifier_is_only_permitted_on_array_and_tuple_literal_types, tokenToString(SyntaxKind.SymbolKeyword));
46877                }
46878            }
46879        }
46880
46881        function checkGrammarForInvalidDynamicName(node: DeclarationName, message: DiagnosticMessage) {
46882            if (isNonBindableDynamicName(node)) {
46883                return grammarErrorOnNode(node, message);
46884            }
46885        }
46886
46887        function checkGrammarMethod(node: MethodDeclaration | MethodSignature) {
46888            if (checkGrammarFunctionLikeDeclaration(node)) {
46889                return true;
46890            }
46891
46892            if (node.kind === SyntaxKind.MethodDeclaration) {
46893                if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
46894                    // We only disallow modifier on a method declaration if it is a property of object-literal-expression
46895                    if (node.modifiers && !(node.modifiers.length === 1 && first(node.modifiers).kind === SyntaxKind.AsyncKeyword)) {
46896                        return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
46897                    }
46898                    else if (checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) {
46899                        return true;
46900                    }
46901                    else if (checkGrammarForInvalidExclamationToken(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context)) {
46902                        return true;
46903                    }
46904                    else if (node.body === undefined) {
46905                        return grammarErrorAtPos(node, node.end - 1, ";".length, Diagnostics._0_expected, "{");
46906                    }
46907                }
46908                if (checkGrammarForGenerator(node)) {
46909                    return true;
46910                }
46911            }
46912
46913            if (isClassLike(node.parent)) {
46914                if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) {
46915                    return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
46916                }
46917                // Technically, computed properties in ambient contexts is disallowed
46918                // for property declarations and accessors too, not just methods.
46919                // However, property declarations disallow computed names in general,
46920                // and accessors are not allowed in ambient contexts in general,
46921                // so this error only really matters for methods.
46922                if (node.flags & NodeFlags.Ambient) {
46923                    return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type);
46924                }
46925                else if (node.kind === SyntaxKind.MethodDeclaration && !node.body) {
46926                    return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type);
46927                }
46928            }
46929            else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) {
46930                return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type);
46931            }
46932            else if (node.parent.kind === SyntaxKind.TypeLiteral) {
46933                return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type);
46934            }
46935        }
46936
46937        function checkGrammarBreakOrContinueStatement(node: BreakOrContinueStatement): boolean {
46938            let current: Node = node;
46939            while (current) {
46940                if (isFunctionLikeOrClassStaticBlockDeclaration(current)) {
46941                    return grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary);
46942                }
46943
46944                switch (current.kind) {
46945                    case SyntaxKind.LabeledStatement:
46946                        if (node.label && (current as LabeledStatement).label.escapedText === node.label.escapedText) {
46947                            // found matching label - verify that label usage is correct
46948                            // continue can only target labels that are on iteration statements
46949                            const isMisplacedContinueLabel = node.kind === SyntaxKind.ContinueStatement
46950                                && !isIterationStatement((current as LabeledStatement).statement, /*lookInLabeledStatement*/ true);
46951
46952                            if (isMisplacedContinueLabel) {
46953                                return grammarErrorOnNode(node, Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement);
46954                            }
46955
46956                            return false;
46957                        }
46958                        break;
46959                    case SyntaxKind.SwitchStatement:
46960                        if (node.kind === SyntaxKind.BreakStatement && !node.label) {
46961                            // unlabeled break within switch statement - ok
46962                            return false;
46963                        }
46964                        break;
46965                    default:
46966                        if (isIterationStatement(current, /*lookInLabeledStatement*/ false) && !node.label) {
46967                            // unlabeled break or continue within iteration statement - ok
46968                            return false;
46969                        }
46970                        break;
46971                }
46972
46973                current = current.parent;
46974            }
46975
46976            if (node.label) {
46977                const message = node.kind === SyntaxKind.BreakStatement
46978                    ? Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement
46979                    : Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement;
46980
46981                return grammarErrorOnNode(node, message);
46982            }
46983            else {
46984                const message = node.kind === SyntaxKind.BreakStatement
46985                    ? Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement
46986                    : Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement;
46987                return grammarErrorOnNode(node, message);
46988            }
46989        }
46990
46991        function checkGrammarBindingElement(node: BindingElement) {
46992            if (node.dotDotDotToken) {
46993                const elements = node.parent.elements;
46994                if (node !== last(elements)) {
46995                    return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern);
46996                }
46997                checkGrammarForDisallowedTrailingComma(elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma);
46998
46999                if (node.propertyName) {
47000                    return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_have_a_property_name);
47001                }
47002            }
47003
47004            if (node.dotDotDotToken && node.initializer) {
47005                // Error on equals token which immediately precedes the initializer
47006                return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
47007            }
47008        }
47009
47010        function isStringOrNumberLiteralExpression(expr: Expression) {
47011            return isStringOrNumericLiteralLike(expr) ||
47012                expr.kind === SyntaxKind.PrefixUnaryExpression && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken &&
47013                (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.NumericLiteral;
47014        }
47015
47016        function isBigIntLiteralExpression(expr: Expression) {
47017            return expr.kind === SyntaxKind.BigIntLiteral ||
47018                expr.kind === SyntaxKind.PrefixUnaryExpression && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken &&
47019                (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.BigIntLiteral;
47020        }
47021
47022        function isSimpleLiteralEnumReference(expr: Expression) {
47023            if ((isPropertyAccessExpression(expr) || (isElementAccessExpression(expr) && isStringOrNumberLiteralExpression(expr.argumentExpression))) &&
47024                isEntityNameExpression(expr.expression)) {
47025                return !!(checkExpressionCached(expr).flags & TypeFlags.EnumLiteral);
47026            }
47027        }
47028
47029        function checkAmbientInitializer(node: VariableDeclaration | PropertyDeclaration | PropertySignature) {
47030            const initializer = node.initializer;
47031            if (initializer) {
47032                const isInvalidInitializer = !(
47033                    isStringOrNumberLiteralExpression(initializer) ||
47034                    isSimpleLiteralEnumReference(initializer) ||
47035                    initializer.kind === SyntaxKind.TrueKeyword || initializer.kind === SyntaxKind.FalseKeyword ||
47036                    isBigIntLiteralExpression(initializer)
47037                );
47038                const isConstOrReadonly = isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node);
47039                if (isConstOrReadonly && !node.type) {
47040                    if (isInvalidInitializer) {
47041                        return grammarErrorOnNode(initializer, Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_or_literal_enum_reference);
47042                    }
47043                }
47044                else {
47045                    return grammarErrorOnNode(initializer, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
47046                }
47047            }
47048        }
47049
47050        function checkGrammarVariableDeclaration(node: VariableDeclaration) {
47051            if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) {
47052                if (node.flags & NodeFlags.Ambient) {
47053                    checkAmbientInitializer(node);
47054                }
47055                else if (!node.initializer) {
47056                    if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) {
47057                        return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer);
47058                    }
47059                    if (isVarConst(node)) {
47060                        return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
47061                    }
47062                }
47063            }
47064
47065            if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) {
47066                const message = node.initializer
47067                    ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions
47068                    : !node.type
47069                        ? Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations
47070                        : Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context;
47071                return grammarErrorOnNode(node.exclamationToken, message);
47072            }
47073
47074            if ((moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && moduleKind !== ModuleKind.System &&
47075                !(node.parent.parent.flags & NodeFlags.Ambient) && hasSyntacticModifier(node.parent.parent, ModifierFlags.Export)) {
47076                checkESModuleMarker(node.name);
47077            }
47078
47079            const checkLetConstNames = (isLet(node) || isVarConst(node));
47080
47081            // 1. LexicalDeclaration : LetOrConst BindingList ;
47082            // It is a Syntax Error if the BoundNames of BindingList contains "let".
47083            // 2. ForDeclaration: ForDeclaration : LetOrConst ForBinding
47084            // It is a Syntax Error if the BoundNames of ForDeclaration contains "let".
47085
47086            // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
47087            // and its Identifier is eval or arguments
47088            return checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name);
47089        }
47090
47091        function checkESModuleMarker(name: Identifier | BindingPattern): boolean {
47092            if (name.kind === SyntaxKind.Identifier) {
47093                if (idText(name) === "__esModule") {
47094                    return grammarErrorOnNodeSkippedOn("noEmit", name, Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules);
47095                }
47096            }
47097            else {
47098                const elements = name.elements;
47099                for (const element of elements) {
47100                    if (!isOmittedExpression(element)) {
47101                        return checkESModuleMarker(element.name);
47102                    }
47103                }
47104            }
47105            return false;
47106        }
47107
47108        function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
47109            if (name.kind === SyntaxKind.Identifier) {
47110                if (name.originalKeywordKind === SyntaxKind.LetKeyword) {
47111                    return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
47112                }
47113            }
47114            else {
47115                const elements = name.elements;
47116                for (const element of elements) {
47117                    if (!isOmittedExpression(element)) {
47118                        checkGrammarNameInLetOrConstDeclarations(element.name);
47119                    }
47120                }
47121            }
47122            return false;
47123        }
47124
47125        function checkGrammarVariableDeclarationList(declarationList: VariableDeclarationList): boolean {
47126            const declarations = declarationList.declarations;
47127            if (checkGrammarForDisallowedTrailingComma(declarationList.declarations)) {
47128                return true;
47129            }
47130
47131            if (!declarationList.declarations.length) {
47132                return grammarErrorAtPos(declarationList, declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty);
47133            }
47134            return false;
47135        }
47136
47137        function allowLetAndConstDeclarations(parent: Node): boolean {
47138            switch (parent.kind) {
47139                case SyntaxKind.IfStatement:
47140                case SyntaxKind.DoStatement:
47141                case SyntaxKind.WhileStatement:
47142                case SyntaxKind.WithStatement:
47143                case SyntaxKind.ForStatement:
47144                case SyntaxKind.ForInStatement:
47145                case SyntaxKind.ForOfStatement:
47146                    return false;
47147                case SyntaxKind.LabeledStatement:
47148                    return allowLetAndConstDeclarations(parent.parent);
47149            }
47150
47151            return true;
47152        }
47153
47154        function checkGrammarForDisallowedLetOrConstStatement(node: VariableStatement) {
47155            if (!allowLetAndConstDeclarations(node.parent)) {
47156                if (isLet(node.declarationList)) {
47157                    return grammarErrorOnNode(node, Diagnostics.let_declarations_can_only_be_declared_inside_a_block);
47158                }
47159                else if (isVarConst(node.declarationList)) {
47160                    return grammarErrorOnNode(node, Diagnostics.const_declarations_can_only_be_declared_inside_a_block);
47161                }
47162            }
47163        }
47164
47165        function checkGrammarMetaProperty(node: MetaProperty) {
47166            const escapedText = node.name.escapedText;
47167            switch (node.keywordToken) {
47168                case SyntaxKind.NewKeyword:
47169                    if (escapedText !== "target") {
47170                        return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "target");
47171                    }
47172                    break;
47173                case SyntaxKind.ImportKeyword:
47174                    if (escapedText !== "meta") {
47175                        return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "meta");
47176                    }
47177                    break;
47178            }
47179        }
47180
47181        function hasParseDiagnostics(sourceFile: SourceFile): boolean {
47182            return sourceFile.parseDiagnostics.length > 0;
47183        }
47184
47185        function grammarErrorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
47186            const sourceFile = getSourceFileOfNode(node);
47187            if (!hasParseDiagnostics(sourceFile)) {
47188                const span = getSpanOfTokenAtPosition(sourceFile, node.pos);
47189                diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2));
47190                return true;
47191            }
47192            return false;
47193        }
47194
47195        function grammarErrorAtPos(nodeForSourceFile: Node, start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
47196            const sourceFile = getSourceFileOfNode(nodeForSourceFile);
47197            if (!hasParseDiagnostics(sourceFile)) {
47198                diagnostics.add(createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2));
47199                return true;
47200            }
47201            return false;
47202        }
47203
47204        function grammarErrorOnNodeSkippedOn(key: keyof CompilerOptions, node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
47205            const sourceFile = getSourceFileOfNode(node);
47206            if (!hasParseDiagnostics(sourceFile)) {
47207                errorSkippedOn(key, node, message, arg0, arg1, arg2);
47208                return true;
47209            }
47210            return false;
47211        }
47212
47213        function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
47214            const sourceFile = getSourceFileOfNode(node);
47215            if (!hasParseDiagnostics(sourceFile)) {
47216                diagnostics.add(createDiagnosticForNode(node, message, arg0, arg1, arg2));
47217                return true;
47218            }
47219            return false;
47220        }
47221
47222        function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) {
47223            const jsdocTypeParameters = isInJSFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined;
47224            const range = node.typeParameters || jsdocTypeParameters && firstOrUndefined(jsdocTypeParameters);
47225            if (range) {
47226                const pos = range.pos === range.end ? range.pos : skipTrivia(getSourceFileOfNode(node).text, range.pos);
47227                return grammarErrorAtPos(node, pos, range.end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration);
47228            }
47229        }
47230
47231        function checkGrammarConstructorTypeAnnotation(node: ConstructorDeclaration) {
47232            const type = node.type || getEffectiveReturnTypeNode(node);
47233            if (type) {
47234                return grammarErrorOnNode(type, Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration);
47235            }
47236        }
47237
47238        function checkGrammarProperty(node: PropertyDeclaration | PropertySignature) {
47239            if (isComputedPropertyName(node.name) && isBinaryExpression(node.name.expression) && node.name.expression.operatorToken.kind === SyntaxKind.InKeyword) {
47240                return grammarErrorOnNode(
47241                    (node.parent as ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode).members[0],
47242                    Diagnostics.A_mapped_type_may_not_declare_properties_or_methods);
47243            }
47244            if (isClassLike(node.parent)) {
47245                if (isStringLiteral(node.name) && node.name.text === "constructor") {
47246                    return grammarErrorOnNode(node.name, Diagnostics.Classes_may_not_have_a_field_named_constructor);
47247                }
47248                if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_have_a_simple_literal_type_or_a_unique_symbol_type)) {
47249                    return true;
47250                }
47251                if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) {
47252                    return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher);
47253                }
47254                if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node)) {
47255                    return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher);
47256                }
47257                if (isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_accessor_property_cannot_be_declared_optional)) {
47258                    return true;
47259                }
47260            }
47261            else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) {
47262                if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) {
47263                    return true;
47264                }
47265
47266                // Interfaces cannot contain property declarations
47267                Debug.assertNode(node, isPropertySignature);
47268                if (node.initializer) {
47269                    return grammarErrorOnNode(node.initializer, Diagnostics.An_interface_property_cannot_have_an_initializer);
47270                }
47271            }
47272            else if (isTypeLiteralNode(node.parent)) {
47273                if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) {
47274                    return true;
47275                }
47276                // Type literals cannot contain property declarations
47277                Debug.assertNode(node, isPropertySignature);
47278                if (node.initializer) {
47279                    return grammarErrorOnNode(node.initializer, Diagnostics.A_type_literal_property_cannot_have_an_initializer);
47280                }
47281            }
47282
47283            if (node.flags & NodeFlags.Ambient) {
47284                checkAmbientInitializer(node);
47285            }
47286
47287            if (isPropertyDeclaration(node) && node.exclamationToken && (!isClassLike(node.parent) || !node.type || node.initializer ||
47288                node.flags & NodeFlags.Ambient || isStatic(node) || hasAbstractModifier(node))) {
47289                const message = node.initializer
47290                    ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions
47291                    : !node.type
47292                        ? Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations
47293                        : Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context;
47294                return grammarErrorOnNode(node.exclamationToken, message);
47295            }
47296        }
47297
47298        function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
47299            // A declare modifier is required for any top level .d.ts declaration except export=, export default, export as namespace
47300            // interfaces and imports categories:
47301            //
47302            //  DeclarationElement:
47303            //     ExportAssignment
47304            //     export_opt   InterfaceDeclaration
47305            //     export_opt   TypeAliasDeclaration
47306            //     export_opt   ImportDeclaration
47307            //     export_opt   ExternalImportDeclaration
47308            //     export_opt   AmbientDeclaration
47309            //
47310            // TODO: The spec needs to be amended to reflect this grammar.
47311            if (node.kind === SyntaxKind.InterfaceDeclaration ||
47312                node.kind === SyntaxKind.TypeAliasDeclaration ||
47313                node.kind === SyntaxKind.ImportDeclaration ||
47314                node.kind === SyntaxKind.ImportEqualsDeclaration ||
47315                node.kind === SyntaxKind.ExportDeclaration ||
47316                node.kind === SyntaxKind.ExportAssignment ||
47317                node.kind === SyntaxKind.NamespaceExportDeclaration ||
47318                hasSyntacticModifier(node, ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) {
47319                return false;
47320            }
47321
47322            return grammarErrorOnFirstToken(node, Diagnostics.Top_level_declarations_in_d_ts_files_must_start_with_either_a_declare_or_export_modifier);
47323        }
47324
47325        function checkGrammarTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean {
47326            for (const decl of file.statements) {
47327                if (isDeclaration(decl) || decl.kind === SyntaxKind.VariableStatement) {
47328                    if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) {
47329                        return true;
47330                    }
47331                }
47332            }
47333            return false;
47334        }
47335
47336        function checkGrammarSourceFile(node: SourceFile): boolean {
47337            return !!(node.flags & NodeFlags.Ambient) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node);
47338        }
47339
47340        function checkGrammarStatementInAmbientContext(node: Node): boolean {
47341            if (node.flags & NodeFlags.Ambient) {
47342                // Find containing block which is either Block, ModuleBlock, SourceFile
47343                const links = getNodeLinks(node);
47344                if (!links.hasReportedStatementInAmbientContext && (isFunctionLike(node.parent) || isAccessor(node.parent))) {
47345                    return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
47346                }
47347
47348                // We are either parented by another statement, or some sort of block.
47349                // If we're in a block, we only want to really report an error once
47350                // to prevent noisiness.  So use a bit on the block to indicate if
47351                // this has already been reported, and don't report if it has.
47352                //
47353                if (node.parent.kind === SyntaxKind.Block || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
47354                    const links = getNodeLinks(node.parent);
47355                    // Check if the containing block ever report this error
47356                    if (!links.hasReportedStatementInAmbientContext) {
47357                        return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
47358                    }
47359                }
47360                else {
47361                    // We must be parented by a statement.  If so, there's no need
47362                    // to report the error as our parent will have already done it.
47363                    // Debug.assert(isStatement(node.parent));
47364                }
47365            }
47366            return false;
47367        }
47368
47369        function checkGrammarNumericLiteral(node: NumericLiteral): boolean {
47370            // Grammar checking
47371            if (node.numericLiteralFlags & TokenFlags.Octal) {
47372                let diagnosticMessage: DiagnosticMessage | undefined;
47373                if (languageVersion >= ScriptTarget.ES5) {
47374                    diagnosticMessage = Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0;
47375                }
47376                else if (isChildOfNodeWithKind(node, SyntaxKind.LiteralType)) {
47377                    diagnosticMessage = Diagnostics.Octal_literal_types_must_use_ES2015_syntax_Use_the_syntax_0;
47378                }
47379                else if (isChildOfNodeWithKind(node, SyntaxKind.EnumMember)) {
47380                    diagnosticMessage = Diagnostics.Octal_literals_are_not_allowed_in_enums_members_initializer_Use_the_syntax_0;
47381                }
47382                if (diagnosticMessage) {
47383                    const withMinus = isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.MinusToken;
47384                    const literal = (withMinus ? "-" : "") + "0o" + node.text;
47385                    return grammarErrorOnNode(withMinus ? node.parent : node, diagnosticMessage, literal);
47386                }
47387            }
47388
47389            // Realism (size) checking
47390            checkNumericLiteralValueSize(node);
47391
47392            return false;
47393        }
47394
47395        function checkNumericLiteralValueSize(node: NumericLiteral) {
47396            // We should test against `getTextOfNode(node)` rather than `node.text`, because `node.text` for large numeric literals can contain "."
47397            // e.g. `node.text` for numeric literal `1100000000000000000000` is `1.1e21`.
47398            const isFractional = getTextOfNode(node).indexOf(".") !== -1;
47399            const isScientific = node.numericLiteralFlags & TokenFlags.Scientific;
47400
47401            // Scientific notation (e.g. 2e54 and 1e00000000010) can't be converted to bigint
47402            // Fractional numbers (e.g. 9000000000000000.001) are inherently imprecise anyway
47403            if (isFractional || isScientific) {
47404                return;
47405            }
47406
47407            // Here `node` is guaranteed to be a numeric literal representing an integer.
47408            // We need to judge whether the integer `node` represents is <= 2 ** 53 - 1, which can be accomplished by comparing to `value` defined below because:
47409            // 1) when `node` represents an integer <= 2 ** 53 - 1, `node.text` is its exact string representation and thus `value` precisely represents the integer.
47410            // 2) otherwise, although `node.text` may be imprecise string representation, its mathematical value and consequently `value` cannot be less than 2 ** 53,
47411            //    thus the result of the predicate won't be affected.
47412            const value = +node.text;
47413            if (value <= 2 ** 53 - 1) {
47414                return;
47415            }
47416
47417            addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers));
47418        }
47419
47420        function checkGrammarBigIntLiteral(node: BigIntLiteral): boolean {
47421            const literalType = isLiteralTypeNode(node.parent) ||
47422                isPrefixUnaryExpression(node.parent) && isLiteralTypeNode(node.parent.parent);
47423            if (!literalType) {
47424                if (languageVersion < ScriptTarget.ES2020) {
47425                    if (grammarErrorOnNode(node, Diagnostics.BigInt_literals_are_not_available_when_targeting_lower_than_ES2020)) {
47426                        return true;
47427                    }
47428                }
47429            }
47430            return false;
47431        }
47432
47433        function grammarErrorAfterFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean {
47434            const sourceFile = getSourceFileOfNode(node);
47435            if (!hasParseDiagnostics(sourceFile)) {
47436                const span = getSpanOfTokenAtPosition(sourceFile, node.pos);
47437                diagnostics.add(createFileDiagnostic(sourceFile, textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2));
47438                return true;
47439            }
47440            return false;
47441        }
47442
47443        function getAmbientModules(): Symbol[] {
47444            if (!ambientModulesCache) {
47445                ambientModulesCache = [];
47446                globals.forEach((global, sym) => {
47447                    // No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module.
47448                    if (ambientModuleSymbolRegex.test(sym as string)) {
47449                        ambientModulesCache!.push(global);
47450                    }
47451                });
47452            }
47453            return ambientModulesCache;
47454        }
47455
47456        function checkGrammarImportClause(node: ImportClause): boolean {
47457            if (node.isTypeOnly && node.name && node.namedBindings) {
47458                return grammarErrorOnNode(node, Diagnostics.A_type_only_import_can_specify_a_default_import_or_named_bindings_but_not_both);
47459            }
47460            if (node.isTypeOnly && node.namedBindings?.kind === SyntaxKind.NamedImports) {
47461                return checkGrammarNamedImportsOrExports(node.namedBindings);
47462            }
47463            return false;
47464        }
47465
47466        function checkGrammarNamedImportsOrExports(namedBindings: NamedImportsOrExports): boolean {
47467            return !!forEach<ImportSpecifier | ExportSpecifier, boolean>(namedBindings.elements, specifier => {
47468                if (specifier.isTypeOnly) {
47469                    return grammarErrorOnFirstToken(
47470                        specifier,
47471                        specifier.kind === SyntaxKind.ImportSpecifier
47472                            ? Diagnostics.The_type_modifier_cannot_be_used_on_a_named_import_when_import_type_is_used_on_its_import_statement
47473                            : Diagnostics.The_type_modifier_cannot_be_used_on_a_named_export_when_export_type_is_used_on_its_export_statement);
47474                }
47475            });
47476        }
47477
47478        function checkGrammarImportCallExpression(node: ImportCall): boolean {
47479            if (moduleKind === ModuleKind.ES2015) {
47480                return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_or_nodenext);
47481            }
47482
47483            if (node.typeArguments) {
47484                return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments);
47485            }
47486
47487            const nodeArguments = node.arguments;
47488            if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext && moduleKind !== ModuleKind.Node16) {
47489                // We are allowed trailing comma after proposal-import-assertions.
47490                checkGrammarForDisallowedTrailingComma(nodeArguments);
47491
47492                if (nodeArguments.length > 1) {
47493                    const assertionArgument = nodeArguments[1];
47494                    return grammarErrorOnNode(assertionArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext);
47495                }
47496            }
47497
47498            if (nodeArguments.length === 0 || nodeArguments.length > 2) {
47499                return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments);
47500            }
47501
47502            // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
47503            // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
47504            const spreadElement = find(nodeArguments, isSpreadElement);
47505            if (spreadElement) {
47506                return grammarErrorOnNode(spreadElement, Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element);
47507            }
47508            return false;
47509        }
47510
47511        function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) {
47512            const sourceObjectFlags = getObjectFlags(source);
47513            if (sourceObjectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) {
47514                return find(unionTarget.types, target => {
47515                    if (target.flags & TypeFlags.Object) {
47516                        const overlapObjFlags = sourceObjectFlags & getObjectFlags(target);
47517                        if (overlapObjFlags & ObjectFlags.Reference) {
47518                            return (source as TypeReference).target === (target as TypeReference).target;
47519                        }
47520                        if (overlapObjFlags & ObjectFlags.Anonymous) {
47521                            return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol;
47522                        }
47523                    }
47524                    return false;
47525                });
47526            }
47527        }
47528
47529        function findBestTypeForObjectLiteral(source: Type, unionTarget: UnionOrIntersectionType) {
47530            if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && someType(unionTarget, isArrayLikeType)) {
47531                return find(unionTarget.types, t => !isArrayLikeType(t));
47532            }
47533        }
47534
47535        function findBestTypeForInvokable(source: Type, unionTarget: UnionOrIntersectionType) {
47536            let signatureKind = SignatureKind.Call;
47537            const hasSignatures = getSignaturesOfType(source, signatureKind).length > 0 ||
47538                (signatureKind = SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0);
47539            if (hasSignatures) {
47540                return find(unionTarget.types, t => getSignaturesOfType(t, signatureKind).length > 0);
47541            }
47542        }
47543
47544        function findMostOverlappyType(source: Type, unionTarget: UnionOrIntersectionType) {
47545            let bestMatch: Type | undefined;
47546            if (!(source.flags & (TypeFlags.Primitive | TypeFlags.InstantiablePrimitive))) {
47547                let matchingCount = 0;
47548                for (const target of unionTarget.types) {
47549                    if (!(target.flags & (TypeFlags.Primitive | TypeFlags.InstantiablePrimitive))) {
47550                        const overlap = getIntersectionType([getIndexType(source), getIndexType(target)]);
47551                        if (overlap.flags & TypeFlags.Index) {
47552                            // perfect overlap of keys
47553                            return target;
47554                        }
47555                        else if (isUnitType(overlap) || overlap.flags & TypeFlags.Union) {
47556                            // We only want to account for literal types otherwise.
47557                            // If we have a union of index types, it seems likely that we
47558                            // needed to elaborate between two generic mapped types anyway.
47559                            const len = overlap.flags & TypeFlags.Union ? countWhere((overlap as UnionType).types, isUnitType) : 1;
47560                            if (len >= matchingCount) {
47561                                bestMatch = target;
47562                                matchingCount = len;
47563                            }
47564                        }
47565                    }
47566                }
47567            }
47568            return bestMatch;
47569        }
47570
47571        function filterPrimitivesIfContainsNonPrimitive(type: UnionType) {
47572            if (maybeTypeOfKind(type, TypeFlags.NonPrimitive)) {
47573                const result = filterType(type, t => !(t.flags & TypeFlags.Primitive));
47574                if (!(result.flags & TypeFlags.Never)) {
47575                    return result;
47576                }
47577            }
47578            return type;
47579        }
47580
47581        // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
47582        function findMatchingDiscriminantType(source: Type, target: Type, isRelatedTo: (source: Type, target: Type) => Ternary, skipPartial?: boolean) {
47583            if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) {
47584                const match = getMatchingUnionConstituentForType(target as UnionType, source);
47585                if (match) {
47586                    return match;
47587                }
47588                const sourceProperties = getPropertiesOfType(source);
47589                if (sourceProperties) {
47590                    const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target);
47591                    if (sourcePropertiesFiltered) {
47592                        return discriminateTypeByDiscriminableItems(target as UnionType, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo, /*defaultValue*/ undefined, skipPartial);
47593                    }
47594                }
47595            }
47596            return undefined;
47597        }
47598    }
47599
47600    function isNotAccessor(declaration: Declaration): boolean {
47601        // Accessors check for their own matching duplicates, and in contexts where they are valid, there are already duplicate identifier checks
47602        return !isAccessor(declaration);
47603    }
47604
47605    function isNotOverload(declaration: Declaration): boolean {
47606        return (declaration.kind !== SyntaxKind.FunctionDeclaration && declaration.kind !== SyntaxKind.MethodDeclaration) ||
47607                !!(declaration as FunctionDeclaration).body;
47608    }
47609
47610    /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */
47611    function isDeclarationNameOrImportPropertyName(name: Node): boolean {
47612        switch (name.parent.kind) {
47613            case SyntaxKind.ImportSpecifier:
47614            case SyntaxKind.ExportSpecifier:
47615                return isIdentifier(name);
47616            default:
47617                return isDeclarationName(name);
47618        }
47619    }
47620
47621    namespace JsxNames {
47622        export const JSX = "JSX" as __String;
47623        export const IntrinsicElements = "IntrinsicElements" as __String;
47624        export const ElementClass = "ElementClass" as __String;
47625        export const ElementAttributesPropertyNameContainer = "ElementAttributesProperty" as __String; // TODO: Deprecate and remove support
47626        export const ElementChildrenAttributeNameContainer = "ElementChildrenAttribute" as __String;
47627        export const Element = "Element" as __String;
47628        export const IntrinsicAttributes = "IntrinsicAttributes" as __String;
47629        export const IntrinsicClassAttributes = "IntrinsicClassAttributes" as __String;
47630        export const LibraryManagedAttributes = "LibraryManagedAttributes" as __String;
47631    }
47632
47633    function getIterationTypesKeyFromIterationTypeKind(typeKind: IterationTypeKind) {
47634        switch (typeKind) {
47635            case IterationTypeKind.Yield: return "yieldType";
47636            case IterationTypeKind.Return: return "returnType";
47637            case IterationTypeKind.Next: return "nextType";
47638        }
47639    }
47640
47641    export function signatureHasRestParameter(s: Signature) {
47642        return !!(s.flags & SignatureFlags.HasRestParameter);
47643    }
47644
47645    export function signatureHasLiteralTypes(s: Signature) {
47646        return !!(s.flags & SignatureFlags.HasLiteralTypes);
47647    }
47648}
47649