Merge pull request #23660 from Microsoft/fixIndexTypeTargetConstraint

Fix constraint of 'keyof T[K]' in target position
This commit is contained in:
Anders Hejlsberg
2018-04-27 15:52:21 -07:00
committed by GitHub
5 changed files with 191 additions and 41 deletions

View File

@@ -10537,11 +10537,14 @@ namespace ts {
}
}
// A type S is assignable to keyof T if S is assignable to keyof C, where C is the
// constraint of T.
const constraint = getConstraintForRelation((<IndexType>target).type);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors)) {
return result;
// simplified form of T or, if T doesn't simplify, the constraint of T.
if (relation !== definitelyAssignableRelation) {
const simplified = getSimplifiedType((<IndexType>target).type);
const constraint = simplified !== (<IndexType>target).type ? simplified : getConstraintOfType((<IndexType>target).type);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors)) {
return result;
}
}
}
}

View File

@@ -566,6 +566,15 @@ type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
}
// Repros from #23592
type Example<T extends { [K in keyof T]: { prop: any } }> = { [K in keyof T]: T[K]["prop"] };
type Result = Example<{ a: { prop: string }; b: { prop: number } }>;
type Helper2<T> = { [K in keyof T]: Extract<T[K], { prop: any }> };
type Example2<T> = { [K in keyof Helper2<T>]: Helper2<T>[K]["prop"] };
type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>;
// Repro from #23618
type DBBoolTable<K extends string> = { [k in K]: 0 | 1 }
@@ -1241,6 +1250,37 @@ declare function f3<T, K extends Extract<keyof T, string>>(t: T, k: K, tk: T[K])
declare type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T];
};
declare type Example<T extends {
[K in keyof T]: {
prop: any;
};
}> = {
[K in keyof T]: T[K]["prop"];
};
declare type Result = Example<{
a: {
prop: string;
};
b: {
prop: number;
};
}>;
declare type Helper2<T> = {
[K in keyof T]: Extract<T[K], {
prop: any;
}>;
};
declare type Example2<T> = {
[K in keyof Helper2<T>]: Helper2<T>[K]["prop"];
};
declare type Result2 = Example2<{
1: {
prop: string;
};
2: {
prop: number;
};
}>;
declare type DBBoolTable<K extends string> = {
[k in K]: 0 | 1;
};

View File

