From 92badaf0efa808211a1997e2eb9ac1605b8eefe1 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 10 Jan 2019 12:55:41 -0800 Subject: [PATCH] Allow nonnull assertions in references --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 11 + .../reference/nonNullReferenceMatching.js | 54 ++++ .../nonNullReferenceMatching.symbols | 193 +++++++++++++ .../reference/nonNullReferenceMatching.types | 262 ++++++++++++++++++ .../compiler/nonNullReferenceMatching.ts | 34 +++ 6 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/nonNullReferenceMatching.js create mode 100644 tests/baselines/reference/nonNullReferenceMatching.symbols create mode 100644 tests/baselines/reference/nonNullReferenceMatching.types create mode 100644 tests/cases/compiler/nonNullReferenceMatching.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7216af4e8172e..f0e172618108b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -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); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7d369317b7e84..9930eded50e72 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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((node).expression); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: const propName = getAccessedPropertyName(node); @@ -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(source) === getResolvedSymbol(target) || @@ -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) && diff --git a/tests/baselines/reference/nonNullReferenceMatching.js b/tests/baselines/reference/nonNullReferenceMatching.js new file mode 100644 index 0000000000000..abb0d5a96db30 --- /dev/null +++ b/tests/baselines/reference/nonNullReferenceMatching.js @@ -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; +}()); diff --git a/tests/baselines/reference/nonNullReferenceMatching.symbols b/tests/baselines/reference/nonNullReferenceMatching.symbols new file mode 100644 index 0000000000000..ee9c608cea498 --- /dev/null +++ b/tests/baselines/reference/nonNullReferenceMatching.symbols @@ -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)) + + }; +} diff --git a/tests/baselines/reference/nonNullReferenceMatching.types b/tests/baselines/reference/nonNullReferenceMatching.types new file mode 100644 index 0000000000000..03ef70177c07f --- /dev/null +++ b/tests/baselines/reference/nonNullReferenceMatching.types @@ -0,0 +1,262 @@ +=== tests/cases/compiler/nonNullReferenceMatching.ts === +type ElementRef = (element: HTMLElement | null) => void; +>ElementRef : ElementRef +>element : HTMLElement | null +>null : null + +type ThumbProps = { +>ThumbProps : ThumbProps + + elementRef?: ElementRef; +>elementRef : ElementRef | undefined +} + +type ComponentProps = { +>ComponentProps : ComponentProps + + thumbYProps?: ThumbProps; +>thumbYProps : ThumbProps | undefined + + thumbXProps: ThumbProps; +>thumbXProps : ThumbProps +} + +class Component { +>Component : Component + + props!: ComponentProps; +>props : ComponentProps + + public thumbYElementRef = (ref: HTMLElement | null) => { +>thumbYElementRef : (ref: HTMLElement | null) => void +>(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); } : (ref: HTMLElement | null) => void +>ref : HTMLElement | null +>null : null + + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof this.props.thumbYProps!.elementRef === 'function' : boolean +>typeof this.props.thumbYProps!.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbYProps!.elementRef : ElementRef | undefined +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef +>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) : false | void +>typeof (this.props.thumbYProps!.elementRef) === 'function' : boolean +>typeof (this.props.thumbYProps!.elementRef) : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>(this.props.thumbYProps!.elementRef) : ElementRef | undefined +>this.props.thumbYProps!.elementRef : ElementRef | undefined +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef +>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) : false | void +>typeof ((this.props).thumbYProps!.elementRef)! === 'function' : boolean +>typeof ((this.props).thumbYProps!.elementRef)! : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>((this.props).thumbYProps!.elementRef)! : ElementRef +>((this.props).thumbYProps!.elementRef) : ElementRef | undefined +>(this.props).thumbYProps!.elementRef : ElementRef | undefined +>(this.props).thumbYProps! : ThumbProps +>(this.props).thumbYProps : ThumbProps | undefined +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbXProps.elementRef(ref) : void +>this.props.thumbXProps.elementRef : ElementRef +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>(this.props).thumbXProps.elementRef(ref) : void +>(this.props).thumbXProps.elementRef : ElementRef +>(this.props).thumbXProps : ThumbProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>(this.props.thumbXProps).elementRef(ref) : void +>(this.props.thumbXProps).elementRef : ElementRef +>(this.props.thumbXProps) : ThumbProps +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>((this.props)!.thumbXProps)!.elementRef(ref) : void +>((this.props)!.thumbXProps)!.elementRef : ElementRef +>((this.props)!.thumbXProps)! : ThumbProps +>((this.props)!.thumbXProps) : ThumbProps +>(this.props)!.thumbXProps : ThumbProps +>(this.props)! : ComponentProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref) : false | void +>typeof (this.props.thumbXProps).elementRef === 'function' : boolean +>typeof (this.props.thumbXProps).elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>(this.props.thumbXProps).elementRef : ElementRef | undefined +>(this.props.thumbXProps) : ThumbProps +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>((this.props)!.thumbXProps)!.elementRef(ref) : void +>((this.props)!.thumbXProps)!.elementRef : ElementRef +>((this.props)!.thumbXProps)! : ThumbProps +>((this.props)!.thumbXProps) : ThumbProps +>(this.props)!.thumbXProps : ThumbProps +>(this.props)! : ComponentProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref) : false | void +>typeof this.props!.thumbXProps!.elementRef === 'function' : boolean +>typeof this.props!.thumbXProps!.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props!.thumbXProps!.elementRef : ElementRef | undefined +>this.props!.thumbXProps! : ThumbProps +>this.props!.thumbXProps : ThumbProps +>this.props! : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>((this.props)!.thumbXProps)!.elementRef(ref) : void +>((this.props)!.thumbXProps)!.elementRef : ElementRef +>((this.props)!.thumbXProps)! : ThumbProps +>((this.props)!.thumbXProps) : ThumbProps +>(this.props)!.thumbXProps : ThumbProps +>(this.props)! : ComponentProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + }; +} diff --git a/tests/cases/compiler/nonNullReferenceMatching.ts b/tests/cases/compiler/nonNullReferenceMatching.ts new file mode 100644 index 0000000000000..1295c3ce9a7f7 --- /dev/null +++ b/tests/cases/compiler/nonNullReferenceMatching.ts @@ -0,0 +1,34 @@ +// @strict: true +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); + }; +} \ No newline at end of file