mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #27911 from Microsoft/fixCircularMappedType
Fix circular mapped type instantiations for arrays and tuples
This commit is contained in:
+11
-1
@@ -10369,7 +10369,15 @@ namespace ts {
|
||||
if (typeVariable) {
|
||||
const mappedTypeVariable = instantiateType(typeVariable, mapper);
|
||||
if (typeVariable !== mappedTypeVariable) {
|
||||
return mapType(mappedTypeVariable, t => {
|
||||
// If we are already in the process of creating an instantiation of this mapped type,
|
||||
// return the error type. This situation only arises if we are instantiating the mapped
|
||||
// type for an array or tuple type, as we then need to eagerly resolve the (possibly
|
||||
// circular) element type(s).
|
||||
if (type.instantiating) {
|
||||
return errorType;
|
||||
}
|
||||
type.instantiating = true;
|
||||
const result = mapType(mappedTypeVariable, t => {
|
||||
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType) {
|
||||
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
|
||||
return isArrayType(t) ? createArrayType(instantiateMappedTypeTemplate(type, numberType, /*isOptional*/ true, replacementMapper)) :
|
||||
@@ -10379,6 +10387,8 @@ namespace ts {
|
||||
}
|
||||
return t;
|
||||
});
|
||||
type.instantiating = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return instantiateAnonymousType(type, mapper);
|
||||
|
||||
@@ -4074,6 +4074,7 @@ namespace ts {
|
||||
templateType?: Type;
|
||||
modifiersType?: Type;
|
||||
resolvedApparentType?: Type;
|
||||
instantiating?: boolean;
|
||||
}
|
||||
|
||||
export interface EvolvingArrayType extends ObjectType {
|
||||
|
||||
@@ -31,4 +31,14 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(12,11): error TS231
|
||||
[K in keyof Recurse1]: Recurse1[K]
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2313: Type parameter 'K' has a circular constraint.
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27881
|
||||
|
||||
export type Circular<T> = {[P in keyof T]: Circular<T>};
|
||||
type tup = [number, number, number, number];
|
||||
|
||||
function foo(arg: Circular<tup>): tup {
|
||||
return arg;
|
||||
}
|
||||
|
||||
@@ -11,19 +11,28 @@ type Recurse1 = {
|
||||
|
||||
type Recurse2 = {
|
||||
[K in keyof Recurse1]: Recurse1[K]
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27881
|
||||
|
||||
export type Circular<T> = {[P in keyof T]: Circular<T>};
|
||||
type tup = [number, number, number, number];
|
||||
|
||||
function foo(arg: Circular<tup>): tup {
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
//// [recursiveMappedTypes.js]
|
||||
"use strict";
|
||||
// Recursive mapped types simply appear empty
|
||||
exports.__esModule = true;
|
||||
function foo(arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
//// [recursiveMappedTypes.d.ts]
|
||||
declare type Recurse = {
|
||||
[K in keyof Recurse]: Recurse[K];
|
||||
};
|
||||
declare type Recurse1 = {
|
||||
[K in keyof Recurse2]: Recurse2[K];
|
||||
};
|
||||
declare type Recurse2 = {
|
||||
[K in keyof Recurse1]: Recurse1[K];
|
||||
export declare type Circular<T> = {
|
||||
[P in keyof T]: Circular<T>;
|
||||
};
|
||||
|
||||
@@ -30,3 +30,28 @@ type Recurse2 = {
|
||||
>Recurse1 : Symbol(Recurse1, Decl(recursiveMappedTypes.ts, 4, 1))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 11, 5))
|
||||
}
|
||||
|
||||
// Repro from #27881
|
||||
|
||||
export type Circular<T> = {[P in keyof T]: Circular<T>};
|
||||
>Circular : Symbol(Circular, Decl(recursiveMappedTypes.ts, 12, 1))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 16, 21))
|
||||
>P : Symbol(P, Decl(recursiveMappedTypes.ts, 16, 28))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 16, 21))
|
||||
>Circular : Symbol(Circular, Decl(recursiveMappedTypes.ts, 12, 1))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 16, 21))
|
||||
|
||||
type tup = [number, number, number, number];
|
||||
>tup : Symbol(tup, Decl(recursiveMappedTypes.ts, 16, 56))
|
||||
|
||||
function foo(arg: Circular<tup>): tup {
|
||||
>foo : Symbol(foo, Decl(recursiveMappedTypes.ts, 17, 44))
|
||||
>arg : Symbol(arg, Decl(recursiveMappedTypes.ts, 19, 13))
|
||||
>Circular : Symbol(Circular, Decl(recursiveMappedTypes.ts, 12, 1))
|
||||
>tup : Symbol(tup, Decl(recursiveMappedTypes.ts, 16, 56))
|
||||
>tup : Symbol(tup, Decl(recursiveMappedTypes.ts, 16, 56))
|
||||
|
||||
return arg;
|
||||
>arg : Symbol(arg, Decl(recursiveMappedTypes.ts, 19, 13))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,3 +18,20 @@ type Recurse2 = {
|
||||
|
||||
[K in keyof Recurse1]: Recurse1[K]
|
||||
}
|
||||
|
||||
// Repro from #27881
|
||||
|
||||
export type Circular<T> = {[P in keyof T]: Circular<T>};
|
||||
>Circular : Circular<T>
|
||||
|
||||
type tup = [number, number, number, number];
|
||||
>tup : [number, number, number, number]
|
||||
|
||||
function foo(arg: Circular<tup>): tup {
|
||||
>foo : (arg: [any, any, any, any]) => [number, number, number, number]
|
||||
>arg : [any, any, any, any]
|
||||
|
||||
return arg;
|
||||
>arg : [any, any, any, any]
|
||||
}
|
||||
|
||||
|
||||
@@ -12,4 +12,13 @@ type Recurse1 = {
|
||||
|
||||
type Recurse2 = {
|
||||
[K in keyof Recurse1]: Recurse1[K]
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #27881
|
||||
|
||||
export type Circular<T> = {[P in keyof T]: Circular<T>};
|
||||
type tup = [number, number, number, number];
|
||||
|
||||
function foo(arg: Circular<tup>): tup {
|
||||
return arg;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user