Merge pull request #18042 from Microsoft/fixMappedTypeIndexedAccess
Defer mapped type indexed access transformations
This commit is contained in:
commit
555a742d16
|
@ -7612,22 +7612,6 @@ namespace ts {
|
|||
return anyType;
|
||||
}
|
||||
|
||||
function getIndexedAccessForMappedType(type: MappedType, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode) {
|
||||
if (accessNode) {
|
||||
// Check if the index type is assignable to 'keyof T' for the object type.
|
||||
if (!isTypeAssignableTo(indexType, getIndexType(type))) {
|
||||
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(type));
|
||||
return unknownType;
|
||||
}
|
||||
if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) && type.declaration.readonlyToken) {
|
||||
error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(type));
|
||||
}
|
||||
}
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(type)], [indexType]);
|
||||
const templateMapper = type.mapper ? combineTypeMappers(type.mapper, mapper) : mapper;
|
||||
return instantiateType(getTemplateTypeFromMappedType(type), templateMapper);
|
||||
}
|
||||
|
||||
function isGenericObjectType(type: Type): boolean {
|
||||
return type.flags & TypeFlags.TypeVariable ? true :
|
||||
getObjectFlags(type) & ObjectFlags.Mapped ? isGenericIndexType(getConstraintTypeFromMappedType(<MappedType>type)) :
|
||||
|
@ -7653,12 +7637,14 @@ namespace ts {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
|
||||
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
|
||||
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
|
||||
// access types with default property values as expressed by D.
|
||||
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
|
||||
// undefined if no transformation is possible.
|
||||
function getTransformedIndexedAccessType(type: IndexedAccessType): Type {
|
||||
const objectType = type.objectType;
|
||||
// Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or
|
||||
// more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a
|
||||
// transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed
|
||||
// access types with default property values as expressed by D.
|
||||
if (objectType.flags & TypeFlags.Intersection && isGenericObjectType(objectType) && some((<IntersectionType>objectType).types, isStringIndexOnlyType)) {
|
||||
const regularTypes: Type[] = [];
|
||||
const stringIndexTypes: Type[] = [];
|
||||
|
@ -7675,20 +7661,23 @@ namespace ts {
|
|||
getIntersectionType(stringIndexTypes)
|
||||
]);
|
||||
}
|
||||
// If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper
|
||||
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
|
||||
// construct the type Box<T[X]>.
|
||||
if (isGenericMappedType(objectType)) {
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(<MappedType>objectType)], [type.indexType]);
|
||||
const objectTypeMapper = (<MappedType>objectType).mapper;
|
||||
const templateMapper = objectTypeMapper ? combineTypeMappers(objectTypeMapper, mapper) : mapper;
|
||||
return instantiateType(getTemplateTypeFromMappedType(<MappedType>objectType), templateMapper);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode): Type {
|
||||
// If the object type is a mapped type { [P in K]: E }, where K is generic, we instantiate E using a mapper
|
||||
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
|
||||
// construct the type Box<T[X]>.
|
||||
if (isGenericMappedType(objectType)) {
|
||||
return getIndexedAccessForMappedType(<MappedType>objectType, indexType, accessNode);
|
||||
}
|
||||
// Otherwise, if the index type is generic, or if the object type is generic and doesn't originate in an
|
||||
// expression, we are performing a higher-order index access where we cannot meaningfully access the properties
|
||||
// of the object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates
|
||||
// in an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]'
|
||||
// If the index type is generic, or if the object type is generic and doesn't originate in an expression,
|
||||
// we are performing a higher-order index access where we cannot meaningfully access the properties of the
|
||||
// object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in
|
||||
// an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]'
|
||||
// has always been resolved eagerly using the constraint type of 'this' at the given location.
|
||||
if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression) && isGenericObjectType(objectType)) {
|
||||
if (objectType.flags & TypeFlags.Any) {
|
||||
|
@ -9310,7 +9299,7 @@ namespace ts {
|
|||
else if (target.flags & TypeFlags.IndexedAccess) {
|
||||
// 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 = getConstraintOfType(<IndexedAccessType>target);
|
||||
const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>target);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
|
@ -9350,7 +9339,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 = getConstraintOfType(<IndexedAccessType>source);
|
||||
const constraint = getConstraintOfIndexedAccess(<IndexedAccessType>source);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(constraint, target, reportErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
|
@ -18839,6 +18828,10 @@ namespace ts {
|
|||
const objectType = (<IndexedAccessType>type).objectType;
|
||||
const indexType = (<IndexedAccessType>type).indexType;
|
||||
if (isTypeAssignableTo(indexType, getIndexType(objectType))) {
|
||||
if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
|
||||
getObjectFlags(objectType) & ObjectFlags.Mapped && (<MappedType>objectType).declaration.readonlyToken) {
|
||||
error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
// Check if we're indexing with a numeric type and if either object or index types
|
||||
|
|
|
@ -69,7 +69,7 @@ function boxify<T>(obj: T): Boxified<T> {
|
|||
|
||||
result[k] = box(obj[k]);
|
||||
>result[k] = box(obj[k]) : Box<T[keyof T]>
|
||||
>result[k] : Box<T[keyof T]>
|
||||
>result[k] : Boxified<T>[keyof T]
|
||||
>result : Boxified<T>
|
||||
>k : keyof T
|
||||
>box(obj[k]) : Box<T[keyof T]>
|
||||
|
@ -107,7 +107,7 @@ function unboxify<T>(obj: Boxified<T>): T {
|
|||
>k : keyof T
|
||||
>unbox(obj[k]) : T[keyof T]
|
||||
>unbox : <T>(x: Box<T>) => T
|
||||
>obj[k] : Box<T[keyof T]>
|
||||
>obj[k] : Boxified<T>[keyof T]
|
||||
>obj : Boxified<T>
|
||||
>k : keyof T
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ function assignBoxified<T>(obj: Boxified<T>, values: T) {
|
|||
obj[k].value = values[k];
|
||||
>obj[k].value = values[k] : T[keyof T]
|
||||
>obj[k].value : T[keyof T]
|
||||
>obj[k] : Box<T[keyof T]>
|
||||
>obj[k] : Boxified<T>[keyof T]
|
||||
>obj : Boxified<T>
|
||||
>k : keyof T
|
||||
>value : T[keyof T]
|
||||
|
|
|
@ -27,8 +27,8 @@ function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
|
|||
>obj : { [P in K]: T; }
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : T
|
||||
>obj[k1] : T
|
||||
>x1 : { [P in K]: T; }[K]
|
||||
>obj[k1] : { [P in K]: T; }[K]
|
||||
>obj : { [P in K]: T; }
|
||||
>k1 : K
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
|
|||
>obj : { [P in K]: T; }
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : T
|
||||
>obj[k2] : T
|
||||
>x2 : { [P in K]: T; }[K]
|
||||
>obj[k2] : { [P in K]: T; }[K]
|
||||
>obj : { [P in K]: T; }
|
||||
>k2 : K
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
|
|||
>obj : { [P in keyof T]: T[P]; }
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : T[keyof T]
|
||||
>obj[k1] : T[keyof T]
|
||||
>x1 : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>obj[k1] : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
>k1 : keyof T
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
|
|||
>obj : { [P in keyof T]: T[P]; }
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : T[keyof T]
|
||||
>obj[k2] : T[keyof T]
|
||||
>x2 : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>obj[k2] : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
>k2 : keyof T
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
|
|||
>obj : { [P in K]: T[P]; }
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : T[K]
|
||||
>obj[k1] : T[K]
|
||||
>x1 : { [P in K]: T[P]; }[K]
|
||||
>obj[k1] : { [P in K]: T[P]; }[K]
|
||||
>obj : { [P in K]: T[P]; }
|
||||
>k1 : K
|
||||
}
|
||||
|
@ -125,8 +125,8 @@ function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
|
|||
>obj : { [P in K]: T[P]; }
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : T[K]
|
||||
>obj[k2] : T[K]
|
||||
>x2 : { [P in K]: T[P]; }[K]
|
||||
>obj[k2] : { [P in K]: T[P]; }[K]
|
||||
>obj : { [P in K]: T[P]; }
|
||||
>k2 : K
|
||||
}
|
||||
|
|
|
@ -2194,7 +2194,7 @@ class Form<T> {
|
|||
|
||||
this.childFormFactories[prop](value)
|
||||
>this.childFormFactories[prop](value) : Form<T[K]>
|
||||
>this.childFormFactories[prop] : (v: T[K]) => Form<T[K]>
|
||||
>this.childFormFactories[prop] : { [K in keyof T]: (v: T[K]) => Form<T[K]>; }[K]
|
||||
>this.childFormFactories : { [K in keyof T]: (v: T[K]) => Form<T[K]>; }
|
||||
>this : this
|
||||
>childFormFactories : { [K in keyof T]: (v: T[K]) => Form<T[K]>; }
|
||||
|
|
49
tests/baselines/reference/mappedTypeIndexedAccess.errors.txt
Normal file
49
tests/baselines/reference/mappedTypeIndexedAccess.errors.txt
Normal file
|
@ -0,0 +1,49 @@
|
|||
tests/cases/compiler/mappedTypeIndexedAccess.ts(18,5): error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
|
||||
Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
|
||||
Types of property 'value' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/compiler/mappedTypeIndexedAccess.ts(24,5): error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
|
||||
Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
|
||||
Types of property 'value' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/mappedTypeIndexedAccess.ts (2 errors) ====
|
||||
// Repro from #15756
|
||||
|
||||
type Pairs<T> = {
|
||||
[TKey in keyof T]: {
|
||||
key: TKey;
|
||||
value: T[TKey];
|
||||
};
|
||||
};
|
||||
|
||||
type Pair<T> = Pairs<T>[keyof T];
|
||||
|
||||
type FooBar = {
|
||||
foo: string;
|
||||
bar: number;
|
||||
};
|
||||
|
||||
// Error expected here
|
||||
let pair1: Pair<FooBar> = {
|
||||
~~~~~
|
||||
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
|
||||
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
|
||||
!!! error TS2322: Types of property 'value' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
||||
|
||||
// Error expected here
|
||||
let pair2: Pairs<FooBar>[keyof FooBar] = {
|
||||
~~~~~
|
||||
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; } | { key: "bar"; value: number; }'.
|
||||
!!! error TS2322: Type '{ key: "foo"; value: number; }' is not assignable to type '{ key: "foo"; value: string; }'.
|
||||
!!! error TS2322: Types of property 'value' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
||||
|
43
tests/baselines/reference/mappedTypeIndexedAccess.js
Normal file
43
tests/baselines/reference/mappedTypeIndexedAccess.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
//// [mappedTypeIndexedAccess.ts]
|
||||
// Repro from #15756
|
||||
|
||||
type Pairs<T> = {
|
||||
[TKey in keyof T]: {
|
||||
key: TKey;
|
||||
value: T[TKey];
|
||||
};
|
||||
};
|
||||
|
||||
type Pair<T> = Pairs<T>[keyof T];
|
||||
|
||||
type FooBar = {
|
||||
foo: string;
|
||||
bar: number;
|
||||
};
|
||||
|
||||
// Error expected here
|
||||
let pair1: Pair<FooBar> = {
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
||||
|
||||
// Error expected here
|
||||
let pair2: Pairs<FooBar>[keyof FooBar] = {
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
||||
|
||||
|
||||
//// [mappedTypeIndexedAccess.js]
|
||||
"use strict";
|
||||
// Repro from #15756
|
||||
// Error expected here
|
||||
var pair1 = {
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
||||
// Error expected here
|
||||
var pair2 = {
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
|
@ -26,17 +26,64 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(26,5): error TS2
|
|||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(26,12): error TS2536: Type 'K' cannot be used to index type 'T'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(30,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]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(35,5): error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(40,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]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(41,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'.
|
||||
Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(30,5): error TS2322: Type 'Partial<T>[keyof T]' is not assignable to type 'T[keyof T]'.
|
||||
Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
|
||||
Type 'undefined' is not assignable to type 'T[keyof T]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
Type 'Partial<T>[keyof T]' is not assignable to type 'T[string]'.
|
||||
Type 'T[keyof T] | undefined' is not assignable to type 'T[string]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(35,5): error TS2322: Type 'Partial<T>[K]' is not assignable to type 'T[K]'.
|
||||
Type 'T[K] | undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
Type 'Partial<T>[K]' is not assignable to type 'T[string]'.
|
||||
Type 'T[K] | undefined' is not assignable to type 'T[string]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(40,5): error TS2322: Type 'Partial<U>[keyof T]' is not assignable to type 'T[keyof T]'.
|
||||
Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
|
||||
Type 'undefined' is not assignable to type 'T[keyof T]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
Type 'Partial<U>[keyof T]' is not assignable to type 'T[string]'.
|
||||
Type 'U[keyof T] | undefined' is not assignable to type 'T[string]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(41,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'Partial<U>[keyof T]'.
|
||||
Type 'T[string]' is not assignable to type 'Partial<U>[keyof T]'.
|
||||
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] | undefined'.
|
||||
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[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(45,5): error TS2322: Type 'Partial<U>[K]' is not assignable to type 'T[K]'.
|
||||
Type 'U[K] | undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
Type 'Partial<U>[K]' is not assignable to type 'T[string]'.
|
||||
Type 'U[K] | undefined' is not assignable to type 'T[string]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2322: Type 'T[K]' is not assignable to type 'Partial<U>[K]'.
|
||||
Type 'T[string]' is not assignable to type 'Partial<U>[K]'.
|
||||
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] | undefined'.
|
||||
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[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(51,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(56,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'Readonly<U>[keyof T]'.
|
||||
Type 'T[string]' is not assignable to type 'Readonly<U>[keyof T]'.
|
||||
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]'.
|
||||
|
@ -44,11 +91,9 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(41,5): error TS2
|
|||
Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(45,5): error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[K]'.
|
||||
Type 'undefined' is not assignable to type 'T[string]'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'.
|
||||
Type 'T[string]' is not assignable to type 'U[K] | undefined'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2322: Type 'T[K]' is not assignable to type 'Readonly<U>[K]'.
|
||||
Type 'T[string]' is not assignable to type 'Readonly<U>[K]'.
|
||||
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]'.
|
||||
|
@ -56,21 +101,6 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2
|
|||
Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(51,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(56,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2322: 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[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
|
||||
Type 'T[string]' is not assignable to type 'U[K]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(72,5): error TS2322: Type 'Partial<T>' is not assignable to type 'T'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(78,5): error TS2322: Type 'Partial<Thing>' is not assignable to type 'Partial<T>'.
|
||||
|
@ -168,57 +198,81 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
|||
function f10<T>(x: T, y: Partial<T>, k: keyof T) {
|
||||
x[k] = y[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<T>[keyof T]' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<T>[keyof T]' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'T[keyof T] | undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
y[k] = x[k];
|
||||
}
|
||||
|
||||
function f11<T, K extends keyof T>(x: T, y: Partial<T>, k: K) {
|
||||
x[k] = y[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<T>[K]' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<T>[K]' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'T[K] | undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
y[k] = x[k];
|
||||
}
|
||||
|
||||
function f12<T, U extends T>(x: T, y: Partial<U>, k: keyof T) {
|
||||
x[k] = y[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<U>[keyof T]' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[keyof T]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<U>[keyof T]' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'U[keyof T] | undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
y[k] = x[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'.
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'Partial<U>[keyof T]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'Partial<U>[keyof T]'.
|
||||
!!! 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] | undefined'.
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! 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) {
|
||||
x[k] = y[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<U>[K]' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[K]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'Partial<U>[K]' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[string]'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'T[string]'.
|
||||
y[k] = x[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'.
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'Partial<U>[K]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'Partial<U>[K]'.
|
||||
!!! 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] | undefined'.
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
}
|
||||
|
||||
function f20<T>(x: T, y: Readonly<T>, k: keyof T) {
|
||||
|
@ -239,12 +293,15 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
|||
x[k] = y[k];
|
||||
y[k] = x[k]; // Error
|
||||
~~~~
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'Readonly<U>[keyof T]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'Readonly<U>[keyof T]'.
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
~~~~
|
||||
!!! error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
}
|
||||
|
@ -253,12 +310,15 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
|||
x[k] = y[k];
|
||||
y[k] = x[k]; // Error
|
||||
~~~~
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'Readonly<U>[K]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'Readonly<U>[K]'.
|
||||
!!! 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[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
~~~~
|
||||
!!! error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ function boxify<T>(obj: T): Boxified<T> {
|
|||
|
||||
result[k] = { value: obj[k] };
|
||||
>result[k] = { value: obj[k] } : { value: T[keyof T]; }
|
||||
>result[k] : Box<T[keyof T]>
|
||||
>result[k] : Boxified<T>[keyof T]
|
||||
>result : Boxified<T>
|
||||
>k : keyof T
|
||||
>{ value: obj[k] } : { value: T[keyof T]; }
|
||||
|
|
|
@ -84,15 +84,15 @@ function fun<T>(item: { [P in keyof T]: T[P] }) {
|
|||
>item : { [P in keyof T]: T[P]; }
|
||||
|
||||
const value = item[key];
|
||||
>value : T[keyof T]
|
||||
>item[key] : T[keyof T]
|
||||
>value : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>item[key] : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>item : { [P in keyof T]: T[P]; }
|
||||
>key : keyof T
|
||||
|
||||
if (typeof value === "string") {
|
||||
>typeof value === "string" : boolean
|
||||
>typeof value : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>value : T[keyof T]
|
||||
>value : { [P in keyof T]: T[P]; }[keyof T]
|
||||
>"string" : "string"
|
||||
|
||||
strings.push(value);
|
||||
|
@ -100,7 +100,7 @@ function fun<T>(item: { [P in keyof T]: T[P] }) {
|
|||
>strings.push : (...items: string[]) => number
|
||||
>strings : string[]
|
||||
>push : (...items: string[]) => number
|
||||
>value : T[keyof T] & string
|
||||
>value : { [P in keyof T]: T[P]; }[keyof T] & string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
29
tests/cases/compiler/mappedTypeIndexedAccess.ts
Normal file
29
tests/cases/compiler/mappedTypeIndexedAccess.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
// @strict: true
|
||||
|
||||
// Repro from #15756
|
||||
|
||||
type Pairs<T> = {
|
||||
[TKey in keyof T]: {
|
||||
key: TKey;
|
||||
value: T[TKey];
|
||||
};
|
||||
};
|
||||
|
||||
type Pair<T> = Pairs<T>[keyof T];
|
||||
|
||||
type FooBar = {
|
||||
foo: string;
|
||||
bar: number;
|
||||
};
|
||||
|
||||
// Error expected here
|
||||
let pair1: Pair<FooBar> = {
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
||||
|
||||
// Error expected here
|
||||
let pair2: Pairs<FooBar>[keyof FooBar] = {
|
||||
key: "foo",
|
||||
value: 3
|
||||
};
|
Loading…
Reference in a new issue