mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Merge pull request #14562 from Microsoft/fixLookupTypeRelation
Fix indexed access type relations
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
86
tests/baselines/reference/indexedAccessTypeConstraints.js
Normal file
86
tests/baselines/reference/indexedAccessTypeConstraints.js
Normal 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;
|
||||
}
|
||||
109
tests/baselines/reference/indexedAccessTypeConstraints.symbols
Normal file
109
tests/baselines/reference/indexedAccessTypeConstraints.symbols
Normal 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))
|
||||
}
|
||||
|
||||
116
tests/baselines/reference/indexedAccessTypeConstraints.types
Normal file
116
tests/baselines/reference/indexedAccessTypeConstraints.types
Normal 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"]
|
||||
}
|
||||
|
||||
@@ -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'.
|
||||
}
|
||||
|
||||
36
tests/cases/compiler/indexedAccessTypeConstraints.ts
Normal file
36
tests/cases/compiler/indexedAccessTypeConstraints.ts
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user