Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ namespace ts {

function isNarrowableReference(expr: Expression): boolean {
return expr.kind === SyntaxKind.Identifier || expr.kind === SyntaxKind.ThisKeyword || expr.kind === SyntaxKind.SuperKeyword ||
isPropertyAccessExpression(expr) && isNarrowableReference(expr.expression) ||
(isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) ||
isElementAccessExpression(expr) && expr.argumentExpression &&
(isStringLiteral(expr.argumentExpression) || isNumericLiteral(expr.argumentExpression)) &&
isNarrowableReference(expr.expression);
Expand Down
11 changes: 11 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14771,6 +14771,9 @@ namespace ts {
return symbol !== unknownSymbol ? (isConstraintPosition(node) ? "@" : "") + getSymbolId(symbol) : undefined;
case SyntaxKind.ThisKeyword:
return "0";
case SyntaxKind.NonNullExpression:
case SyntaxKind.ParenthesizedExpression:
return getFlowCacheKey((<NonNullExpression | ParenthesizedExpression>node).expression);
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
const propName = getAccessedPropertyName(<AccessExpression>node);
Expand All @@ -14783,6 +14786,11 @@ namespace ts {
}

function isMatchingReference(source: Node, target: Node): boolean {
switch (target.kind) {
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.NonNullExpression:
return isMatchingReference(source, (target as NonNullExpression | ParenthesizedExpression).expression);
}
switch (source.kind) {
case SyntaxKind.Identifier:
return target.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>source) === getResolvedSymbol(<Identifier>target) ||
Expand All @@ -14792,6 +14800,9 @@ namespace ts {
return target.kind === SyntaxKind.ThisKeyword;
case SyntaxKind.SuperKeyword:
return target.kind === SyntaxKind.SuperKeyword;
case SyntaxKind.NonNullExpression:
case SyntaxKind.ParenthesizedExpression:
return isMatchingReference((source as NonNullExpression | ParenthesizedExpression).expression, target);
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
return isAccessExpression(target) &&
Expand Down
54 changes: 54 additions & 0 deletions tests/baselines/reference/nonNullReferenceMatching.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//// [nonNullReferenceMatching.ts]
type ElementRef = (element: HTMLElement | null) => void;

type ThumbProps = {
elementRef?: ElementRef;
}

type ComponentProps = {
thumbYProps?: ThumbProps;
thumbXProps: ThumbProps;
}

class Component {
props!: ComponentProps;
public thumbYElementRef = (ref: HTMLElement | null) => {
typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref);

typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref);

typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref);

typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref);

typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref);

typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref);

typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref);

typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref);

typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref);
};
}

//// [nonNullReferenceMatching.js]
"use strict";
var Component = /** @class */ (function () {
function Component() {
var _this = this;
this.thumbYElementRef = function (ref) {
typeof _this.props.thumbYProps.elementRef === 'function' && _this.props.thumbYProps.elementRef(ref);
typeof (_this.props.thumbYProps.elementRef) === 'function' && _this.props.thumbYProps.elementRef(ref);
typeof ((_this.props).thumbYProps.elementRef) === 'function' && _this.props.thumbYProps.elementRef(ref);
typeof _this.props.thumbXProps.elementRef === 'function' && _this.props.thumbXProps.elementRef(ref);
typeof _this.props.thumbXProps.elementRef === 'function' && (_this.props).thumbXProps.elementRef(ref);
typeof _this.props.thumbXProps.elementRef === 'function' && (_this.props.thumbXProps).elementRef(ref);
typeof _this.props.thumbXProps.elementRef === 'function' && ((_this.props).thumbXProps).elementRef(ref);
typeof (_this.props.thumbXProps).elementRef === 'function' && ((_this.props).thumbXProps).elementRef(ref);
typeof _this.props.thumbXProps.elementRef === 'function' && ((_this.props).thumbXProps).elementRef(ref);
};
}
return Component;
}());
193 changes: 193 additions & 0 deletions tests/baselines/reference/nonNullReferenceMatching.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
=== tests/cases/compiler/nonNullReferenceMatching.ts ===
type ElementRef = (element: HTMLElement | null) => void;
>ElementRef : Symbol(ElementRef, Decl(nonNullReferenceMatching.ts, 0, 0))
>element : Symbol(element, Decl(nonNullReferenceMatching.ts, 0, 19))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

type ThumbProps = {
>ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56))

elementRef?: ElementRef;
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ElementRef : Symbol(ElementRef, Decl(nonNullReferenceMatching.ts, 0, 0))
}

type ComponentProps = {
>ComponentProps : Symbol(ComponentProps, Decl(nonNullReferenceMatching.ts, 4, 1))

thumbYProps?: ThumbProps;
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56))

thumbXProps: ThumbProps;
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56))
}

class Component {
>Component : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))

props!: ComponentProps;
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>ComponentProps : Symbol(ComponentProps, Decl(nonNullReferenceMatching.ts, 4, 1))

public thumbYElementRef = (ref: HTMLElement | null) => {
>thumbYElementRef : Symbol(Component.thumbYElementRef, Decl(nonNullReferenceMatching.ts, 12, 27))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))
>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref);
>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref);
>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref);
>(this.props).thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props).thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref);
>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref);
>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props).thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props).thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref);
>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props.thumbXProps).elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref);
>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref);
>(this.props.thumbXProps).elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref);
>this.props!.thumbXProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>this.props!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1))
>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17))
>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29))
>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19))
>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31))

};
}
Loading