Merge pull request #14562 from Microsoft/fixLookupTypeRelation

Fix indexed access type relations
This commit is contained in:
Anders Hejlsberg
2017-03-09 10:51:29 -10:00
committed by GitHub
6 changed files with 419 additions and 32 deletions

View File

@@ -3973,7 +3973,7 @@ namespace ts {
return true;
}
if (type.flags & TypeFlags.TypeVariable) {
const constraint = getBaseConstraintOfType(<TypeVariable>type);
const constraint = getBaseConstraintOfType(type);
return constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint);
}
return false;
@@ -4989,16 +4989,32 @@ namespace ts {
}
function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) : getBaseConstraintOfType(type);
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) :
type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(<IndexedAccessType>type) :
getBaseConstraintOfType(type);
}
function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type {
return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined;
}
function getBaseConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
const constraint = getResolvedBaseConstraint(type);
return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
const baseObjectType = getBaseConstraintOfType(type.objectType);
const baseIndexType = getBaseConstraintOfType(type.indexType);
return baseObjectType || baseIndexType ? getIndexedAccessType(baseObjectType || type.objectType, baseIndexType || type.indexType) : undefined;
}
function getBaseConstraintOfType(type: Type): Type {
if (type.flags & (TypeFlags.TypeVariable | TypeFlags.UnionOrIntersection)) {
const constraint = getResolvedBaseConstraint(<TypeVariable | UnionOrIntersectionType>type);
if (constraint !== noConstraintType && constraint !== circularConstraintType) {
return constraint;
}
}
else if (type.flags & TypeFlags.Index) {
return stringType;
}
return undefined;
}
function hasNonCircularBaseConstraint(type: TypeVariable): boolean {
@@ -5096,7 +5112,7 @@ namespace ts {
* type itself. Note that the apparent type of a union type is the union type itself.
*/
function getApparentType(type: Type): Type {
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(<TypeVariable>type) || emptyObjectType : type;
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(type) || emptyObjectType : type;
return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
t.flags & TypeFlags.StringLike ? globalStringType :
t.flags & TypeFlags.NumberLike ? globalNumberType :
@@ -7921,7 +7937,7 @@ namespace ts {
}
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
// A is the apparent type of S.
const constraint = getBaseConstraintOfType(<IndexedAccessType>target);
const constraint = getBaseConstraintOfType(target);
if (constraint) {
if (result = isRelatedTo(source, constraint, reportErrors)) {
errorInfo = saveErrorInfo;
@@ -7961,7 +7977,7 @@ namespace ts {
else if (source.flags & TypeFlags.IndexedAccess) {
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
// A is the apparent type of S.
const constraint = getBaseConstraintOfType(<IndexedAccessType>source);
const constraint = getConstraintOfType(<IndexedAccessType>source);
if (constraint) {
if (result = isRelatedTo(constraint, target, reportErrors)) {
errorInfo = saveErrorInfo;
@@ -9874,7 +9890,7 @@ namespace ts {
return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts;
}
if (flags & TypeFlags.TypeVariable) {
return getTypeFacts(getBaseConstraintOfType(<TypeVariable>type) || emptyObjectType);
return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType);
}
if (flags & TypeFlags.UnionOrIntersection) {
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
@@ -10686,7 +10702,7 @@ namespace ts {
return targetType;
}
if (type.flags & TypeFlags.TypeVariable) {
const constraint = getBaseConstraintOfType(<TypeVariable>type) || anyType;
const constraint = getBaseConstraintOfType(type) || anyType;
if (isTypeSubtypeOf(targetType, constraint)) {
return getIntersectionType([type, targetType]);
}
@@ -16234,7 +16250,7 @@ namespace ts {
function isLiteralContextualType(contextualType: Type) {
if (contextualType) {
if (contextualType.flags & TypeFlags.TypeVariable) {
const constraint = getBaseConstraintOfType(<TypeVariable>contextualType) || emptyObjectType;
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
// If the type parameter is constrained to the base primitive type we're checking for,
// consider this a literal context. For example, given a type parameter 'T extends string',
// this causes us to infer string literal types for T.
@@ -17124,7 +17140,7 @@ namespace ts {
// Check if we're indexing with a numeric type and the object type is a generic
// type with a constraint that has a numeric index signature.
if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeOfKind(indexType, TypeFlags.NumberLike)) {
const constraint = getBaseConstraintOfType(<TypeVariable | UnionOrIntersectionType>objectType);
const constraint = getBaseConstraintOfType(objectType);
if (constraint && getIndexInfoOfType(constraint, IndexKind.Number)) {
return type;
}

View File

@@ -0,0 +1,86 @@
//// [indexedAccessTypeConstraints.ts]
// Repro from #14557
interface IData<T> {
content: T;
}
type Data<T> = {
get: <K extends keyof T>(prop: K) => T[K];
};
class Parent<M> {
private data: Data<M>;
getData(): Data<M> {
return this.data;
}
}
export class Foo<C> extends Parent<IData<C>> {
getContent(): C {
return this.getData().get('content');
}
}
export class Bar<C, T extends IData<C>> extends Parent<T> {
getContent(): C {
return this.getData().get('content');
}
}
// Repro from #14557
function foo<C, T extends { content: C }>(x: C, y: T['content']) {
x = y;
}
//// [indexedAccessTypeConstraints.js]
// Repro from #14557
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Parent = (function () {
function Parent() {
}
Parent.prototype.getData = function () {
return this.data;
};
return Parent;
}());
var Foo = (function (_super) {
__extends(Foo, _super);
function Foo() {
return _super !== null && _super.apply(this, arguments) || this;
}
Foo.prototype.getContent = function () {
return this.getData().get('content');
};
return Foo;
}(Parent));
exports.Foo = Foo;
var Bar = (function (_super) {
__extends(Bar, _super);
function Bar() {
return _super !== null && _super.apply(this, arguments) || this;
}
Bar.prototype.getContent = function () {
return this.getData().get('content');
};
return Bar;
}(Parent));
exports.Bar = Bar;
// Repro from #14557
function foo(x, y) {
x = y;
}

View File

@@ -0,0 +1,109 @@
=== tests/cases/compiler/indexedAccessTypeConstraints.ts ===
// Repro from #14557
interface IData<T> {
>IData : Symbol(IData, Decl(indexedAccessTypeConstraints.ts, 0, 0))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 3, 16))
content: T;
>content : Symbol(IData.content, Decl(indexedAccessTypeConstraints.ts, 3, 20))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 3, 16))
}
type Data<T> = {
>Data : Symbol(Data, Decl(indexedAccessTypeConstraints.ts, 5, 1))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 7, 10))
get: <K extends keyof T>(prop: K) => T[K];
>get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 7, 16))
>K : Symbol(K, Decl(indexedAccessTypeConstraints.ts, 8, 10))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 7, 10))
>prop : Symbol(prop, Decl(indexedAccessTypeConstraints.ts, 8, 29))
>K : Symbol(K, Decl(indexedAccessTypeConstraints.ts, 8, 10))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 7, 10))
>K : Symbol(K, Decl(indexedAccessTypeConstraints.ts, 8, 10))
};
class Parent<M> {
>Parent : Symbol(Parent, Decl(indexedAccessTypeConstraints.ts, 9, 2))
>M : Symbol(M, Decl(indexedAccessTypeConstraints.ts, 11, 13))
private data: Data<M>;
>data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 11, 17))
>Data : Symbol(Data, Decl(indexedAccessTypeConstraints.ts, 5, 1))
>M : Symbol(M, Decl(indexedAccessTypeConstraints.ts, 11, 13))
getData(): Data<M> {
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 12, 26))
>Data : Symbol(Data, Decl(indexedAccessTypeConstraints.ts, 5, 1))
>M : Symbol(M, Decl(indexedAccessTypeConstraints.ts, 11, 13))
return this.data;
>this.data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 11, 17))
>this : Symbol(Parent, Decl(indexedAccessTypeConstraints.ts, 9, 2))
>data : Symbol(Parent.data, Decl(indexedAccessTypeConstraints.ts, 11, 17))
}
}
export class Foo<C> extends Parent<IData<C>> {
>Foo : Symbol(Foo, Decl(indexedAccessTypeConstraints.ts, 16, 1))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 18, 17))
>Parent : Symbol(Parent, Decl(indexedAccessTypeConstraints.ts, 9, 2))
>IData : Symbol(IData, Decl(indexedAccessTypeConstraints.ts, 0, 0))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 18, 17))
getContent(): C {
>getContent : Symbol(Foo.getContent, Decl(indexedAccessTypeConstraints.ts, 18, 46))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 18, 17))
return this.getData().get('content');
>this.getData().get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 7, 16))
>this.getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 12, 26))
>this : Symbol(Foo, Decl(indexedAccessTypeConstraints.ts, 16, 1))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 12, 26))
>get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 7, 16))
}
}
export class Bar<C, T extends IData<C>> extends Parent<T> {
>Bar : Symbol(Bar, Decl(indexedAccessTypeConstraints.ts, 22, 1))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 24, 17))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 24, 19))
>IData : Symbol(IData, Decl(indexedAccessTypeConstraints.ts, 0, 0))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 24, 17))
>Parent : Symbol(Parent, Decl(indexedAccessTypeConstraints.ts, 9, 2))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 24, 19))
getContent(): C {
>getContent : Symbol(Bar.getContent, Decl(indexedAccessTypeConstraints.ts, 24, 59))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 24, 17))
return this.getData().get('content');
>this.getData().get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 7, 16))
>this.getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 12, 26))
>this : Symbol(Bar, Decl(indexedAccessTypeConstraints.ts, 22, 1))
>getData : Symbol(Parent.getData, Decl(indexedAccessTypeConstraints.ts, 12, 26))
>get : Symbol(get, Decl(indexedAccessTypeConstraints.ts, 7, 16))
}
}
// Repro from #14557
function foo<C, T extends { content: C }>(x: C, y: T['content']) {
>foo : Symbol(foo, Decl(indexedAccessTypeConstraints.ts, 28, 1))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 32, 13))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 32, 15))
>content : Symbol(content, Decl(indexedAccessTypeConstraints.ts, 32, 27))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 32, 13))
>x : Symbol(x, Decl(indexedAccessTypeConstraints.ts, 32, 42))
>C : Symbol(C, Decl(indexedAccessTypeConstraints.ts, 32, 13))
>y : Symbol(y, Decl(indexedAccessTypeConstraints.ts, 32, 47))
>T : Symbol(T, Decl(indexedAccessTypeConstraints.ts, 32, 15))
x = y;
>x : Symbol(x, Decl(indexedAccessTypeConstraints.ts, 32, 42))
>y : Symbol(y, Decl(indexedAccessTypeConstraints.ts, 32, 47))
}

