diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8ab4ec7802..3fbac84fa64 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17381,9 +17381,9 @@ namespace ts { (target as UnionType).types.length <= 3 && maybeTypeOfKind(target, TypeFlags.Nullable)) { const nullStrippedTarget = extractTypesOfKind(target, ~TypeFlags.Nullable); if (!(nullStrippedTarget.flags & (TypeFlags.Union | TypeFlags.Never))) { - if (source === nullStrippedTarget) return Ternary.True; - target = nullStrippedTarget; + target = getNormalizedType(nullStrippedTarget, /*writing*/ true); } + if (source === nullStrippedTarget) return Ternary.True; } if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || diff --git a/tests/baselines/reference/indexedAccessNormalization.js b/tests/baselines/reference/indexedAccessNormalization.js new file mode 100644 index 00000000000..57f89a87ff6 --- /dev/null +++ b/tests/baselines/reference/indexedAccessNormalization.js @@ -0,0 +1,35 @@ +//// [indexedAccessNormalization.ts] +// Repro from from #43152 + +type MyMap = { + [K in keyof M]: { + x: number + } +} + +declare function g(value?: T): void; + +function f1(mymap: MyMap, k: keyof M) { + const elemofM = mymap[k]; + g(elemofM); +} + +function f2(mymap: MyMap, k: keyof M, z: { x: number }) { + const q1: MyMap[keyof M] = z; + const q2: MyMap[keyof M] | undefined = z; + const q3: MyMap[keyof M] | string = z; +} + + +//// [indexedAccessNormalization.js] +"use strict"; +// Repro from from #43152 +function f1(mymap, k) { + var elemofM = mymap[k]; + g(elemofM); +} +function f2(mymap, k, z) { + var q1 = z; + var q2 = z; + var q3 = z; +} diff --git a/tests/baselines/reference/indexedAccessNormalization.symbols b/tests/baselines/reference/indexedAccessNormalization.symbols new file mode 100644 index 00000000000..9c1cd638f44 --- /dev/null +++ b/tests/baselines/reference/indexedAccessNormalization.symbols @@ -0,0 +1,74 @@ +=== tests/cases/compiler/indexedAccessNormalization.ts === +// Repro from from #43152 + +type MyMap = { +>MyMap : Symbol(MyMap, Decl(indexedAccessNormalization.ts, 0, 0)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 2, 11)) + + [K in keyof M]: { +>K : Symbol(K, Decl(indexedAccessNormalization.ts, 3, 5)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 2, 11)) + + x: number +>x : Symbol(x, Decl(indexedAccessNormalization.ts, 3, 21)) + } +} + +declare function g(value?: T): void; +>g : Symbol(g, Decl(indexedAccessNormalization.ts, 6, 1)) +>T : Symbol(T, Decl(indexedAccessNormalization.ts, 8, 19)) +>value : Symbol(value, Decl(indexedAccessNormalization.ts, 8, 22)) +>T : Symbol(T, Decl(indexedAccessNormalization.ts, 8, 19)) + +function f1(mymap: MyMap, k: keyof M) { +>f1 : Symbol(f1, Decl(indexedAccessNormalization.ts, 8, 39)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 10, 12)) +>mymap : Symbol(mymap, Decl(indexedAccessNormalization.ts, 10, 30)) +>MyMap : Symbol(MyMap, Decl(indexedAccessNormalization.ts, 0, 0)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 10, 12)) +>k : Symbol(k, Decl(indexedAccessNormalization.ts, 10, 46)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 10, 12)) + + const elemofM = mymap[k]; +>elemofM : Symbol(elemofM, Decl(indexedAccessNormalization.ts, 11, 9)) +>mymap : Symbol(mymap, Decl(indexedAccessNormalization.ts, 10, 30)) +>k : Symbol(k, Decl(indexedAccessNormalization.ts, 10, 46)) + + g(elemofM); +>g : Symbol(g, Decl(indexedAccessNormalization.ts, 6, 1)) +>elemofM : Symbol(elemofM, Decl(indexedAccessNormalization.ts, 11, 9)) +} + +function f2(mymap: MyMap, k: keyof M, z: { x: number }) { +>f2 : Symbol(f2, Decl(indexedAccessNormalization.ts, 13, 1)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>mymap : Symbol(mymap, Decl(indexedAccessNormalization.ts, 15, 30)) +>MyMap : Symbol(MyMap, Decl(indexedAccessNormalization.ts, 0, 0)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>k : Symbol(k, Decl(indexedAccessNormalization.ts, 15, 46)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>z : Symbol(z, Decl(indexedAccessNormalization.ts, 15, 58)) +>x : Symbol(x, Decl(indexedAccessNormalization.ts, 15, 63)) + + const q1: MyMap[keyof M] = z; +>q1 : Symbol(q1, Decl(indexedAccessNormalization.ts, 16, 9)) +>MyMap : Symbol(MyMap, Decl(indexedAccessNormalization.ts, 0, 0)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>z : Symbol(z, Decl(indexedAccessNormalization.ts, 15, 58)) + + const q2: MyMap[keyof M] | undefined = z; +>q2 : Symbol(q2, Decl(indexedAccessNormalization.ts, 17, 9)) +>MyMap : Symbol(MyMap, Decl(indexedAccessNormalization.ts, 0, 0)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>z : Symbol(z, Decl(indexedAccessNormalization.ts, 15, 58)) + + const q3: MyMap[keyof M] | string = z; +>q3 : Symbol(q3, Decl(indexedAccessNormalization.ts, 18, 9)) +>MyMap : Symbol(MyMap, Decl(indexedAccessNormalization.ts, 0, 0)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>M : Symbol(M, Decl(indexedAccessNormalization.ts, 15, 12)) +>z : Symbol(z, Decl(indexedAccessNormalization.ts, 15, 58)) +} + diff --git a/tests/baselines/reference/indexedAccessNormalization.types b/tests/baselines/reference/indexedAccessNormalization.types new file mode 100644 index 00000000000..53d57f4319a --- /dev/null +++ b/tests/baselines/reference/indexedAccessNormalization.types @@ -0,0 +1,53 @@ +=== tests/cases/compiler/indexedAccessNormalization.ts === +// Repro from from #43152 + +type MyMap = { +>MyMap : MyMap + + [K in keyof M]: { + x: number +>x : number + } +} + +declare function g(value?: T): void; +>g : (value?: T | undefined) => void +>value : T | undefined + +function f1(mymap: MyMap, k: keyof M) { +>f1 : (mymap: MyMap, k: keyof M) => void +>mymap : MyMap +>k : keyof M + + const elemofM = mymap[k]; +>elemofM : MyMap[keyof M] +>mymap[k] : MyMap[keyof M] +>mymap : MyMap +>k : keyof M + + g(elemofM); +>g(elemofM) : void +>g : (value?: T | undefined) => void +>elemofM : MyMap[keyof M] +} + +function f2(mymap: MyMap, k: keyof M, z: { x: number }) { +>f2 : (mymap: MyMap, k: keyof M, z: { x: number;}) => void +>mymap : MyMap +>k : keyof M +>z : { x: number; } +>x : number + + const q1: MyMap[keyof M] = z; +>q1 : MyMap[keyof M] +>z : { x: number; } + + const q2: MyMap[keyof M] | undefined = z; +>q2 : MyMap[keyof M] | undefined +>z : { x: number; } + + const q3: MyMap[keyof M] | string = z; +>q3 : string | MyMap[keyof M] +>z : { x: number; } +} + diff --git a/tests/cases/compiler/indexedAccessNormalization.ts b/tests/cases/compiler/indexedAccessNormalization.ts new file mode 100644 index 00000000000..e59e11d3c69 --- /dev/null +++ b/tests/cases/compiler/indexedAccessNormalization.ts @@ -0,0 +1,22 @@ +// @strict: true + +// Repro from from #43152 + +type MyMap = { + [K in keyof M]: { + x: number + } +} + +declare function g(value?: T): void; + +function f1(mymap: MyMap, k: keyof M) { + const elemofM = mymap[k]; + g(elemofM); +} + +function f2(mymap: MyMap, k: keyof M, z: { x: number }) { + const q1: MyMap[keyof M] = z; + const q2: MyMap[keyof M] | undefined = z; + const q3: MyMap[keyof M] | string = z; +}