Test assignability of indexed access types

This commit is contained in:
Nathan Shively-Sanders 2018-01-17 13:22:31 -08:00
parent 5c889299f4
commit 485ec34e8e
9 changed files with 377 additions and 47 deletions

View file

@ -552,6 +552,19 @@ class AnotherSampleClass<T> extends SampleClass<T & Foo> {
}
}
new AnotherSampleClass({});
// Positive repro from #17166
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
for (let key in t) {
key = k // ok, K ==> keyof T
t[key] = tk; // ok, T[K] ==> T[keyof T]
}
}
// # 21185
type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
}
//// [keyofAndIndexedAccess.js]
@ -928,6 +941,13 @@ var AnotherSampleClass = /** @class */ (function (_super) {
return AnotherSampleClass;
}(SampleClass));
new AnotherSampleClass({});
// Positive repro from #17166
function f3(t, k, tk) {
for (var key in t) {
key = k; // ok, K ==> keyof T
t[key] = tk; // ok, T[K] ==> T[keyof T]
}
}
//// [keyofAndIndexedAccess.d.ts]
@ -1188,3 +1208,7 @@ declare class AnotherSampleClass<T> extends SampleClass<T & Foo> {
constructor(props: T);
brokenMethod(): void;
}
declare function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void;
declare type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T];
};

View file

@ -1962,3 +1962,48 @@ class AnotherSampleClass<T> extends SampleClass<T & Foo> {
new AnotherSampleClass({});
>AnotherSampleClass : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 540, 54))
// Positive repro from #17166
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
>f3 : Symbol(f3, Decl(keyofAndIndexedAccess.ts, 552, 27))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 555, 14))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 555, 34))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 555, 39))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 555, 14))
>tk : Symbol(tk, Decl(keyofAndIndexedAccess.ts, 555, 45))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 555, 12))
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 555, 14))
for (let key in t) {
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 556, 12))
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 555, 34))
key = k // ok, K ==> keyof T
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 556, 12))
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 555, 39))
t[key] = tk; // ok, T[K] ==> T[keyof T]
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 555, 34))
>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 556, 12))
>tk : Symbol(tk, Decl(keyofAndIndexedAccess.ts, 555, 45))
}
}
// # 21185
type Predicates<TaggedRecord> = {
>Predicates : Symbol(Predicates, Decl(keyofAndIndexedAccess.ts, 560, 1))
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3))
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
>variant : Symbol(variant, Decl(keyofAndIndexedAccess.ts, 564, 30))
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
>variant : Symbol(variant, Decl(keyofAndIndexedAccess.ts, 564, 30))
>TaggedRecord : Symbol(TaggedRecord, Decl(keyofAndIndexedAccess.ts, 563, 16))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 564, 3))
}

View file

@ -2294,3 +2294,51 @@ new AnotherSampleClass({});
>AnotherSampleClass : typeof AnotherSampleClass
>{} : {}
// Positive repro from #17166
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
>f3 : <T, K extends keyof T>(t: T, k: K, tk: T[K]) => void
>T : T
>K : K
>T : T
>t : T
>T : T
>k : K
>K : K
>tk : T[K]
>T : T
>K : K
for (let key in t) {
>key : keyof T
>t : T
key = k // ok, K ==> keyof T
>key = k : K
>key : keyof T
>k : K
t[key] = tk; // ok, T[K] ==> T[keyof T]
>t[key] = tk : T[K]
>t[key] : T[keyof T]
>t : T
>key : keyof T
>tk : T[K]
}
}
// # 21185
type Predicates<TaggedRecord> = {
>Predicates : Predicates<TaggedRecord>
>TaggedRecord : TaggedRecord
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
>T : T
>TaggedRecord : TaggedRecord
>variant : TaggedRecord[keyof TaggedRecord]
>TaggedRecord : TaggedRecord
>TaggedRecord : TaggedRecord
>variant : any
>TaggedRecord : TaggedRecord
>T : T
}

View file