View File

@@ -0,0 +1,116 @@
=== tests/cases/compiler/indexedAccessTypeConstraints.ts ===
// Repro from #14557
interface IData<T> {
>IData : IData<T>
>T : T
content: T;
>content : T
>T : T
}
type Data<T> = {
>Data : { get: <K extends keyof T>(prop: K) => T[K]; }
>T : T
get: <K extends keyof T>(prop: K) => T[K];
>get : <K extends keyof T>(prop: K) => T[K]
>K : K
>T : T
>prop : K
>K : K
>T : T
>K : K
};
class Parent<M> {
>Parent : Parent<M>
>M : M
private data: Data<M>;
>data : { get: <K extends keyof M>(prop: K) => M[K]; }
>Data : { get: <K extends keyof T>(prop: K) => T[K]; }
>M : M
getData(): Data<M> {
>getData : () => { get: <K extends keyof M>(prop: K) => M[K]; }
>Data : { get: <K extends keyof T>(prop: K) => T[K]; }
>M : M
return this.data;
>this.data : { get: <K extends keyof M>(prop: K) => M[K]; }
>this : this
>data : { get: <K extends keyof M>(prop: K) => M[K]; }
}
}
export class Foo<C> extends Parent<IData<C>> {
>Foo : Foo<C>
>C : C
>Parent : Parent<IData<C>>
>IData : IData<T>
>C : C
getContent(): C {
>getContent : () => C
>C : C
return this.getData().get('content');
>this.getData().get('content') : C
>this.getData().get : <K extends "content">(prop: K) => IData<C>[K]
>this.getData() : { get: <K extends "content">(prop: K) => IData<C>[K]; }
>this.getData : () => { get: <K extends "content">(prop: K) => IData<C>[K]; }
>this : this
>getData : () => { get: <K extends "content">(prop: K) => IData<C>[K]; }
>get : <K extends "content">(prop: K) => IData<C>[K]
>'content' : "content"
}
}
export class Bar<C, T extends IData<C>> extends Parent<T> {
>Bar : Bar<C, T>
>C : C
>T : T
>IData : IData<T>
>C : C
>Parent : Parent<T>
>T : T
getContent(): C {
>getContent : () => C
>C : C
return this.getData().get('content');
>this.getData().get('content') : T["content"]
>this.getData().get : <K extends keyof T>(prop: K) => T[K]
>this.getData() : { get: <K extends keyof T>(prop: K) => T[K]; }
>this.getData : () => { get: <K extends keyof T>(prop: K) => T[K]; }
>this : this
>getData : () => { get: <K extends keyof T>(prop: K) => T[K]; }
>get : <K extends keyof T>(prop: K) => T[K]
>'content' : "content"
}
}
// Repro from #14557
function foo<C, T extends { content: C }>(x: C, y: T['content']) {
>foo : <C, T extends { content: C; }>(x: C, y: T["content"]) => void
>C : C
>T : T
>content : C
>C : C
>x : C
>C : C
>y : T["content"]
>T : T
x = y;
>x = y : T["content"]
>x : C
>y : T["content"]
}