@@ -2010,64 +2010,113 @@ type Predicates<TaggedRecord> = {
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3))
}
// Repros from #23592
type Example<T extends { [K in keyof T]: { prop: any } }> = { [K in keyof T]: T[K]["prop"] };
>Example : Symbol(Example, Decl(keyofAndIndexedAccess.ts, 565, 1))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 26))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 569, 42))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 63))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 569, 13))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 63))
type Result = Example<{ a: { prop: string }; b: { prop: number } }>;
>Result : Symbol(Result, Decl(keyofAndIndexedAccess.ts, 569, 93))
>Example : Symbol(Example, Decl(keyofAndIndexedAccess.ts, 565, 1))
>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 570, 23))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 570, 28))
>b : Symbol(b, Decl(keyofAndIndexedAccess.ts, 570, 44))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 570, 49))
type Helper2<T> = { [K in keyof T]: Extract<T[K], { prop: any }> };
>Helper2 : Symbol(Helper2, Decl(keyofAndIndexedAccess.ts, 570, 68))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 572, 13))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 572, 21))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 572, 13))
>Extract : Symbol(Extract, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 572, 13))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 572, 21))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 572, 51))
type Example2<T> = { [K in keyof Helper2<T>]: Helper2<T>[K]["prop"] };
>Example2 : Symbol(Example2, Decl(keyofAndIndexedAccess.ts, 572, 67))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 573, 14))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 573, 22))
>Helper2 : Symbol(Helper2, Decl(keyofAndIndexedAccess.ts, 570, 68))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 573, 14))
>Helper2 : Symbol(Helper2, Decl(keyofAndIndexedAccess.ts, 570, 68))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 573, 14))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 573, 22))
type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>;
>Result2 : Symbol(Result2, Decl(keyofAndIndexedAccess.ts, 573, 70))
>Example2 : Symbol(Example2, Decl(keyofAndIndexedAccess.ts, 572, 67))
>1 : Symbol(1, Decl(keyofAndIndexedAccess.ts, 574, 25))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 574, 30))
>2 : Symbol(2, Decl(keyofAndIndexedAccess.ts, 574, 46))
>prop : Symbol(prop, Decl(keyofAndIndexedAccess.ts, 574, 51))
// Repro from #23618
type DBBoolTable<K extends string> = { [k in K]: 0 | 1 }
>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 565, 1))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 17))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 569, 40))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 569, 17))
>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 574, 70))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 578, 17))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 578, 40))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 578, 17))
enum Flag {
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 569, 56))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 578, 56))
FLAG_1 = "flag_1",
>FLAG_1 : Symbol(Flag.FLAG_1, Decl(keyofAndIndexedAccess.ts, 570, 11))
>FLAG_1 : Symbol(Flag.FLAG_1, Decl(keyofAndIndexedAccess.ts, 579, 11))
FLAG_2 = "flag_2"
>FLAG_2 : Symbol(Flag.FLAG_2, Decl(keyofAndIndexedAccess.ts, 571, 22))
>FLAG_2 : Symbol(Flag.FLAG_2, Decl(keyofAndIndexedAccess.ts, 580, 22))
}
type SimpleDBRecord<Flag extends string> = { staticField: number } & DBBoolTable<Flag>
>SimpleDBRecord : Symbol(SimpleDBRecord, Decl(keyofAndIndexedAccess.ts, 573, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 575, 20))
>staticField : Symbol(staticField, Decl(keyofAndIndexedAccess.ts, 575, 44))
>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 565, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 575, 20))
>SimpleDBRecord : Symbol(SimpleDBRecord, Decl(keyofAndIndexedAccess.ts, 582, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 584, 20))
>staticField : Symbol(staticField, Decl(keyofAndIndexedAccess.ts, 584, 44))
>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 574, 70))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 584, 20))
function getFlagsFromSimpleRecord<Flag extends string>(record: SimpleDBRecord<Flag>, flags: Flag[]) {
>getFlagsFromSimpleRecord : Symbol(getFlagsFromSimpleRecord, Decl(keyofAndIndexedAccess.ts, 575, 86))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 576, 34))
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 576, 55))
>SimpleDBRecord : Symbol(SimpleDBRecord, Decl(keyofAndIndexedAccess.ts, 573, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 576, 34))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 576, 84))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 576, 34))
>getFlagsFromSimpleRecord : Symbol(getFlagsFromSimpleRecord, Decl(keyofAndIndexedAccess.ts, 584, 86))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 585, 34))
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 585, 55))
>SimpleDBRecord : Symbol(SimpleDBRecord, Decl(keyofAndIndexedAccess.ts, 582, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 585, 34))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 585, 84))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 585, 34))
return record[flags[0]];
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 576, 55))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 576, 84))
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 585, 55))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 585, 84))
}
type DynamicDBRecord<Flag extends string> = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable<Flag>
>DynamicDBRecord : Symbol(DynamicDBRecord, Decl(keyofAndIndexedAccess.ts, 578, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 580, 21))
>dynamicField : Symbol(dynamicField, Decl(keyofAndIndexedAccess.ts, 580, 46))
>dynamicField : Symbol(dynamicField, Decl(keyofAndIndexedAccess.ts, 580, 73))
>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 565, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 580, 21))
>DynamicDBRecord : Symbol(DynamicDBRecord, Decl(keyofAndIndexedAccess.ts, 587, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 589, 21))
>dynamicField : Symbol(dynamicField, Decl(keyofAndIndexedAccess.ts, 589, 46))
>dynamicField : Symbol(dynamicField, Decl(keyofAndIndexedAccess.ts, 589, 73))
>DBBoolTable : Symbol(DBBoolTable, Decl(keyofAndIndexedAccess.ts, 574, 70))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 589, 21))
function getFlagsFromDynamicRecord<Flag extends string>(record: DynamicDBRecord<Flag>, flags: Flag[]) {
>getFlagsFromDynamicRecord : Symbol(getFlagsFromDynamicRecord, Decl(keyofAndIndexedAccess.ts, 580, 117))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 581, 35))
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 581, 56))
>DynamicDBRecord : Symbol(DynamicDBRecord, Decl(keyofAndIndexedAccess.ts, 578, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 581, 35))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 581, 86))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 581, 35))
>getFlagsFromDynamicRecord : Symbol(getFlagsFromDynamicRecord, Decl(keyofAndIndexedAccess.ts, 589, 117))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 590, 35))
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 590, 56))
>DynamicDBRecord : Symbol(DynamicDBRecord, Decl(keyofAndIndexedAccess.ts, 587, 1))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 590, 35))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 590, 86))
>Flag : Symbol(Flag, Decl(keyofAndIndexedAccess.ts, 590, 35))
return record[flags[0]];
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 581, 56))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 581, 86))
>record : Symbol(record, Decl(keyofAndIndexedAccess.ts, 590, 56))
>flags : Symbol(flags, Decl(keyofAndIndexedAccess.ts, 590, 86))
}

View File

@@ -2345,6 +2345,55 @@ type Predicates<TaggedRecord> = {
>T : T
}
// Repros from #23592
type Example<T extends { [K in keyof T]: { prop: any } }> = { [K in keyof T]: T[K]["prop"] };
>Example : Example<T>
>T : T
>K : K
>T : T
>prop : any
>K : K
>T : T
>T : T
>K : K
type Result = Example<{ a: { prop: string }; b: { prop: number } }>;
>Result : Example<{ a: { prop: string; }; b: { prop: number; }; }>
>Example : Example<T>
>a : { prop: string; }
>prop : string
>b : { prop: number; }
>prop : number
type Helper2<T> = { [K in keyof T]: Extract<T[K], { prop: any }> };
>Helper2 : Helper2<T>
>T : T
>K : K
>T : T
>Extract : Extract<T, U>
>T : T
>K : K
>prop : any
type Example2<T> = { [K in keyof Helper2<T>]: Helper2<T>[K]["prop"] };
>Example2 : Example2<T>
>T : T
>K : K
>Helper2 : Helper2<T>
>T : T
>Helper2 : Helper2<T>
>T : T
>K : K
type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>;
>Result2 : Example2<{ 1: { prop: string; }; 2: { prop: number; }; }>
>Example2 : Example2<T>
>1 : { prop: string; }
>prop : string
>2 : { prop: number; }
>prop : number
// Repro from #23618
type DBBoolTable<K extends string> = { [k in K]: 0 | 1 }

View File

@@ -568,6 +568,15 @@ type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
}
// Repros from #23592
type Example<T extends { [K in keyof T]: { prop: any } }> = { [K in keyof T]: T[K]["prop"] };
type Result = Example<{ a: { prop: string }; b: { prop: number } }>;
type Helper2<T> = { [K in keyof T]: Extract<T[K], { prop: any }> };
type Example2<T> = { [K in keyof Helper2<T>]: Helper2<T>[K]["prop"] };
type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>;
// Repro from #23618
type DBBoolTable<K extends string> = { [k in K]: 0 | 1 }