diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 34bf68b663021..0a0b50ac45ef4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12219,9 +12219,10 @@ namespace ts { } function isMappedTypeGenericIndexedAccess(type: Type) { - return type.flags & TypeFlags.IndexedAccess && getObjectFlags((type as IndexedAccessType).objectType) & ObjectFlags.Mapped && - !((type as IndexedAccessType).objectType as MappedType).declaration.nameType && - !isGenericMappedType((type as IndexedAccessType).objectType) && isGenericIndexType((type as IndexedAccessType).indexType); + let objectType; + return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped && + !isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) && + !(objectType as MappedType).declaration.questionToken && !(objectType as MappedType).declaration.nameType); } /** diff --git a/tests/baselines/reference/correlatedUnions.js b/tests/baselines/reference/correlatedUnions.js index f1e13f4417030..0d6698588d31c 100644 --- a/tests/baselines/reference/correlatedUnions.js +++ b/tests/baselines/reference/correlatedUnions.js @@ -209,6 +209,31 @@ function func(k: K): MyObj[K]['name'] | undefined { } return undefined; } + +// Repro from #48157 + +interface Foo { + bar?: string +} + +function foo(prop: T, f: Required) { + bar(f[prop]); +} + +declare function bar(t: string): void; + +// Repro from #48246 + +declare function makeCompleteLookupMapping, Attr extends keyof T[number]>( + ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item }; + +const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const; + +const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name'); + +type BarLookup = typeof BAR_LOOKUP; + +type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] }; //// [correlatedUnions.js] @@ -325,6 +350,11 @@ function func(k) { } return undefined; } +function foo(prop, f) { + bar(f[prop]); +} +var ALL_BARS = [{ name: 'a' }, { name: 'b' }]; +var BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name'); //// [correlatedUnions.d.ts] @@ -451,3 +481,28 @@ interface MyObj { } declare const ref: MyObj; declare function func(k: K): MyObj[K]['name'] | undefined; +interface Foo { + bar?: string; +} +declare function foo(prop: T, f: Required): void; +declare function bar(t: string): void; +declare function makeCompleteLookupMapping, Attr extends keyof T[number]>(ops: T, attr: Attr): { + [Item in T[number] as Item[Attr]]: Item; +}; +declare const ALL_BARS: readonly [{ + readonly name: "a"; +}, { + readonly name: "b"; +}]; +declare const BAR_LOOKUP: { + a: { + readonly name: "a"; + }; + b: { + readonly name: "b"; + }; +}; +declare type BarLookup = typeof BAR_LOOKUP; +declare type Baz = { + [K in keyof BarLookup]: BarLookup[K]['name']; +}; diff --git a/tests/baselines/reference/correlatedUnions.symbols b/tests/baselines/reference/correlatedUnions.symbols index 16fa17e1a4f0e..9485b70c5dcd5 100644 --- a/tests/baselines/reference/correlatedUnions.symbols +++ b/tests/baselines/reference/correlatedUnions.symbols @@ -753,3 +753,74 @@ function func(k: K): MyObj[K]['name'] | undefined { >undefined : Symbol(undefined) } +// Repro from #48157 + +interface Foo { +>Foo : Symbol(Foo, Decl(correlatedUnions.ts, 209, 1)) + + bar?: string +>bar : Symbol(Foo.bar, Decl(correlatedUnions.ts, 213, 15)) +} + +function foo(prop: T, f: Required) { +>foo : Symbol(foo, Decl(correlatedUnions.ts, 215, 1)) +>T : Symbol(T, Decl(correlatedUnions.ts, 217, 13)) +>Foo : Symbol(Foo, Decl(correlatedUnions.ts, 209, 1)) +>prop : Symbol(prop, Decl(correlatedUnions.ts, 217, 34)) +>T : Symbol(T, Decl(correlatedUnions.ts, 217, 13)) +>f : Symbol(f, Decl(correlatedUnions.ts, 217, 42)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>Foo : Symbol(Foo, Decl(correlatedUnions.ts, 209, 1)) + + bar(f[prop]); +>bar : Symbol(bar, Decl(correlatedUnions.ts, 219, 1)) +>f : Symbol(f, Decl(correlatedUnions.ts, 217, 42)) +>prop : Symbol(prop, Decl(correlatedUnions.ts, 217, 34)) +} + +declare function bar(t: string): void; +>bar : Symbol(bar, Decl(correlatedUnions.ts, 219, 1)) +>t : Symbol(t, Decl(correlatedUnions.ts, 221, 21)) + +// Repro from #48246 + +declare function makeCompleteLookupMapping, Attr extends keyof T[number]>( +>makeCompleteLookupMapping : Symbol(makeCompleteLookupMapping, Decl(correlatedUnions.ts, 221, 38)) +>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --)) +>Attr : Symbol(Attr, Decl(correlatedUnions.ts, 225, 72)) +>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43)) + + ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item }; +>ops : Symbol(ops, Decl(correlatedUnions.ts, 225, 103)) +>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43)) +>attr : Symbol(attr, Decl(correlatedUnions.ts, 226, 11)) +>Attr : Symbol(Attr, Decl(correlatedUnions.ts, 225, 72)) +>Item : Symbol(Item, Decl(correlatedUnions.ts, 226, 28)) +>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43)) +>Item : Symbol(Item, Decl(correlatedUnions.ts, 226, 28)) +>Attr : Symbol(Attr, Decl(correlatedUnions.ts, 225, 72)) +>Item : Symbol(Item, Decl(correlatedUnions.ts, 226, 28)) + +const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const; +>ALL_BARS : Symbol(ALL_BARS, Decl(correlatedUnions.ts, 228, 5)) +>name : Symbol(name, Decl(correlatedUnions.ts, 228, 19)) +>name : Symbol(name, Decl(correlatedUnions.ts, 228, 33)) +>const : Symbol(const) + +const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name'); +>BAR_LOOKUP : Symbol(BAR_LOOKUP, Decl(correlatedUnions.ts, 230, 5)) +>makeCompleteLookupMapping : Symbol(makeCompleteLookupMapping, Decl(correlatedUnions.ts, 221, 38)) +>ALL_BARS : Symbol(ALL_BARS, Decl(correlatedUnions.ts, 228, 5)) + +type BarLookup = typeof BAR_LOOKUP; +>BarLookup : Symbol(BarLookup, Decl(correlatedUnions.ts, 230, 63)) +>BAR_LOOKUP : Symbol(BAR_LOOKUP, Decl(correlatedUnions.ts, 230, 5)) + +type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] }; +>Baz : Symbol(Baz, Decl(correlatedUnions.ts, 232, 35)) +>K : Symbol(K, Decl(correlatedUnions.ts, 234, 14)) +>BarLookup : Symbol(BarLookup, Decl(correlatedUnions.ts, 230, 63)) +>BarLookup : Symbol(BarLookup, Decl(correlatedUnions.ts, 230, 63)) +>K : Symbol(K, Decl(correlatedUnions.ts, 234, 14)) + diff --git a/tests/baselines/reference/correlatedUnions.types b/tests/baselines/reference/correlatedUnions.types index 3a4d950070704..ec83dd5426dfa 100644 --- a/tests/baselines/reference/correlatedUnions.types +++ b/tests/baselines/reference/correlatedUnions.types @@ -695,3 +695,61 @@ function func(k: K): MyObj[K]['name'] | undefined { >undefined : undefined } +// Repro from #48157 + +interface Foo { + bar?: string +>bar : string | undefined +} + +function foo(prop: T, f: Required) { +>foo : (prop: T, f: Required) => void +>prop : T +>f : Required + + bar(f[prop]); +>bar(f[prop]) : void +>bar : (t: string) => void +>f[prop] : Required[T] +>f : Required +>prop : T +} + +declare function bar(t: string): void; +>bar : (t: string) => void +>t : string + +// Repro from #48246 + +declare function makeCompleteLookupMapping, Attr extends keyof T[number]>( +>makeCompleteLookupMapping : (ops: T, attr: Attr) => { [Item in T[number] as Item[Attr]]: Item; } + + ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item }; +>ops : T +>attr : Attr + +const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const; +>ALL_BARS : readonly [{ readonly name: "a"; }, { readonly name: "b"; }] +>[{ name: 'a'}, {name: 'b'}] as const : readonly [{ readonly name: "a"; }, { readonly name: "b"; }] +>[{ name: 'a'}, {name: 'b'}] : readonly [{ readonly name: "a"; }, { readonly name: "b"; }] +>{ name: 'a'} : { readonly name: "a"; } +>name : "a" +>'a' : "a" +>{name: 'b'} : { readonly name: "b"; } +>name : "b" +>'b' : "b" + +const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name'); +>BAR_LOOKUP : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; } +>makeCompleteLookupMapping(ALL_BARS, 'name') : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; } +>makeCompleteLookupMapping : (ops: T, attr: Attr) => { [Item in T[number] as Item[Attr]]: Item; } +>ALL_BARS : readonly [{ readonly name: "a"; }, { readonly name: "b"; }] +>'name' : "name" + +type BarLookup = typeof BAR_LOOKUP; +>BarLookup : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; } +>BAR_LOOKUP : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; } + +type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] }; +>Baz : Baz + diff --git a/tests/cases/compiler/correlatedUnions.ts b/tests/cases/compiler/correlatedUnions.ts index f6b4086f03f5a..e75e56f15ce69 100644 --- a/tests/cases/compiler/correlatedUnions.ts +++ b/tests/cases/compiler/correlatedUnions.ts @@ -211,3 +211,28 @@ function func(k: K): MyObj[K]['name'] | undefined { } return undefined; } + +// Repro from #48157 + +interface Foo { + bar?: string +} + +function foo(prop: T, f: Required) { + bar(f[prop]); +} + +declare function bar(t: string): void; + +// Repro from #48246 + +declare function makeCompleteLookupMapping, Attr extends keyof T[number]>( + ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item }; + +const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const; + +const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name'); + +type BarLookup = typeof BAR_LOOKUP; + +type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] };