Skip to content

Commit 8e5a84a

Browse files
authored
Exclude mapped types with optionality modifiers and 'as' clauses from constraint logic (#48273)
* Exclude mapped types with optionality modifiers and 'as' clauses * Add regression tests
1 parent 111ca92 commit 8e5a84a

File tree

5 files changed

+213
-3
lines changed

5 files changed

+213
-3
lines changed

src/compiler/checker.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -12219,9 +12219,10 @@ namespace ts {
1221912219
}
1222012220

1222112221
function isMappedTypeGenericIndexedAccess(type: Type) {
12222-
return type.flags & TypeFlags.IndexedAccess && getObjectFlags((type as IndexedAccessType).objectType) & ObjectFlags.Mapped &&
12223-
!((type as IndexedAccessType).objectType as MappedType).declaration.nameType &&
12224-
!isGenericMappedType((type as IndexedAccessType).objectType) && isGenericIndexType((type as IndexedAccessType).indexType);
12222+
let objectType;
12223+
return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped &&
12224+
!isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) &&
12225+
!(objectType as MappedType).declaration.questionToken && !(objectType as MappedType).declaration.nameType);
1222512226
}
1222612227

1222712228
/**

tests/baselines/reference/correlatedUnions.js

+55
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,31 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
209209
}
210210
return undefined;
211211
}
212+
213+
// Repro from #48157
214+
215+
interface Foo {
216+
bar?: string
217+
}
218+
219+
function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
220+
bar(f[prop]);
221+
}
222+
223+
declare function bar(t: string): void;
224+
225+
// Repro from #48246
226+
227+
declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, Attr extends keyof T[number]>(
228+
ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item };
229+
230+
const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const;
231+
232+
const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name');
233+
234+
type BarLookup = typeof BAR_LOOKUP;
235+
236+
type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] };
212237

213238

214239
//// [correlatedUnions.js]
@@ -325,6 +350,11 @@ function func(k) {
325350
}
326351
return undefined;
327352
}
353+
function foo(prop, f) {
354+
bar(f[prop]);
355+
}
356+
var ALL_BARS = [{ name: 'a' }, { name: 'b' }];
357+
var BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name');
328358

329359

330360
//// [correlatedUnions.d.ts]
@@ -451,3 +481,28 @@ interface MyObj {
451481
}
452482
declare const ref: MyObj;
453483
declare function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined;
484+
interface Foo {
485+
bar?: string;
486+
}
487+
declare function foo<T extends keyof Foo>(prop: T, f: Required<Foo>): void;
488+
declare function bar(t: string): void;
489+
declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, Attr extends keyof T[number]>(ops: T, attr: Attr): {
490+
[Item in T[number] as Item[Attr]]: Item;
491+
};
492+
declare const ALL_BARS: readonly [{
493+
readonly name: "a";
494+
}, {
495+
readonly name: "b";
496+
}];
497+
declare const BAR_LOOKUP: {
498+
a: {
499+
readonly name: "a";
500+
};
501+
b: {
502+
readonly name: "b";
503+
};
504+
};
505+
declare type BarLookup = typeof BAR_LOOKUP;
506+
declare type Baz = {
507+
[K in keyof BarLookup]: BarLookup[K]['name'];
508+
};

tests/baselines/reference/correlatedUnions.symbols

+71
Original file line numberDiff line numberDiff line change
@@ -753,3 +753,74 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
753753
>undefined : Symbol(undefined)
754754
}
755755

756+
// Repro from #48157
757+
758+
interface Foo {
759+
>Foo : Symbol(Foo, Decl(correlatedUnions.ts, 209, 1))
760+
761+
bar?: string
762+
>bar : Symbol(Foo.bar, Decl(correlatedUnions.ts, 213, 15))
763+
}
764+
765+
function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
766+
>foo : Symbol(foo, Decl(correlatedUnions.ts, 215, 1))
767+
>T : Symbol(T, Decl(correlatedUnions.ts, 217, 13))
768+
>Foo : Symbol(Foo, Decl(correlatedUnions.ts, 209, 1))
769+
>prop : Symbol(prop, Decl(correlatedUnions.ts, 217, 34))
770+
>T : Symbol(T, Decl(correlatedUnions.ts, 217, 13))
771+
>f : Symbol(f, Decl(correlatedUnions.ts, 217, 42))
772+
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
773+
>Foo : Symbol(Foo, Decl(correlatedUnions.ts, 209, 1))
774+
775+
bar(f[prop]);
776+
>bar : Symbol(bar, Decl(correlatedUnions.ts, 219, 1))
777+
>f : Symbol(f, Decl(correlatedUnions.ts, 217, 42))
778+
>prop : Symbol(prop, Decl(correlatedUnions.ts, 217, 34))
779+
}
780+
781+
declare function bar(t: string): void;
782+
>bar : Symbol(bar, Decl(correlatedUnions.ts, 219, 1))
783+
>t : Symbol(t, Decl(correlatedUnions.ts, 221, 21))
784+
785+
// Repro from #48246
786+
787+
declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, Attr extends keyof T[number]>(
788+
>makeCompleteLookupMapping : Symbol(makeCompleteLookupMapping, Decl(correlatedUnions.ts, 221, 38))
789+
>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43))
790+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --))
791+
>Attr : Symbol(Attr, Decl(correlatedUnions.ts, 225, 72))
792+
>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43))
793+
794+
ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item };
795+
>ops : Symbol(ops, Decl(correlatedUnions.ts, 225, 103))
796+
>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43))
797+
>attr : Symbol(attr, Decl(correlatedUnions.ts, 226, 11))
798+
>Attr : Symbol(Attr, Decl(correlatedUnions.ts, 225, 72))
799+
>Item : Symbol(Item, Decl(correlatedUnions.ts, 226, 28))
800+
>T : Symbol(T, Decl(correlatedUnions.ts, 225, 43))
801+
>Item : Symbol(Item, Decl(correlatedUnions.ts, 226, 28))
802+
>Attr : Symbol(Attr, Decl(correlatedUnions.ts, 225, 72))
803+
>Item : Symbol(Item, Decl(correlatedUnions.ts, 226, 28))
804+
805+
const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const;
806+
>ALL_BARS : Symbol(ALL_BARS, Decl(correlatedUnions.ts, 228, 5))
807+
>name : Symbol(name, Decl(correlatedUnions.ts, 228, 19))
808+
>name : Symbol(name, Decl(correlatedUnions.ts, 228, 33))
809+
>const : Symbol(const)
810+
811+
const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name');
812+
>BAR_LOOKUP : Symbol(BAR_LOOKUP, Decl(correlatedUnions.ts, 230, 5))
813+
>makeCompleteLookupMapping : Symbol(makeCompleteLookupMapping, Decl(correlatedUnions.ts, 221, 38))
814+
>ALL_BARS : Symbol(ALL_BARS, Decl(correlatedUnions.ts, 228, 5))
815+
816+
type BarLookup = typeof BAR_LOOKUP;
817+
>BarLookup : Symbol(BarLookup, Decl(correlatedUnions.ts, 230, 63))
818+
>BAR_LOOKUP : Symbol(BAR_LOOKUP, Decl(correlatedUnions.ts, 230, 5))
819+
820+
type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] };
821+
>Baz : Symbol(Baz, Decl(correlatedUnions.ts, 232, 35))
822+
>K : Symbol(K, Decl(correlatedUnions.ts, 234, 14))
823+
>BarLookup : Symbol(BarLookup, Decl(correlatedUnions.ts, 230, 63))
824+
>BarLookup : Symbol(BarLookup, Decl(correlatedUnions.ts, 230, 63))
825+
>K : Symbol(K, Decl(correlatedUnions.ts, 234, 14))
826+

tests/baselines/reference/correlatedUnions.types

+58
Original file line numberDiff line numberDiff line change
@@ -695,3 +695,61 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
695695
>undefined : undefined
696696
}
697697

698+
// Repro from #48157
699+
700+
interface Foo {
701+
bar?: string
702+
>bar : string | undefined
703+
}
704+
705+
function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
706+
>foo : <T extends "bar">(prop: T, f: Required<Foo>) => void
707+
>prop : T
708+
>f : Required<Foo>
709+
710+
bar(f[prop]);
711+
>bar(f[prop]) : void
712+
>bar : (t: string) => void
713+
>f[prop] : Required<Foo>[T]
714+
>f : Required<Foo>
715+
>prop : T
716+
}
717+
718+
declare function bar(t: string): void;
719+
>bar : (t: string) => void
720+
>t : string
721+
722+
// Repro from #48246
723+
724+
declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, Attr extends keyof T[number]>(
725+
>makeCompleteLookupMapping : <T extends readonly any[], Attr extends keyof T[number]>(ops: T, attr: Attr) => { [Item in T[number] as Item[Attr]]: Item; }
726+
727+
ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item };
728+
>ops : T
729+
>attr : Attr
730+
731+
const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const;
732+
>ALL_BARS : readonly [{ readonly name: "a"; }, { readonly name: "b"; }]
733+
>[{ name: 'a'}, {name: 'b'}] as const : readonly [{ readonly name: "a"; }, { readonly name: "b"; }]
734+
>[{ name: 'a'}, {name: 'b'}] : readonly [{ readonly name: "a"; }, { readonly name: "b"; }]
735+
>{ name: 'a'} : { readonly name: "a"; }
736+
>name : "a"
737+
>'a' : "a"
738+
>{name: 'b'} : { readonly name: "b"; }
739+
>name : "b"
740+
>'b' : "b"
741+
742+
const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name');
743+
>BAR_LOOKUP : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; }
744+
>makeCompleteLookupMapping(ALL_BARS, 'name') : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; }
745+
>makeCompleteLookupMapping : <T extends readonly any[], Attr extends keyof T[number]>(ops: T, attr: Attr) => { [Item in T[number] as Item[Attr]]: Item; }
746+
>ALL_BARS : readonly [{ readonly name: "a"; }, { readonly name: "b"; }]
747+
>'name' : "name"
748+
749+
type BarLookup = typeof BAR_LOOKUP;
750+
>BarLookup : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; }
751+
>BAR_LOOKUP : { a: { readonly name: "a"; }; b: { readonly name: "b"; }; }
752+
753+
type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] };
754+
>Baz : Baz
755+

tests/cases/compiler/correlatedUnions.ts

+25
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,28 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
211211
}
212212
return undefined;
213213
}
214+
215+
// Repro from #48157
216+
217+
interface Foo {
218+
bar?: string
219+
}
220+
221+
function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
222+
bar(f[prop]);
223+
}
224+
225+
declare function bar(t: string): void;
226+
227+
// Repro from #48246
228+
229+
declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, Attr extends keyof T[number]>(
230+
ops: T, attr: Attr): { [Item in T[number]as Item[Attr]]: Item };
231+
232+
const ALL_BARS = [{ name: 'a'}, {name: 'b'}] as const;
233+
234+
const BAR_LOOKUP = makeCompleteLookupMapping(ALL_BARS, 'name');
235+
236+
type BarLookup = typeof BAR_LOOKUP;
237+
238+
type Baz = { [K in keyof BarLookup]: BarLookup[K]['name'] };

0 commit comments

Comments
 (0)