(symbol, location)
| 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(); |
no test coverage detected