MCPcopy Index your code
hub / github.com/nodejs/node / getNarrowedTypeOfSymbol

Function getNarrowedTypeOfSymbol

test/fixtures/snapshot/typescript.js:71561–71642  ·  view source on GitHub ↗
(symbol, location)

Source from the content-addressed store, hash-verified

71559 }
71560 }
71561 function getNarrowedTypeOfSymbol(symbol, location) {
71562 var declaration = symbol.valueDeclaration;
71563 if (declaration) {
71564 // If we have a non-rest binding element with no initializer declared as a const variable or a const-like
71565 // parameter (a parameter for which there are no assignments in the function body), and if the parent type
71566 // for the destructuring is a union type, one or more of the binding elements may represent discriminant
71567 // properties, and we want the effects of conditional checks on such discriminants to affect the types of
71568 // other binding elements from the same destructuring. Consider:
71569 //
71570 // type Action =
71571 // | { kind: 'A', payload: number }
71572 // | { kind: 'B', payload: string };
71573 //
71574 // function f({ kind, payload }: Action) {
71575 // if (kind === 'A') {
71576 // payload.toFixed();
71577 // }
71578 // if (kind === 'B') {
71579 // payload.toUpperCase();
71580 // }
71581 // }
71582 //
71583 // Above, we want the conditional checks on 'kind' to affect the type of 'payload'. To facilitate this, we use
71584 // the binding pattern AST instance for '{ kind, payload }' as a pseudo-reference and narrow this reference
71585 // as if it occurred in the specified location. We then recompute the narrowed binding element type by
71586 // destructuring from the narrowed parent type.
71587 if (ts.isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) {
71588 var parent = declaration.parent.parent;
71589 if (parent.kind === 254 /* SyntaxKind.VariableDeclaration */ && ts.getCombinedNodeFlags(declaration) & 2 /* NodeFlags.Const */ || parent.kind === 164 /* SyntaxKind.Parameter */) {
71590 var links = getNodeLinks(parent);
71591 if (!(links.flags & 268435456 /* NodeCheckFlags.InCheckIdentifier */)) {
71592 links.flags |= 268435456 /* NodeCheckFlags.InCheckIdentifier */;
71593 var parentType = getTypeForBindingElementParent(parent, 0 /* CheckMode.Normal */);
71594 links.flags &= ~268435456 /* NodeCheckFlags.InCheckIdentifier */;
71595 if (parentType && parentType.flags & 1048576 /* TypeFlags.Union */ && !(parent.kind === 164 /* SyntaxKind.Parameter */ && isSymbolAssigned(symbol))) {
71596 var pattern = declaration.parent;
71597 var narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode);
71598 if (narrowedType.flags & 131072 /* TypeFlags.Never */) {
71599 return neverType;
71600 }
71601 return getBindingElementTypeFromParentType(declaration, narrowedType);
71602 }
71603 }
71604 }
71605 }
71606 // If we have a const-like parameter with no type annotation or initializer, and if the parameter is contextually
71607 // typed by a signature with a single rest parameter of a union of tuple types, one or more of the parameters may
71608 // represent discriminant tuple elements, and we want the effects of conditional checks on such discriminants to
71609 // affect the types of other parameters in the same parameter list. Consider:
71610 //
71611 // type Action = [kind: 'A', payload: number] | [kind: 'B', payload: string];
71612 //
71613 // const f: (...args: Action) => void = (kind, payload) => {
71614 // if (kind === 'A') {
71615 // payload.toFixed();
71616 // }
71617 // if (kind === 'B') {
71618 // payload.toUpperCase();

Callers 1

checkIdentifierFunction · 0.85

Calls 14

getNodeLinksFunction · 0.85
isSymbolAssignedFunction · 0.85
getFlowTypeOfReferenceFunction · 0.85
getContextualSignatureFunction · 0.85
getReducedApparentTypeFunction · 0.85
getTypeOfSymbolFunction · 0.85
everyTypeFunction · 0.85
getIndexedAccessTypeFunction · 0.85

Tested by

no test coverage detected