@ -27,11 +27,21 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(76,5): error
Type 'T' is not assignable to type 'T & U'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(77,5): error TS2322: Type 'keyof (T & U)' is not assignable to type 'keyof (T | U)'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(84,9): error TS2322: Type 'keyof T' is not assignable to type 'K'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(85,9): error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(86,9): error TS2322: Type 'keyof T' is not assignable to type 'K'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(88,9): error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
Type 'keyof T' is not assignable to type 'K'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(91,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(94,5): error TS2322: Type 'T[J]' is not assignable to type 'U[J]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(97,5): error TS2322: Type 'T[K]' is not assignable to type 'T[J]'.
Type 'K' is not assignable to type 'J'.
Type 'keyof T' is not assignable to type 'J'.
tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(100,5): error TS2322: Type 'T[K]' is not assignable to type 'U[J]'.
Type 'T' is not assignable to type 'U'.
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (27 errors) ====
==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (31 errors) ====
class Shape {
name: string;
width: number;
@ -167,15 +177,42 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(85,9): error
}
// Repro from #17166
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
for (let key in obj) {
function f3<T, K extends keyof T, U extends T, J extends K>(
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
for (let key in t) {
key = k // ok, K ==> keyof T
k = key // error, keyof T =/=> K
~
!!! error TS2322: Type 'keyof T' is not assignable to type 'K'.
value = obj[key]; // error, T[keyof T] =/=> T[K]
~~~~~
t[key] = tk; // ok, T[K] ==> T[keyof T]
tk = t[key]; // error, T[keyof T] =/=> T[K]
~~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
!!! error TS2322: Type 'keyof T' is not assignable to type 'K'.
}
}
tk = uk;
uk = tk; // error
~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
tj = uj;
uj = tj; // error
~~
!!! error TS2322: Type 'T[J]' is not assignable to type 'U[J]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
tk = tj;
tj = tk; // error
~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'T[J]'.
!!! error TS2322: Type 'K' is not assignable to type 'J'.
!!! error TS2322: Type 'keyof T' is not assignable to type 'J'.
tk = uj;
uj = tk; // error
~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[J]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}

View file

@ -80,13 +80,26 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
}
// Repro from #17166
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
for (let key in obj) {
function f3<T, K extends keyof T, U extends T, J extends K>(
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
for (let key in t) {
key = k // ok, K ==> keyof T
k = key // error, keyof T =/=> K
value = obj[key]; // error, T[keyof T] =/=> T[K]
t[key] = tk; // ok, T[K] ==> T[keyof T]
tk = t[key]; // error, T[keyof T] =/=> T[K]
}
}
tk = uk;
uk = tk; // error
tj = uj;
uj = tj; // error
tk = tj;
tj = tk; // error
tk = uj;
uj = tk; // error
}
//// [keyofAndIndexedAccessErrors.js]
@ -120,9 +133,19 @@ function f20(k1, k2, o1, o2) {
k2 = k1;
}
// Repro from #17166
function f3(obj, k, value) {
for (var key in obj) {
function f3(t, k, tk, u, j, uk, tj, uj) {
for (var key in t) {
key = k; // ok, K ==> keyof T
k = key; // error, keyof T =/=> K
value = obj[key]; // error, T[keyof T] =/=> T[K]
t[key] = tk; // ok, T[K] ==> T[keyof T]
tk = t[key]; // error, T[keyof T] =/=> T[K]
}
tk = uk;
uk = tk; // error
tj = uj;
uj = tj; // error
tk = tj;
tj = tk; // error
tk = uj;
uj = tk; // error
}

View file

@ -270,32 +270,90 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
}
// Repro from #17166
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
function f3<T, K extends keyof T, U extends T, J extends K>(
>f3 : Symbol(f3, Decl(keyofAndIndexedAccessErrors.ts, 78, 1))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>obj : Symbol(obj, Decl(keyofAndIndexedAccessErrors.ts, 81, 34))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 81, 41))
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
>value : Symbol(value, Decl(keyofAndIndexedAccessErrors.ts, 81, 47))
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
for (let key in obj) {
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 82, 12))
>obj : Symbol(obj, Decl(keyofAndIndexedAccessErrors.ts, 81, 34))
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9))
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
>u : Symbol(u, Decl(keyofAndIndexedAccessErrors.ts, 82, 25))
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
>j : Symbol(j, Decl(keyofAndIndexedAccessErrors.ts, 82, 31))
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37))
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 81, 14))
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 81, 12))
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
>U : Symbol(U, Decl(keyofAndIndexedAccessErrors.ts, 81, 33))
>J : Symbol(J, Decl(keyofAndIndexedAccessErrors.ts, 81, 46))
for (let key in t) {
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
key = k // ok, K ==> keyof T
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9))
k = key // error, keyof T =/=> K
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 81, 41))
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 82, 12))
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 82, 9))
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
value = obj[key]; // error, T[keyof T] =/=> T[K]
>value : Symbol(value, Decl(keyofAndIndexedAccessErrors.ts, 81, 47))
>obj : Symbol(obj, Decl(keyofAndIndexedAccessErrors.ts, 81, 34))
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 82, 12))
t[key] = tk; // ok, T[K] ==> T[keyof T]
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
tk = t[key]; // error, T[keyof T] =/=> T[K]
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
>t : Symbol(t, Decl(keyofAndIndexedAccessErrors.ts, 81, 60))
>key : Symbol(key, Decl(keyofAndIndexedAccessErrors.ts, 83, 12))
}
tk = uk;
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37))
uk = tk; // error
>uk : Symbol(uk, Decl(keyofAndIndexedAccessErrors.ts, 82, 37))
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
tj = uj;
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
uj = tj; // error
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
tk = tj;
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
tj = tk; // error
>tj : Symbol(tj, Decl(keyofAndIndexedAccessErrors.ts, 82, 47))
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
tk = uj;
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
uj = tk; // error
>uj : Symbol(uj, Decl(keyofAndIndexedAccessErrors.ts, 82, 57))
>tk : Symbol(tk, Decl(keyofAndIndexedAccessErrors.ts, 82, 15))
}

