diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80b61edd3657a..543939c0bdba7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27275,7 +27275,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function optionalChainContainsReference(source: Node, target: Node) { while (isOptionalChain(source)) { source = source.expression; - if (isMatchingReference(source, target)) { + if (isMatchingReference(target, source)) { return true; } } diff --git a/tests/baselines/reference/controlFlowOptionalChain4.symbols b/tests/baselines/reference/controlFlowOptionalChain4.symbols new file mode 100644 index 0000000000000..0cfa04823a44a --- /dev/null +++ b/tests/baselines/reference/controlFlowOptionalChain4.symbols @@ -0,0 +1,141 @@ +//// [tests/cases/conformance/controlFlow/controlFlowOptionalChain4.ts] //// + +=== controlFlowOptionalChain4.ts === +// https://github.com/microsoft/TypeScript/issues/56998 + +type Type = { +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) + + id: number; +>id : Symbol(id, Decl(controlFlowOptionalChain4.ts, 2, 13)) + +}; + +type InferenceInfo = { +>InferenceInfo : Symbol(InferenceInfo, Decl(controlFlowOptionalChain4.ts, 4, 2)) + + typeParameter: Type; +>typeParameter : Symbol(typeParameter, Decl(controlFlowOptionalChain4.ts, 6, 22)) +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) + + impliedArity?: number; +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) + +}; + +declare function getInferenceInfoForType(type: Type): InferenceInfo | undefined; +>getInferenceInfoForType : Symbol(getInferenceInfoForType, Decl(controlFlowOptionalChain4.ts, 9, 2)) +>type : Symbol(type, Decl(controlFlowOptionalChain4.ts, 11, 41)) +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) +>InferenceInfo : Symbol(InferenceInfo, Decl(controlFlowOptionalChain4.ts, 4, 2)) + +function fn1(t1: Type, t2: Type) { +>fn1 : Symbol(fn1, Decl(controlFlowOptionalChain4.ts, 11, 80)) +>t1 : Symbol(t1, Decl(controlFlowOptionalChain4.ts, 13, 13)) +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) +>t2 : Symbol(t2, Decl(controlFlowOptionalChain4.ts, 13, 22)) +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) + + let info = getInferenceInfoForType(t1); +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 14, 5)) +>getInferenceInfoForType : Symbol(getInferenceInfoForType, Decl(controlFlowOptionalChain4.ts, 9, 2)) +>t1 : Symbol(t1, Decl(controlFlowOptionalChain4.ts, 13, 13)) + + if (info?.impliedArity !== undefined) { +>info?.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 14, 5)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>undefined : Symbol(undefined) + + info.impliedArity; +>info.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 14, 5)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) + + } else if ((info = getInferenceInfoForType(t2))?.impliedArity !== undefined) { +>(info = getInferenceInfoForType(t2))?.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 14, 5)) +>getInferenceInfoForType : Symbol(getInferenceInfoForType, Decl(controlFlowOptionalChain4.ts, 9, 2)) +>t2 : Symbol(t2, Decl(controlFlowOptionalChain4.ts, 13, 22)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>undefined : Symbol(undefined) + + info.impliedArity; +>info.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 14, 5)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) + } +} + +function fn2(t1: Type, t2: Type) { +>fn2 : Symbol(fn2, Decl(controlFlowOptionalChain4.ts, 20, 1)) +>t1 : Symbol(t1, Decl(controlFlowOptionalChain4.ts, 22, 13)) +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) +>t2 : Symbol(t2, Decl(controlFlowOptionalChain4.ts, 22, 22)) +>Type : Symbol(Type, Decl(controlFlowOptionalChain4.ts, 0, 0)) + + let info = getInferenceInfoForType(t1); +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 23, 5)) +>getInferenceInfoForType : Symbol(getInferenceInfoForType, Decl(controlFlowOptionalChain4.ts, 9, 2)) +>t1 : Symbol(t1, Decl(controlFlowOptionalChain4.ts, 22, 13)) + + if (info?.impliedArity !== undefined) { +>info?.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 23, 5)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>undefined : Symbol(undefined) + + info.impliedArity; +>info.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 23, 5)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) + + } else if ((info = getInferenceInfoForType(t2))?.impliedArity) { +>(info = getInferenceInfoForType(t2))?.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 23, 5)) +>getInferenceInfoForType : Symbol(getInferenceInfoForType, Decl(controlFlowOptionalChain4.ts, 9, 2)) +>t2 : Symbol(t2, Decl(controlFlowOptionalChain4.ts, 22, 22)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) + + info.impliedArity; +>info.impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) +>info : Symbol(info, Decl(controlFlowOptionalChain4.ts, 23, 5)) +>impliedArity : Symbol(impliedArity, Decl(controlFlowOptionalChain4.ts, 7, 22)) + } +} + +// https://github.com/microsoft/TypeScript/issues/60855 + +type Option = { type: "Some"; value: number } | { type: "None" }; +>Option : Symbol(Option, Decl(lib.dom.d.ts, --, --), Decl(controlFlowOptionalChain4.ts, 29, 1)) +>type : Symbol(type, Decl(controlFlowOptionalChain4.ts, 33, 15)) +>value : Symbol(value, Decl(controlFlowOptionalChain4.ts, 33, 29)) +>type : Symbol(type, Decl(controlFlowOptionalChain4.ts, 33, 49)) + +declare function someOptionalOption(): Option | undefined; +>someOptionalOption : Symbol(someOptionalOption, Decl(controlFlowOptionalChain4.ts, 33, 65)) +>Option : Symbol(Option, Decl(lib.dom.d.ts, --, --), Decl(controlFlowOptionalChain4.ts, 29, 1)) + +function test60855(): number | undefined { +>test60855 : Symbol(test60855, Decl(controlFlowOptionalChain4.ts, 35, 58)) + + let option: Option | undefined; +>option : Symbol(option, Decl(controlFlowOptionalChain4.ts, 38, 5)) +>Option : Symbol(Option, Decl(lib.dom.d.ts, --, --), Decl(controlFlowOptionalChain4.ts, 29, 1)) + + if ((option = someOptionalOption())?.type === "Some") { +>(option = someOptionalOption())?.type : Symbol(type, Decl(controlFlowOptionalChain4.ts, 33, 15), Decl(controlFlowOptionalChain4.ts, 33, 49)) +>option : Symbol(option, Decl(controlFlowOptionalChain4.ts, 38, 5)) +>someOptionalOption : Symbol(someOptionalOption, Decl(controlFlowOptionalChain4.ts, 33, 65)) +>type : Symbol(type, Decl(controlFlowOptionalChain4.ts, 33, 15), Decl(controlFlowOptionalChain4.ts, 33, 49)) + + return option.value; +>option.value : Symbol(value, Decl(controlFlowOptionalChain4.ts, 33, 29)) +>option : Symbol(option, Decl(controlFlowOptionalChain4.ts, 38, 5)) +>value : Symbol(value, Decl(controlFlowOptionalChain4.ts, 33, 29)) + } + + return undefined; +>undefined : Symbol(undefined) +} + diff --git a/tests/baselines/reference/controlFlowOptionalChain4.types b/tests/baselines/reference/controlFlowOptionalChain4.types new file mode 100644 index 0000000000000..bda29da9b6907 --- /dev/null +++ b/tests/baselines/reference/controlFlowOptionalChain4.types @@ -0,0 +1,229 @@ +//// [tests/cases/conformance/controlFlow/controlFlowOptionalChain4.ts] //// + +=== controlFlowOptionalChain4.ts === +// https://github.com/microsoft/TypeScript/issues/56998 + +type Type = { +>Type : Type +> : ^^^^ + + id: number; +>id : number +> : ^^^^^^ + +}; + +type InferenceInfo = { +>InferenceInfo : InferenceInfo +> : ^^^^^^^^^^^^^ + + typeParameter: Type; +>typeParameter : Type +> : ^^^^ + + impliedArity?: number; +>impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + +}; + +declare function getInferenceInfoForType(type: Type): InferenceInfo | undefined; +>getInferenceInfoForType : (type: Type) => InferenceInfo | undefined +> : ^ ^^ ^^^^^ +>type : Type +> : ^^^^ + +function fn1(t1: Type, t2: Type) { +>fn1 : (t1: Type, t2: Type) => void +> : ^ ^^ ^^ ^^ ^^^^^^^^^ +>t1 : Type +> : ^^^^ +>t2 : Type +> : ^^^^ + + let info = getInferenceInfoForType(t1); +>info : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType(t1) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType : (type: Type) => InferenceInfo | undefined +> : ^ ^^ ^^^^^ +>t1 : Type +> : ^^^^ + + if (info?.impliedArity !== undefined) { +>info?.impliedArity !== undefined : boolean +> : ^^^^^^^ +>info?.impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>info : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + info.impliedArity; +>info.impliedArity : number +> : ^^^^^^ +>info : InferenceInfo +> : ^^^^^^^^^^^^^ +>impliedArity : number +> : ^^^^^^ + + } else if ((info = getInferenceInfoForType(t2))?.impliedArity !== undefined) { +>(info = getInferenceInfoForType(t2))?.impliedArity !== undefined : boolean +> : ^^^^^^^ +>(info = getInferenceInfoForType(t2))?.impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>(info = getInferenceInfoForType(t2)) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>info = getInferenceInfoForType(t2) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>info : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType(t2) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType : (type: Type) => InferenceInfo | undefined +> : ^ ^^ ^^^^^ +>t2 : Type +> : ^^^^ +>impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + info.impliedArity; +>info.impliedArity : number +> : ^^^^^^ +>info : InferenceInfo +> : ^^^^^^^^^^^^^ +>impliedArity : number +> : ^^^^^^ + } +} + +function fn2(t1: Type, t2: Type) { +>fn2 : (t1: Type, t2: Type) => void +> : ^ ^^ ^^ ^^ ^^^^^^^^^ +>t1 : Type +> : ^^^^ +>t2 : Type +> : ^^^^ + + let info = getInferenceInfoForType(t1); +>info : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType(t1) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType : (type: Type) => InferenceInfo | undefined +> : ^ ^^ ^^^^^ +>t1 : Type +> : ^^^^ + + if (info?.impliedArity !== undefined) { +>info?.impliedArity !== undefined : boolean +> : ^^^^^^^ +>info?.impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>info : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + info.impliedArity; +>info.impliedArity : number +> : ^^^^^^ +>info : InferenceInfo +> : ^^^^^^^^^^^^^ +>impliedArity : number +> : ^^^^^^ + + } else if ((info = getInferenceInfoForType(t2))?.impliedArity) { +>(info = getInferenceInfoForType(t2))?.impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>(info = getInferenceInfoForType(t2)) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>info = getInferenceInfoForType(t2) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>info : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType(t2) : InferenceInfo | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +>getInferenceInfoForType : (type: Type) => InferenceInfo | undefined +> : ^ ^^ ^^^^^ +>t2 : Type +> : ^^^^ +>impliedArity : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + + info.impliedArity; +>info.impliedArity : number +> : ^^^^^^ +>info : InferenceInfo +> : ^^^^^^^^^^^^^ +>impliedArity : number +> : ^^^^^^ + } +} + +// https://github.com/microsoft/TypeScript/issues/60855 + +type Option = { type: "Some"; value: number } | { type: "None" }; +>Option : Option +> : ^^^^^^ +>type : "Some" +> : ^^^^^^ +>value : number +> : ^^^^^^ +>type : "None" +> : ^^^^^^ + +declare function someOptionalOption(): Option | undefined; +>someOptionalOption : () => Option | undefined +> : ^^^^^^ + +function test60855(): number | undefined { +>test60855 : () => number | undefined +> : ^^^^^^ + + let option: Option | undefined; +>option : Option | undefined +> : ^^^^^^^^^^^^^^^^^^ + + if ((option = someOptionalOption())?.type === "Some") { +>(option = someOptionalOption())?.type === "Some" : boolean +> : ^^^^^^^ +>(option = someOptionalOption())?.type : "Some" | "None" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(option = someOptionalOption()) : Option | undefined +> : ^^^^^^^^^^^^^^^^^^ +>option = someOptionalOption() : Option | undefined +> : ^^^^^^^^^^^^^^^^^^ +>option : Option | undefined +> : ^^^^^^^^^^^^^^^^^^ +>someOptionalOption() : Option | undefined +> : ^^^^^^^^^^^^^^^^^^ +>someOptionalOption : () => Option | undefined +> : ^^^^^^ +>type : "Some" | "None" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"Some" : "Some" +> : ^^^^^^ + + return option.value; +>option.value : number +> : ^^^^^^ +>option : { type: "Some"; value: number; } +> : ^^^^^^^^ ^^^^^^^^^ ^^^ +>value : number +> : ^^^^^^ + } + + return undefined; +>undefined : undefined +> : ^^^^^^^^^ +} + diff --git a/tests/cases/conformance/controlFlow/controlFlowOptionalChain4.ts b/tests/cases/conformance/controlFlow/controlFlowOptionalChain4.ts new file mode 100644 index 0000000000000..612beafc9d164 --- /dev/null +++ b/tests/cases/conformance/controlFlow/controlFlowOptionalChain4.ts @@ -0,0 +1,49 @@ +// @strict: true +// @noEmit: true + +// 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; +}