Skip to content
Open
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
4 changes: 2 additions & 2 deletions tsc/internal/checker/flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,7 @@ func (c *Checker) reportFlowControlError(node *ast.Node) {

func (c *Checker) isMatchingReference(source *ast.Node, target *ast.Node) bool {
switch target.Kind {
case ast.KindParenthesizedExpression, ast.KindNonNullExpression:
case ast.KindParenthesizedExpression, ast.KindNonNullExpression, ast.KindSatisfiesExpression:
return c.isMatchingReference(source, target.Expression())
case ast.KindBinaryExpression:
return ast.IsAssignmentExpression(target, false) && c.isMatchingReference(source, target.AsBinaryExpression().Left) ||
Expand Down Expand Up @@ -1851,7 +1851,7 @@ func (c *Checker) containsMatchingReference(source *ast.Node, target *ast.Node)
func (c *Checker) optionalChainContainsReference(source *ast.Node, target *ast.Node) bool {
for ast.IsOptionalChain(source) {
source = source.Expression()
if c.isMatchingReference(source, target) {
if c.isMatchingReference(target, source) {
return true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,9 @@ narrowByEquality.ts(55,9): error TS2322: Type 'string | number' is not assignabl
xUnknown;
}

declare let option: { type: string } | undefined;

if ((option satisfies { type: string } | undefined) !== undefined) {
option.type;
}

8 changes: 8 additions & 0 deletions tsc/testdata/baselines/reference/compiler/narrowByEquality.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ if (xUnknown != null) {
xUnknown;
}

declare let option: { type: string } | undefined;

if ((option satisfies { type: string } | undefined) !== undefined) {
option.type;
}


//// [narrowByEquality.js]
Expand Down Expand Up @@ -129,3 +134,6 @@ if (xUnknown != null) {
else {
xUnknown;
}
if (option !== undefined) {
option.type;
}
14 changes: 14 additions & 0 deletions tsc/testdata/baselines/reference/compiler/narrowByEquality.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,18 @@ if (xUnknown != null) {
>xUnknown : Symbol(xUnknown, Decl(narrowByEquality.ts, 4, 11))
}

declare let option: { type: string } | undefined;
>option : Symbol(option, Decl(narrowByEquality.ts, 72, 11))
>type : Symbol(type, Decl(narrowByEquality.ts, 72, 21))

if ((option satisfies { type: string } | undefined) !== undefined) {
>option : Symbol(option, Decl(narrowByEquality.ts, 72, 11))
>type : Symbol(type, Decl(narrowByEquality.ts, 74, 23))
>undefined : Symbol(undefined)

option.type;
>option.type : Symbol(type, Decl(narrowByEquality.ts, 72, 21))
>option : Symbol(option, Decl(narrowByEquality.ts, 72, 11))
>type : Symbol(type, Decl(narrowByEquality.ts, 72, 21))
}

17 changes: 17 additions & 0 deletions tsc/testdata/baselines/reference/compiler/narrowByEquality.types
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,21 @@ if (xUnknown != null) {
>xUnknown : null | undefined
}

declare let option: { type: string } | undefined;
>option : { type: string; } | undefined
>type : string

if ((option satisfies { type: string } | undefined) !== undefined) {
>(option satisfies { type: string } | undefined) !== undefined : boolean
>(option satisfies { type: string } | undefined) : { type: string; } | undefined
>option satisfies { type: string } | undefined : { type: string; } | undefined
>option : { type: string; } | undefined
>type : string
>undefined : undefined

option.type;
>option.type : string
>option : { type: string; }
>type : string
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
controlFlowOptionalChain4.ts(54,9): error TS18048: 'option' is possibly 'undefined'.
controlFlowOptionalChain4.ts(62,9): error TS18048: 'option' is possibly 'undefined'.
controlFlowOptionalChain4.ts(70,9): error TS18048: 'option' is possibly 'undefined'.


==== controlFlowOptionalChain4.ts (3 errors) ====
// https://github.com/microsoft/TypeScript/issues/56998

type Type = {
id: number;
};

type InferenceInfo = {
typeParameter: Type;
impliedArity?: number;
};

declare function getInferenceInfoForType(type: Type): InferenceInfo | undefined;

function fn1(t1: Type, t2: Type) {
let info = getInferenceInfoForType(t1);
if (info?.impliedArity !== undefined) {
info.impliedArity;
}
else if ((info = getInferenceInfoForType(t2))?.impliedArity !== undefined) {
info.impliedArity;
}
}

function fn2(t1: Type, t2: Type) {
let info = getInferenceInfoForType(t1);
if (info?.impliedArity !== undefined) {
info.impliedArity;
}
else if ((info = getInferenceInfoForType(t2))?.impliedArity) {
info.impliedArity;
}
}

// https://github.com/microsoft/TypeScript/issues/60855

type Option = { type: "Some"; value: number; } | { type: "None"; };

declare function someOptionalOption(): Option | undefined;

function test60855(): number | undefined {
let option: Option | undefined;

if ((option = someOptionalOption())?.type === "Some") {
return option.value;
}

return undefined;
}

function testEqualityWithUndefined() {
let option: Option | undefined;

if ((option = someOptionalOption())?.type === undefined) {
option.type;
~~~~~~
!!! error TS18048: 'option' is possibly 'undefined'.
}
}

function testNegativeEquality() {
let option: Option | undefined;

if ((option = someOptionalOption())?.type !== "Some") {
option.type;
~~~~~~
!!! error TS18048: 'option' is possibly 'undefined'.
}
}

function testFalsyBranch() {
let option: Option | undefined;

if (!(option = someOptionalOption())?.type) {
option.type;
~~~~~~
!!! error TS18048: 'option' is possibly 'undefined'.
}
}

function testAssignmentWithSatisfies() {
let option: Option | undefined;

if ((option = someOptionalOption() satisfies Option | undefined)?.type === "Some") {
option.value;
}
}

Loading