View file

@ -301,35 +301,104 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
}
// Repro from #17166
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
>f3 : <T, K extends keyof T>(obj: T, k: K, value: T[K]) => void
function f3<T, K extends keyof T, U extends T, J extends K>(
>f3 : <T, K extends keyof T, U extends T, J extends K>(t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]) => void
>T : T
>K : K
>T : T
>obj : T
>U : U
>T : T
>J : J
>K : K
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
>t : T
>T : T
>k : K
>K : K
>value : T[K]
>tk : T[K]
>T : T
>K : K
>u : U
>U : U
>j : J
>J : J
>uk : U[K]
>U : U
>K : K
>tj : T[J]
>T : T
>J : J
>uj : U[J]
>U : U
>J : J
for (let key in obj) {
for (let key in t) {
>key : keyof T
>obj : T
>t : T
key = k // ok, K ==> keyof T
>key = k : K
>key : keyof T
>k : K
k = key // error, keyof T =/=> K
>k = key : keyof T
>k : K
>key : keyof T
value = obj[key]; // error, T[keyof T] =/=> T[K]
>value = obj[key] : T[keyof T]
>value : T[K]
>obj[key] : T[keyof T]
>obj : T
t[key] = tk; // ok, T[K] ==> T[keyof T]
>t[key] = tk : T[K]
>t[key] : T[keyof T]
>t : T
>key : keyof T
>tk : T[K]
tk = t[key]; // error, T[keyof T] =/=> T[K]
>tk = t[key] : T[keyof T]
>tk : T[K]
>t[key] : T[keyof T]
>t : T
>key : keyof T
}
tk = uk;
>tk = uk : U[K]
>tk : T[K]
>uk : U[K]
uk = tk; // error
>uk = tk : T[K]
>uk : U[K]
>tk : T[K]
tj = uj;
>tj = uj : U[J]
>tj : T[J]
>uj : U[J]
uj = tj; // error
>uj = tj : T[J]
>uj : U[J]
>tj : T[J]
tk = tj;
>tk = tj : T[J]
>tk : T[K]
>tj : T[J]
tj = tk; // error
>tj = tk : T[K]
>tj : T[J]
>tk : T[K]
tk = uj;
>tk = uj : U[J]
>tk : T[K]
>uj : U[J]
uj = tk; // error
>uj = tk : T[K]
>uj : U[J]
>tk : T[K]
}

View file

@ -554,3 +554,16 @@ class AnotherSampleClass<T> extends SampleClass<T & Foo> {
}
}
new AnotherSampleClass({});
// Positive repro from #17166
function f3<T, K extends keyof T>(t: T, k: K, tk: T[K]): void {
for (let key in t) {
key = k // ok, K ==> keyof T
t[key] = tk; // ok, T[K] ==> T[keyof T]
}
}
// # 21185
type Predicates<TaggedRecord> = {
[T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T]
}

View file

@ -79,10 +79,23 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
}
// Repro from #17166
function f3<T, K extends keyof T>(obj: T, k: K, value: T[K]): void {
for (let key in obj) {
function f3<T, K extends keyof T, U extends T, J extends K>(
t: T, k: K, tk: T[K], u: U, j: J, uk: U[K], tj: T[J], uj: U[J]): void {
for (let key in t) {
key = k // ok, K ==> keyof T
k = key // error, keyof T =/=> K
value = obj[key]; // error, T[keyof T] =/=> T[K]
t[key] = tk; // ok, T[K] ==> T[keyof T]
tk = t[key]; // error, T[keyof T] =/=> T[K]
}
}
tk = uk;
uk = tk; // error
tj = uj;
uj = tj; // error
tk = tj;
tj = tk; // error
tk = uj;
uj = tk; // error
}