View File

@@ -1,14 +1,18 @@
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(12,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(17,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(21,5): error TS2536: Type 'keyof U' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(22,5): error TS2322: Type 'T[keyof U]' is not assignable to type 'U[keyof U]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[keyof U]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(22,12): error TS2536: Type 'keyof U' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(26,5): error TS2536: Type 'K' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(27,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(27,12): error TS2536: Type 'K' cannot be used to index type 'T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(31,5): error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
@@ -17,13 +21,19 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(36,5): error TS2
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(41,5): error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
Type 'undefined' is not assignable to type 'T[keyof T]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(42,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'.
Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
Type 'T[string]' is not assignable to type 'U[keyof T]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
Type 'undefined' is not assignable to type 'T[K]'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(47,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'.
Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[K] | undefined'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T[K]' is not assignable to type 'U[K]'.
Type 'T[string]' is not assignable to type 'U[K]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(52,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(57,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(62,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
@@ -33,7 +43,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(76,5): error TS2
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(126,5): error TS2322: Type 'Partial<U>' is not assignable to type 'Identity<U>'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(142,5): error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof T]: U[P]; }'.
Type 'T[P]' is not assignable to type 'U[P]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[P]'.
Type 'T' is not assignable to type 'U'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(147,5): error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof U]: U[P]; }'.
Type 'keyof U' is not assignable to type 'keyof T'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(152,5): error TS2322: Type '{ [P in K]: T[P]; }' is not assignable to type '{ [P in keyof T]: T[P]; }'.
@@ -44,7 +55,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(162,5): error TS
Type 'keyof T' is not assignable to type 'K'.
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS2322: Type '{ [P in K]: T[P]; }' is not assignable to type '{ [P in K]: U[P]; }'.
Type 'T[P]' is not assignable to type 'U[P]'.
Type 'T' is not assignable to type 'U'.
Type 'T[string]' is not assignable to type 'U[P]'.
Type 'T' is not assignable to type 'U'.
==== tests/cases/conformance/types/mapped/mappedTypeRelationships.ts (27 errors) ====
@@ -62,7 +74,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f4<T, U extends T, K extends keyof T>(x: T, y: U, k: K) {
@@ -70,7 +83,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f5<T, U extends T>(x: T, y: U, k: keyof U) {
@@ -80,7 +94,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof U]' is not assignable to type 'U[keyof U]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof U]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
~~~~
!!! error TS2536: Type 'keyof U' cannot be used to index type 'T'.
}
@@ -92,7 +107,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
~~~~
!!! error TS2536: Type 'K' cannot be used to index type 'T'.
}
@@ -121,8 +137,11 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f13<T, U extends T, K extends keyof T>(x: T, y: Partial<U>, k: K) {
@@ -133,8 +152,11 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
y[k] = x[k]; // Error
~~~~
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K] | undefined'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f20<T>(x: T, y: Readonly<T>, k: keyof T) {
@@ -247,7 +269,8 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
~
!!! error TS2322: Type '{ [P in keyof T]: T[P]; }' is not assignable to type '{ [P in keyof T]: U[P]; }'.
!!! error TS2322: Type 'T[P]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}
function f72<T, U extends T>(x: { [P in keyof T]: T[P] }, y: { [P in keyof U]: U[P] }) {
@@ -288,6 +311,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(167,5): error TS
~
!!! error TS2322: Type '{ [P in K]: T[P]; }' is not assignable to type '{ [P in K]: U[P]; }'.
!!! error TS2322: Type 'T[P]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[P]'.
!!! error TS2322: Type 'T' is not assignable to type 'U'.
}

View File

@@ -0,0 +1,36 @@
// @strict: true
// Repro from #14557
interface IData<T> {
content: T;
}
type Data<T> = {
get: <K extends keyof T>(prop: K) => T[K];
};
class Parent<M> {
private data: Data<M>;
getData(): Data<M> {
return this.data;
}
}
export class Foo<C> extends Parent<IData<C>> {
getContent(): C {
return this.getData().get('content');
}
}
export class Bar<C, T extends IData<C>> extends Parent<T> {
getContent(): C {
return this.getData().get('content');
}
}
// Repro from #14557
function foo<C, T extends { content: C }>(x: C, y: T['content']) {
x = y;
}