diff --git a/tests/baselines/reference/controlFlowGenericTypes.errors.txt b/tests/baselines/reference/controlFlowGenericTypes.errors.txt index 27141a5898c..f78e67823d8 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.errors.txt +++ b/tests/baselines/reference/controlFlowGenericTypes.errors.txt @@ -5,10 +5,12 @@ controlFlowGenericTypes.ts(81,11): error TS2339: Property 'foo' does not exist o controlFlowGenericTypes.ts(90,44): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. controlFlowGenericTypes.ts(91,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'. Property 'foo' does not exist on type 'AA'. -controlFlowGenericTypes.ts(168,9): error TS2536: Type 'keyof PublicSpec' cannot be used to index type 'InternalSpec'. +controlFlowGenericTypes.ts(176,16): error TS18049: 'obj' is possibly 'null' or 'undefined'. +controlFlowGenericTypes.ts(182,16): error TS18049: 'obj' is possibly 'null' or 'undefined'. +controlFlowGenericTypes.ts(195,9): error TS2536: Type 'keyof PublicSpec' cannot be used to index type 'InternalSpec'. -==== controlFlowGenericTypes.ts (6 errors) ==== +==== controlFlowGenericTypes.ts (8 errors) ==== function f1(x: T, y: { a: T }, z: [T]): string { if (x) { x; @@ -161,23 +163,54 @@ controlFlowGenericTypes.ts(168,9): error TS2536: Type 'keyof PublicSpec' cannot emittingObject.off(eventName as typeof eventName, 0); } - // In an element access obj[x], we consider obj to be in a constraint position, except when obj is of - // a generic type without a nullable constraint and x is a generic type. This is because when both obj - // and x are of generic types T and K, we want the resulting type to be T[K]. + // In an element access obj[key], we consider obj to be in a constraint position, except when + // obj and key both have generic types. When obj and key are of generic types T and K, we want + // the resulting type to be T[K]. function fx1(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx2, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx4(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx5(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx6(obj: T | null | undefined, key: K) { + const x1 = obj[key]; // Error + ~~~ +!!! error TS18049: 'obj' is possibly 'null' or 'undefined'. + const x2 = obj && obj[key]; + const x3 = obj?.[key]; + } + + function fx7(obj: { x: T } | null | undefined, key: K) { + const x1 = obj.x[key]; // Error + ~~~ +!!! error TS18049: 'obj' is possibly 'null' or 'undefined'. + const x2 = obj && obj.x[key]; + const x3 = obj?.x[key]; } // Repro from #44166 diff --git a/tests/baselines/reference/controlFlowGenericTypes.js b/tests/baselines/reference/controlFlowGenericTypes.js index 60af0a54ebd..4236bf88bf9 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.js +++ b/tests/baselines/reference/controlFlowGenericTypes.js @@ -141,23 +141,50 @@ function once>(emittingObject: T, eventName: keyo emittingObject.off(eventName as typeof eventName, 0); } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx2, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx4(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx5(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx6(obj: T | null | undefined, key: K) { + const x1 = obj[key]; // Error + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx7(obj: { x: T } | null | undefined, key: K) { + const x1 = obj.x[key]; // Error + const x2 = obj && obj.x[key]; + const x3 = obj?.x[key]; } // Repro from #44166 @@ -327,20 +354,43 @@ function once(emittingObject, eventName) { emittingObject.off(eventName, 0); emittingObject.off(eventName, 0); } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj, key) { var x1 = obj[key]; var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; } function fx2(obj, key) { var x1 = obj[key]; var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; } function fx3(obj, key) { var x1 = obj[key]; var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx4(obj, key) { + var x1 = obj[key]; + var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx5(obj, key) { + var x1 = obj[key]; + var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx6(obj, key) { + var x1 = obj[key]; // Error + var x2 = obj && obj[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj[key]; +} +function fx7(obj, key) { + var x1 = obj.x[key]; // Error + var x2 = obj && obj.x[key]; + var x3 = obj === null || obj === void 0 ? void 0 : obj.x[key]; } // Repro from #44166 var TableBaseEnum = /** @class */ (function () { diff --git a/tests/baselines/reference/controlFlowGenericTypes.symbols b/tests/baselines/reference/controlFlowGenericTypes.symbols index 4c8edd62076..136b21aef62 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.symbols +++ b/tests/baselines/reference/controlFlowGenericTypes.symbols @@ -407,9 +407,9 @@ function once>(emittingObject: T, eventName: keyo >eventName : Symbol(eventName, Decl(controlFlowGenericTypes.ts, 135, 64)) } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { >fx1 : Symbol(fx1, Decl(controlFlowGenericTypes.ts, 138, 1)) @@ -430,227 +430,357 @@ function fx1(obj: T, key: K) { >x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 146, 9)) >obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 144, 35)) >obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 144, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 144, 42)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 147, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 144, 35)) >key : Symbol(key, Decl(controlFlowGenericTypes.ts, 144, 42)) } function fx2, K extends keyof T>(obj: T, key: K) { ->fx2 : Symbol(fx2, Decl(controlFlowGenericTypes.ts, 147, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) +>fx2 : Symbol(fx2, Decl(controlFlowGenericTypes.ts, 148, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 149, 47)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 149, 13)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 149, 74)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 149, 47)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 150, 47)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 150, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 150, 47)) const x1 = obj[key]; ->x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 150, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 149, 74)) +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 151, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) const x2 = obj && obj[key]; ->x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 151, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 149, 67)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 149, 74)) +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 152, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 153, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 150, 67)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 150, 74)) } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { ->fx3 : Symbol(fx3, Decl(controlFlowGenericTypes.ts, 152, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) +>fx3 : Symbol(fx3, Decl(controlFlowGenericTypes.ts, 154, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 154, 59)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 154, 13)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 154, 86)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 154, 59)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 156, 59)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 156, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 156, 59)) const x1 = obj[key]; ->x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 155, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 154, 86)) +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 157, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) const x2 = obj && obj[key]; ->x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 156, 9)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 154, 79)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 154, 86)) +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 158, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 159, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 156, 79)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 156, 86)) +} + +function fx4(obj: T, key: K) { +>fx4 : Symbol(fx4, Decl(controlFlowGenericTypes.ts, 160, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 162, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 162, 31)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 162, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 162, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 162, 31)) + + const x1 = obj[key]; +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 163, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) + + const x2 = obj && obj[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 164, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 165, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 162, 51)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 162, 58)) +} + +function fx5(obj: T, key: K) { +>fx5 : Symbol(fx5, Decl(controlFlowGenericTypes.ts, 166, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 168, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 168, 45)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 168, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 168, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 168, 45)) + + const x1 = obj[key]; +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 169, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) + + const x2 = obj && obj[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 170, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 171, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 168, 65)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 168, 72)) +} + +function fx6(obj: T | null | undefined, key: K) { +>fx6 : Symbol(fx6, Decl(controlFlowGenericTypes.ts, 172, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 174, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 174, 15)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 174, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 174, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 174, 15)) + + const x1 = obj[key]; // Error +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 175, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) + + const x2 = obj && obj[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 176, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) + + const x3 = obj?.[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 177, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 174, 35)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 174, 61)) +} + +function fx7(obj: { x: T } | null | undefined, key: K) { +>fx7 : Symbol(fx7, Decl(controlFlowGenericTypes.ts, 178, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 180, 13)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 180, 15)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 180, 13)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 180, 13)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 180, 15)) + + const x1 = obj.x[key]; // Error +>x1 : Symbol(x1, Decl(controlFlowGenericTypes.ts, 181, 9)) +>obj.x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) + + const x2 = obj && obj.x[key]; +>x2 : Symbol(x2, Decl(controlFlowGenericTypes.ts, 182, 9)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>obj.x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) + + const x3 = obj?.x[key]; +>x3 : Symbol(x3, Decl(controlFlowGenericTypes.ts, 183, 9)) +>obj?.x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>obj : Symbol(obj, Decl(controlFlowGenericTypes.ts, 180, 35)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 180, 41)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 180, 68)) } // Repro from #44166 class TableBaseEnum< ->TableBaseEnum : Symbol(TableBaseEnum, Decl(controlFlowGenericTypes.ts, 157, 1)) +>TableBaseEnum : Symbol(TableBaseEnum, Decl(controlFlowGenericTypes.ts, 184, 1)) PublicSpec extends Record, ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) InternalSpec extends Record | undefined = undefined> { ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) m() { ->m : Symbol(TableBaseEnum.m, Decl(controlFlowGenericTypes.ts, 163, 82)) +>m : Symbol(TableBaseEnum.m, Decl(controlFlowGenericTypes.ts, 190, 82)) let iSpec = null! as InternalSpec; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) iSpec[null! as keyof InternalSpec]; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) iSpec[null! as keyof PublicSpec]; // Error ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) if (iSpec === undefined) { ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) >undefined : Symbol(undefined) return; } iSpec[null! as keyof InternalSpec]; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 162, 55)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>InternalSpec : Symbol(InternalSpec, Decl(controlFlowGenericTypes.ts, 189, 55)) iSpec[null! as keyof PublicSpec]; ->iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 165, 11)) ->PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 161, 20)) +>iSpec : Symbol(iSpec, Decl(controlFlowGenericTypes.ts, 192, 11)) +>PublicSpec : Symbol(PublicSpec, Decl(controlFlowGenericTypes.ts, 188, 20)) } } // Repros from #45145 function f10(x: T, y: Partial) { ->f10 : Symbol(f10, Decl(controlFlowGenericTypes.ts, 174, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 178, 13)) ->a : Symbol(a, Decl(controlFlowGenericTypes.ts, 178, 24)) ->x : Symbol(x, Decl(controlFlowGenericTypes.ts, 178, 50)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 178, 13)) ->y : Symbol(y, Decl(controlFlowGenericTypes.ts, 178, 55)) +>f10 : Symbol(f10, Decl(controlFlowGenericTypes.ts, 201, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 205, 13)) +>a : Symbol(a, Decl(controlFlowGenericTypes.ts, 205, 24)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 205, 50)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 205, 13)) +>y : Symbol(y, Decl(controlFlowGenericTypes.ts, 205, 55)) >Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 178, 13)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 205, 13)) y = x; ->y : Symbol(y, Decl(controlFlowGenericTypes.ts, 178, 55)) ->x : Symbol(x, Decl(controlFlowGenericTypes.ts, 178, 50)) +>y : Symbol(y, Decl(controlFlowGenericTypes.ts, 205, 55)) +>x : Symbol(x, Decl(controlFlowGenericTypes.ts, 205, 50)) } type SqlInsertSet = T extends undefined ? object : { [P in keyof T]: unknown }; ->SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 180, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 182, 18)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 182, 18)) ->P : Symbol(P, Decl(controlFlowGenericTypes.ts, 182, 57)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 182, 18)) +>SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 207, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 209, 18)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 209, 18)) +>P : Symbol(P, Decl(controlFlowGenericTypes.ts, 209, 57)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 209, 18)) class SqlTable { ->SqlTable : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 182, 82)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 184, 15)) +>SqlTable : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 209, 82)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 211, 15)) protected validateRow(_row: Partial>): void { ->validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 184, 19)) ->_row : Symbol(_row, Decl(controlFlowGenericTypes.ts, 185, 26)) +>validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 211, 19)) +>_row : Symbol(_row, Decl(controlFlowGenericTypes.ts, 212, 26)) >Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) ->SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 180, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 184, 15)) +>SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 207, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 211, 15)) } public insertRow(row: SqlInsertSet) { ->insertRow : Symbol(SqlTable.insertRow, Decl(controlFlowGenericTypes.ts, 186, 5)) ->row : Symbol(row, Decl(controlFlowGenericTypes.ts, 187, 21)) ->SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 180, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 184, 15)) +>insertRow : Symbol(SqlTable.insertRow, Decl(controlFlowGenericTypes.ts, 213, 5)) +>row : Symbol(row, Decl(controlFlowGenericTypes.ts, 214, 21)) +>SqlInsertSet : Symbol(SqlInsertSet, Decl(controlFlowGenericTypes.ts, 207, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 211, 15)) this.validateRow(row); ->this.validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 184, 19)) ->this : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 182, 82)) ->validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 184, 19)) ->row : Symbol(row, Decl(controlFlowGenericTypes.ts, 187, 21)) +>this.validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 211, 19)) +>this : Symbol(SqlTable, Decl(controlFlowGenericTypes.ts, 209, 82)) +>validateRow : Symbol(SqlTable.validateRow, Decl(controlFlowGenericTypes.ts, 211, 19)) +>row : Symbol(row, Decl(controlFlowGenericTypes.ts, 214, 21)) } } // Repro from #46495 interface Button { ->Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 190, 1)) +>Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 217, 1)) type: "button"; ->type : Symbol(Button.type, Decl(controlFlowGenericTypes.ts, 194, 18)) +>type : Symbol(Button.type, Decl(controlFlowGenericTypes.ts, 221, 18)) text: string; ->text : Symbol(Button.text, Decl(controlFlowGenericTypes.ts, 195, 19)) +>text : Symbol(Button.text, Decl(controlFlowGenericTypes.ts, 222, 19)) } interface Checkbox { ->Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 197, 1)) +>Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 224, 1)) type: "checkbox"; ->type : Symbol(Checkbox.type, Decl(controlFlowGenericTypes.ts, 199, 20)) +>type : Symbol(Checkbox.type, Decl(controlFlowGenericTypes.ts, 226, 20)) isChecked: boolean; ->isChecked : Symbol(Checkbox.isChecked, Decl(controlFlowGenericTypes.ts, 200, 21)) +>isChecked : Symbol(Checkbox.isChecked, Decl(controlFlowGenericTypes.ts, 227, 21)) } type Control = Button | Checkbox; ->Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 202, 1)) ->Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 190, 1)) ->Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 197, 1)) +>Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 229, 1)) +>Button : Symbol(Button, Decl(controlFlowGenericTypes.ts, 217, 1)) +>Checkbox : Symbol(Checkbox, Decl(controlFlowGenericTypes.ts, 224, 1)) function update(control : T | undefined, key: K, value: T[K]): void { ->update : Symbol(update, Decl(controlFlowGenericTypes.ts, 204, 33)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 202, 1)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 206, 34)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->control : Symbol(control, Decl(controlFlowGenericTypes.ts, 206, 54)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 206, 78)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 206, 34)) ->value : Symbol(value, Decl(controlFlowGenericTypes.ts, 206, 86)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 206, 16)) ->K : Symbol(K, Decl(controlFlowGenericTypes.ts, 206, 34)) +>update : Symbol(update, Decl(controlFlowGenericTypes.ts, 231, 33)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>Control : Symbol(Control, Decl(controlFlowGenericTypes.ts, 229, 1)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 233, 34)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>control : Symbol(control, Decl(controlFlowGenericTypes.ts, 233, 54)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 233, 78)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 233, 34)) +>value : Symbol(value, Decl(controlFlowGenericTypes.ts, 233, 86)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 233, 16)) +>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 233, 34)) if (control !== undefined) { ->control : Symbol(control, Decl(controlFlowGenericTypes.ts, 206, 54)) +>control : Symbol(control, Decl(controlFlowGenericTypes.ts, 233, 54)) >undefined : Symbol(undefined) control[key] = value; ->control : Symbol(control, Decl(controlFlowGenericTypes.ts, 206, 54)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 206, 78)) ->value : Symbol(value, Decl(controlFlowGenericTypes.ts, 206, 86)) +>control : Symbol(control, Decl(controlFlowGenericTypes.ts, 233, 54)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 233, 78)) +>value : Symbol(value, Decl(controlFlowGenericTypes.ts, 233, 86)) } } // Repro from #50465 type Column = (keyof T extends never ? { id?: number | string } : { id: T }) & { title?: string; } ->Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 210, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 214, 12)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 214, 12)) ->id : Symbol(id, Decl(controlFlowGenericTypes.ts, 214, 43)) ->id : Symbol(id, Decl(controlFlowGenericTypes.ts, 214, 70)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 214, 12)) ->title : Symbol(title, Decl(controlFlowGenericTypes.ts, 214, 83)) +>Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 237, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 241, 12)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 241, 12)) +>id : Symbol(id, Decl(controlFlowGenericTypes.ts, 241, 43)) +>id : Symbol(id, Decl(controlFlowGenericTypes.ts, 241, 70)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 241, 12)) +>title : Symbol(title, Decl(controlFlowGenericTypes.ts, 241, 83)) function getColumnProperty(column: Column, key: keyof Column) { ->getColumnProperty : Symbol(getColumnProperty, Decl(controlFlowGenericTypes.ts, 214, 101)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 216, 27)) ->column : Symbol(column, Decl(controlFlowGenericTypes.ts, 216, 30)) ->Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 210, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 216, 27)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 216, 48)) ->Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 210, 1)) ->T : Symbol(T, Decl(controlFlowGenericTypes.ts, 216, 27)) +>getColumnProperty : Symbol(getColumnProperty, Decl(controlFlowGenericTypes.ts, 241, 101)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 243, 27)) +>column : Symbol(column, Decl(controlFlowGenericTypes.ts, 243, 30)) +>Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 237, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 243, 27)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 243, 48)) +>Column : Symbol(Column, Decl(controlFlowGenericTypes.ts, 237, 1)) +>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 243, 27)) return column[key]; ->column : Symbol(column, Decl(controlFlowGenericTypes.ts, 216, 30)) ->key : Symbol(key, Decl(controlFlowGenericTypes.ts, 216, 48)) +>column : Symbol(column, Decl(controlFlowGenericTypes.ts, 243, 30)) +>key : Symbol(key, Decl(controlFlowGenericTypes.ts, 243, 48)) } diff --git a/tests/baselines/reference/controlFlowGenericTypes.types b/tests/baselines/reference/controlFlowGenericTypes.types index ea257ef2c9e..2eaff9186c4 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.types +++ b/tests/baselines/reference/controlFlowGenericTypes.types @@ -583,9 +583,9 @@ function once>(emittingObject: T, eventName: keyo > : ^ } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { >fx1 : (obj: T, key: K) => void @@ -617,6 +617,16 @@ function fx1(obj: T, key: K) { >obj : NonNullable > : ^^^^^^^^^^^^^^ >key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K > : ^ } @@ -650,6 +660,16 @@ function fx2, K extends keyof T>(obj: T, key: >obj : T > : ^ >key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : T[K] +> : ^^^^ +>obj?.[key] : T[K] +> : ^^^^ +>obj : T +> : ^ +>key : K > : ^ } @@ -683,6 +703,202 @@ function fx3 | undefined, K extends keyof T>(o >obj : NonNullable > : ^^^^^^^^^^^^^^ >key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ +} + +function fx4(obj: T, key: K) { +>fx4 : (obj: T, key: K) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x1 = obj[key]; +>x1 : T[K] +> : ^^^^ +>obj[key] : T[K] +> : ^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x2 = obj && obj[key]; +>x2 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ +} + +function fx5(obj: T, key: K) { +>fx5 : (obj: T, key: K) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x1 = obj[key]; +>x1 : T[K] +> : ^^^^ +>obj[key] : T[K] +> : ^^^^ +>obj : T +> : ^ +>key : K +> : ^ + + const x2 = obj && obj[key]; +>x2 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T +> : ^ +>key : K +> : ^ +} + +function fx6(obj: T | null | undefined, key: K) { +>fx6 : (obj: T | null | undefined, key: K) => void +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x1 = obj[key]; // Error +>x1 : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x2 = obj && obj[key]; +>x2 : NonNullable[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj && obj[key] : NonNullable[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>obj[key] : NonNullable[K] +> : ^^^^^^^^^^^^^^^^^ +>obj : NonNullable +> : ^^^^^^^^^^^^^^ +>key : K +> : ^ + + const x3 = obj?.[key]; +>x3 : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj?.[key] : NonNullable[K] | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>obj : T | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^ +>key : K +> : ^ +} + +function fx7(obj: { x: T } | null | undefined, key: K) { +>fx7 : (obj: { x: T; } | null | undefined, key: K) => void +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^^^^^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>x : T +> : ^ +>key : K +> : ^ + + const x1 = obj.x[key]; // Error +>x1 : T[K] +> : ^^^^ +>obj.x[key] : T[K] +> : ^^^^ +>obj.x : T +> : ^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>x : T +> : ^ +>key : K +> : ^ + + const x2 = obj && obj.x[key]; +>x2 : T[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>obj && obj.x[key] : T[K] | null | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>obj.x[key] : T[K] +> : ^^^^ +>obj.x : T +> : ^ +>obj : { x: T; } +> : ^^^^^ ^^^ +>x : T +> : ^ +>key : K +> : ^ + + const x3 = obj?.x[key]; +>x3 : T[K] | undefined +> : ^^^^^^^^^^^^^^^^ +>obj?.x[key] : T[K] | undefined +> : ^^^^^^^^^^^^^^^^ +>obj?.x : T | undefined +> : ^^^^^^^^^^^^^ +>obj : { x: T; } | null | undefined +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ +>x : T | undefined +> : ^^^^^^^^^^^^^ +>key : K > : ^ } diff --git a/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts b/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts index 3cd51616c88..d4dcd885a45 100644 --- a/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts +++ b/tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts @@ -140,23 +140,50 @@ function once>(emittingObject: T, eventName: keyo emittingObject.off(eventName as typeof eventName, 0); } -// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of -// a generic type without a nullable constraint and x is a generic type. This is because when both obj -// and x are of generic types T and K, we want the resulting type to be T[K]. +// In an element access obj[key], we consider obj to be in a constraint position, except when +// obj and key both have generic types. When obj and key are of generic types T and K, we want +// the resulting type to be T[K]. function fx1(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx2, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; } function fx3 | undefined, K extends keyof T>(obj: T, key: K) { const x1 = obj[key]; const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx4(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx5(obj: T, key: K) { + const x1 = obj[key]; + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx6(obj: T | null | undefined, key: K) { + const x1 = obj[key]; // Error + const x2 = obj && obj[key]; + const x3 = obj?.[key]; +} + +function fx7(obj: { x: T } | null | undefined, key: K) { + const x1 = obj.x[key]; // Error + const x2 = obj && obj.x[key]; + const x3 = obj?.x[key]; } // Repro from #44166