Skip to content

Commit 1ed06e6

Browse files
authored
Fixed an issue with not being able to use mapped type over union constraint as rest param (#49947)
1 parent 27aca61 commit 1ed06e6

11 files changed

+429
-3
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13861,7 +13861,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1386113861
const typeVariable = getHomomorphicTypeVariable(type);
1386213862
if (typeVariable && !type.declaration.nameType) {
1386313863
const constraint = getConstraintOfTypeParameter(typeVariable);
13864-
if (constraint && isArrayType(constraint)) {
13864+
if (constraint && everyType(constraint, isArrayOrTupleType)) {
1386513865
return instantiateType(type, prependTypeMapping(typeVariable, constraint, type.mapper));
1386613866
}
1386713867
}
@@ -21686,7 +21686,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2168621686
return varianceResult;
2168721687
}
2168821688
}
21689-
else if (isReadonlyArrayType(target) ? isArrayOrTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
21689+
else if (isReadonlyArrayType(target) ? everyType(source, isArrayOrTupleType) : isArrayType(target) && everyType(source, t => isTupleType(t) && !t.target.readonly)) {
2169021690
if (relation !== identityRelation) {
2169121691
return isRelatedTo(getIndexTypeOfType(source, numberType) || anyType, getIndexTypeOfType(target, numberType) || anyType, RecursionFlags.Both, reportErrors);
2169221692
}
@@ -29258,7 +29258,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2925829258
getContextualType(node, contextFlags);
2925929259
const instantiatedType = instantiateContextualType(contextualType, node, contextFlags);
2926029260
if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) {
29261-
const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true);
29261+
const apparentType = mapType(
29262+
instantiatedType,
29263+
// When obtaining apparent type of *contextual* type we don't want to get apparent type of mapped types.
29264+
// That would evaluate mapped types with array or tuple type constraints too eagerly
29265+
// and thus it would prevent `getTypeOfPropertyOfContextualType` from obtaining per-position contextual type for elements of array literal expressions.
29266+
// Apparent type of other mapped types is already the mapped type itself so we can just avoid calling `getApparentType` here for all mapped types.
29267+
t => getObjectFlags(t) & ObjectFlags.Mapped ? t : getApparentType(t),
29268+
/*noReductions*/ true
29269+
);
2926229270
return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) :
2926329271
apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) :
2926429272
apparentType;
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
=== tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts ===
2+
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594
3+
4+
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
5+
>Writeable : Symbol(Writeable, Decl(mappedTypeTupleConstraintAssignability.ts, 0, 0))
6+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15))
7+
>P : Symbol(P, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 33))
8+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15))
9+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 15))
10+
>P : Symbol(P, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 33))
11+
12+
type EnumValues = [string, ...string[]];
13+
>EnumValues : Symbol(EnumValues, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 55))
14+
15+
type Values<T extends EnumValues> = { [k in T[number]]: k; };
16+
>Values : Symbol(Values, Decl(mappedTypeTupleConstraintAssignability.ts, 3, 40))
17+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 12))
18+
>EnumValues : Symbol(EnumValues, Decl(mappedTypeTupleConstraintAssignability.ts, 2, 55))
19+
>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 39))
20+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 12))
21+
>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 39))
22+
23+
declare class ZodEnum<T extends [string, ...string[]]> {
24+
>ZodEnum : Symbol(ZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 61))
25+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 22))
26+
27+
get enum(): Values<T>
28+
>enum : Symbol(ZodEnum.enum, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 56))
29+
>Values : Symbol(Values, Decl(mappedTypeTupleConstraintAssignability.ts, 3, 40))
30+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 6, 22))
31+
}
32+
33+
declare function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(values: T): ZodEnum<Writeable<T>>;
34+
>createZodEnum : Symbol(createZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 8, 1))
35+
>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31))
36+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48))
37+
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
38+
>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31))
39+
>U : Symbol(U, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 31))
40+
>values : Symbol(values, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 82))
41+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48))
42+
>ZodEnum : Symbol(ZodEnum, Decl(mappedTypeTupleConstraintAssignability.ts, 4, 61))
43+
>Writeable : Symbol(Writeable, Decl(mappedTypeTupleConstraintAssignability.ts, 0, 0))
44+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 48))
45+
46+
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607
47+
48+
type Maybe<T> = T | null | undefined;
49+
>Maybe : Symbol(Maybe, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 116))
50+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 11))
51+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 11))
52+
53+
type AnyTuple = [unknown, ...unknown[]];
54+
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
55+
56+
type AnyObject = { [k: string]: any };
57+
>AnyObject : Symbol(AnyObject, Decl(mappedTypeTupleConstraintAssignability.ts, 15, 40))
58+
>k : Symbol(k, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 20))
59+
60+
type Flags = "s" | "d" | "";
61+
>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38))
62+
63+
interface ISchema<T, C = any, F extends Flags = any, D = any> {
64+
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
65+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 18))
66+
>C : Symbol(C, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 20))
67+
>F : Symbol(F, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 29))
68+
>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38))
69+
>D : Symbol(D, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 52))
70+
71+
__flags: F;
72+
>__flags : Symbol(ISchema.__flags, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 63))
73+
>F : Symbol(F, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 29))
74+
75+
__context: C;
76+
>__context : Symbol(ISchema.__context, Decl(mappedTypeTupleConstraintAssignability.ts, 20, 13))
77+
>C : Symbol(C, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 20))
78+
79+
__outputType: T;
80+
>__outputType : Symbol(ISchema.__outputType, Decl(mappedTypeTupleConstraintAssignability.ts, 21, 15))
81+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 18))
82+
83+
__default: D;
84+
>__default : Symbol(ISchema.__default, Decl(mappedTypeTupleConstraintAssignability.ts, 22, 18))
85+
>D : Symbol(D, Decl(mappedTypeTupleConstraintAssignability.ts, 19, 52))
86+
}
87+
88+
declare class TupleSchema<
89+
>TupleSchema : Symbol(TupleSchema, Decl(mappedTypeTupleConstraintAssignability.ts, 24, 1))
90+
91+
TType extends Maybe<AnyTuple> = AnyTuple | undefined,
92+
>TType : Symbol(TType, Decl(mappedTypeTupleConstraintAssignability.ts, 26, 26))
93+
>Maybe : Symbol(Maybe, Decl(mappedTypeTupleConstraintAssignability.ts, 10, 116))
94+
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
95+
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
96+
97+
TContext = AnyObject,
98+
>TContext : Symbol(TContext, Decl(mappedTypeTupleConstraintAssignability.ts, 27, 55))
99+
>AnyObject : Symbol(AnyObject, Decl(mappedTypeTupleConstraintAssignability.ts, 15, 40))
100+
101+
TDefault = undefined,
102+
>TDefault : Symbol(TDefault, Decl(mappedTypeTupleConstraintAssignability.ts, 28, 23))
103+
104+
TFlags extends Flags = ""
105+
>TFlags : Symbol(TFlags, Decl(mappedTypeTupleConstraintAssignability.ts, 29, 23))
106+
>Flags : Symbol(Flags, Decl(mappedTypeTupleConstraintAssignability.ts, 16, 38))
107+
108+
> {
109+
constructor(schemas: [ISchema<any>, ...ISchema<any>[]]);
110+
>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 32, 14))
111+
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
112+
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
113+
}
114+
115+
export function create<T extends AnyTuple>(schemas: {
116+
>create : Symbol(create, Decl(mappedTypeTupleConstraintAssignability.ts, 33, 1))
117+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
118+
>AnyTuple : Symbol(AnyTuple, Decl(mappedTypeTupleConstraintAssignability.ts, 14, 37))
119+
>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 43))
120+
121+
[K in keyof T]: ISchema<T[K]>;
122+
>K : Symbol(K, Decl(mappedTypeTupleConstraintAssignability.ts, 36, 3))
123+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
124+
>ISchema : Symbol(ISchema, Decl(mappedTypeTupleConstraintAssignability.ts, 17, 28))
125+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
126+
>K : Symbol(K, Decl(mappedTypeTupleConstraintAssignability.ts, 36, 3))
127+
128+
}) {
129+
return new TupleSchema<T | undefined>(schemas);
130+
>TupleSchema : Symbol(TupleSchema, Decl(mappedTypeTupleConstraintAssignability.ts, 24, 1))
131+
>T : Symbol(T, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 23))
132+
>schemas : Symbol(schemas, Decl(mappedTypeTupleConstraintAssignability.ts, 35, 43))
133+
}
134+
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
=== tests/cases/compiler/mappedTypeTupleConstraintAssignability.ts ===
2+
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390594
3+
4+
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
5+
>Writeable : Writeable<T>
6+
7+
type EnumValues = [string, ...string[]];
8+
>EnumValues : [string, ...string[]]
9+
10+
type Values<T extends EnumValues> = { [k in T[number]]: k; };
11+
>Values : Values<T>
12+
13+
declare class ZodEnum<T extends [string, ...string[]]> {
14+
>ZodEnum : ZodEnum<T>
15+
16+
get enum(): Values<T>
17+
>enum : Values<T>
18+
}
19+
20+
declare function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(values: T): ZodEnum<Writeable<T>>;
21+
>createZodEnum : <U extends string, T extends readonly [U, ...U[]]>(values: T) => ZodEnum<Writeable<T>>
22+
>values : T
23+
24+
// https://github.com/microsoft/TypeScript/issues/53359#issuecomment-1475390607
25+
26+
type Maybe<T> = T | null | undefined;
27+
>Maybe : Maybe<T>
28+
29+
type AnyTuple = [unknown, ...unknown[]];
30+
>AnyTuple : [unknown, ...unknown[]]
31+
32+
type AnyObject = { [k: string]: any };
33+
>AnyObject : { [k: string]: any; }
34+
>k : string
35+
36+
type Flags = "s" | "d" | "";
37+
>Flags : "" | "s" | "d"
38+
39+
interface ISchema<T, C = any, F extends Flags = any, D = any> {
40+
__flags: F;
41+
>__flags : F
42+
43+
__context: C;
44+
>__context : C
45+
46+
__outputType: T;
47+
>__outputType : T
48+
49+
__default: D;
50+
>__default : D
51+
}
52+
53+
declare class TupleSchema<
54+
>TupleSchema : TupleSchema<TType, TContext, TDefault, TFlags>
55+
56+
TType extends Maybe<AnyTuple> = AnyTuple | undefined,
57+
TContext = AnyObject,
58+
TDefault = undefined,
59+
TFlags extends Flags = ""
60+
> {
61+
constructor(schemas: [ISchema<any>, ...ISchema<any>[]]);
62+
>schemas : [ISchema<any, any, any, any>, ...ISchema<any, any, any, any>[]]
63+
}
64+
65+
export function create<T extends AnyTuple>(schemas: {
66+
>create : <T extends AnyTuple>(schemas: { [K in keyof T]: ISchema<T[K], any, any, any>; }) => TupleSchema<T | undefined, AnyObject, undefined, "">
67+
>schemas : { [K in keyof T]: ISchema<T[K], any, any, any>; }
68+
69+
[K in keyof T]: ISchema<T[K]>;
70+
}) {
71+
return new TupleSchema<T | undefined>(schemas);
72+
>new TupleSchema<T | undefined>(schemas) : TupleSchema<T | undefined, AnyObject, undefined, "">
73+
>TupleSchema : typeof TupleSchema
74+
>schemas : { [K in keyof T]: ISchema<T[K], any, any, any>; }
75+
}
76+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts(9,9): error TS2322: Type 'HomomorphicMappedType<T>' is not assignable to type 'any[]'.
2+
3+
4+
==== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts (1 errors) ====
5+
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
6+
7+
function test1<T extends [number] | [string]>(args: T) {
8+
const arr: any[] = [] as HomomorphicMappedType<T>
9+
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
10+
}
11+
12+
function test2<T extends [number] | readonly [string]>(args: T) {
13+
const arr: any[] = [] as HomomorphicMappedType<T> // error
14+
~~~
15+
!!! error TS2322: Type 'HomomorphicMappedType<T>' is not assignable to type 'any[]'.
16+
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
17+
}
18+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
=== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts ===
2+
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
3+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
4+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27))
5+
>P : Symbol(P, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 35))
6+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27))
7+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 27))
8+
>P : Symbol(P, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 35))
9+
10+
function test1<T extends [number] | [string]>(args: T) {
11+
>test1 : Symbol(test1, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 88))
12+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
13+
>args : Symbol(args, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 46))
14+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
15+
16+
const arr: any[] = [] as HomomorphicMappedType<T>
17+
>arr : Symbol(arr, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 3, 7))
18+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
19+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
20+
21+
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
22+
>arr2 : Symbol(arr2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 4, 7))
23+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
24+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 2, 15))
25+
}
26+
27+
function test2<T extends [number] | readonly [string]>(args: T) {
28+
>test2 : Symbol(test2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 5, 1))
29+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
30+
>args : Symbol(args, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 55))
31+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
32+
33+
const arr: any[] = [] as HomomorphicMappedType<T> // error
34+
>arr : Symbol(arr, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 8, 7))
35+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
36+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
37+
38+
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
39+
>arr2 : Symbol(arr2, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 9, 7))
40+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 0, 0))
41+
>T : Symbol(T, Decl(mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts, 7, 15))
42+
}
43+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/mappedTypeUnionConstrainTupleTreatedAsArrayLike.ts ===
2+
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
3+
>HomomorphicMappedType : HomomorphicMappedType<T>
4+
5+
function test1<T extends [number] | [string]>(args: T) {
6+
>test1 : <T extends [number] | [string]>(args: T) => void
7+
>args : T
8+
9+
const arr: any[] = [] as HomomorphicMappedType<T>
10+
>arr : any[]
11+
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
12+
>[] : []
13+
14+
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
15+
>arr2 : readonly any[]
16+
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
17+
>[] : []
18+
}
19+
20+
function test2<T extends [number] | readonly [string]>(args: T) {
21+
>test2 : <T extends [number] | readonly [string]>(args: T) => void
22+
>args : T
23+
24+
const arr: any[] = [] as HomomorphicMappedType<T> // error
25+
>arr : any[]
26+
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
27+
>[] : []
28+
29+
const arr2: readonly any[] = [] as HomomorphicMappedType<T>
30+
>arr2 : readonly any[]
31+
>[] as HomomorphicMappedType<T> : HomomorphicMappedType<T>
32+
>[] : []
33+
}
34+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts ===
2+
// repro 29919#issuecomment-470948453
3+
4+
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
5+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0))
6+
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27))
7+
>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 35))
8+
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27))
9+
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 27))
10+
>P : Symbol(P, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 35))
11+
12+
declare function test<T extends [number] | [string]>(
13+
>test : Symbol(test, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 2, 88))
14+
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22))
15+
16+
args: T,
17+
>args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 53))
18+
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22))
19+
20+
fn: (...args: HomomorphicMappedType<T>) => void
21+
>fn : Symbol(fn, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 5, 10))
22+
>args : Symbol(args, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 6, 7))
23+
>HomomorphicMappedType : Symbol(HomomorphicMappedType, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 0, 0))
24+
>T : Symbol(T, Decl(restParamUsingMappedTypeOverUnionConstraint.ts, 4, 22))
25+
26+
): void
27+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts ===
2+
// repro 29919#issuecomment-470948453
3+
4+
type HomomorphicMappedType<T> = { [P in keyof T]: T[P] extends string ? boolean : null }
5+
>HomomorphicMappedType : HomomorphicMappedType<T>
6+
7+
declare function test<T extends [number] | [string]>(
8+
>test : <T extends [number] | [string]>(args: T, fn: (...args: HomomorphicMappedType<T>) => void) => void
9+
10+
args: T,
11+
>args : T
12+
13+
fn: (...args: HomomorphicMappedType<T>) => void
14+
>fn : (...args: HomomorphicMappedType<T>) => void
15+
>args : HomomorphicMappedType<T>
16+
17+
): void
18+

0 commit comments

Comments
 (0)