Skip to content

Commit

Permalink
Exclude mapped types with optionality modifiers and 'as' clauses from…
Browse files Browse the repository at this point in the history
… constraint logic (#48273)

* Exclude mapped types with optionality modifiers and 'as' clauses

* Add regression tests
  • Loading branch information
ahejlsberg committed Mar 16, 2022
1 parent 111ca92 commit 8e5a84a
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 3 deletions.
7 changes: 4 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down
55 changes: 55 additions & 0 deletions tests/baselines/reference/correlatedUnions.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,31 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
}
return undefined;
}

// Repro from #48157

interface Foo {
bar?: string
}

function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
bar(f[prop]);
}

declare function bar(t: string): void;

// Repro from #48246

declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, 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]
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -451,3 +481,28 @@ interface MyObj {
}
declare const ref: MyObj;
declare function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined;
interface Foo {
bar?: string;
}
declare function foo<T extends keyof Foo>(prop: T, f: Required<Foo>): void;
declare function bar(t: string): void;
declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, 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'];
};
71 changes: 71 additions & 0 deletions tests/baselines/reference/correlatedUnions.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -753,3 +753,74 @@ function func<K extends keyof MyObj>(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<T extends keyof Foo>(prop: T, f: Required<Foo>) {
>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<T extends ReadonlyArray<any>, 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))

58 changes: 58 additions & 0 deletions tests/baselines/reference/correlatedUnions.types
Original file line number Diff line number Diff line change
Expand Up @@ -695,3 +695,61 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
>undefined : undefined
}

// Repro from #48157

interface Foo {
bar?: string
>bar : string | undefined
}

function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
>foo : <T extends "bar">(prop: T, f: Required<Foo>) => void
>prop : T
>f : Required<Foo>

bar(f[prop]);
>bar(f[prop]) : void
>bar : (t: string) => void
>f[prop] : Required<Foo>[T]
>f : Required<Foo>
>prop : T
}

declare function bar(t: string): void;
>bar : (t: string) => void
>t : string

// Repro from #48246

declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, Attr extends keyof T[number]>(
>makeCompleteLookupMapping : <T extends readonly any[], Attr extends keyof T[number]>(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 : <T extends readonly any[], Attr extends keyof T[number]>(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

25 changes: 25 additions & 0 deletions tests/cases/compiler/correlatedUnions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,28 @@ function func<K extends keyof MyObj>(k: K): MyObj[K]['name'] | undefined {
}
return undefined;
}

// Repro from #48157

interface Foo {
bar?: string
}

function foo<T extends keyof Foo>(prop: T, f: Required<Foo>) {
bar(f[prop]);
}

declare function bar(t: string): void;

// Repro from #48246

declare function makeCompleteLookupMapping<T extends ReadonlyArray<any>, 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'] };

0 comments on commit 8e5a84a

Please sign in to comment.