From 0fb7a70882c12ed6756b3bb8fce06c795ee00fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 27 Sep 2024 09:59:26 +0200 Subject: [PATCH 1/4] Add numeric constraints to type parameters of mapped types with array/tuple intersections constraints --- src/compiler/checker.ts | 4 +-- .../mappedArrayTupleIntersections.symbols | 34 +++++++++++++++++++ .../mappedArrayTupleIntersections.types | 30 ++++++++++++++++ .../compiler/mappedArrayTupleIntersections.ts | 10 ++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dbe53a978c6ed..12c56284f4028 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16875,8 +16875,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (getTypeParameterFromMappedType(mappedType) === getActualTypeVariable(type)) { const typeParameter = getHomomorphicTypeVariable(mappedType); if (typeParameter) { - const constraint = getConstraintOfTypeParameter(typeParameter); - if (constraint && everyType(constraint, isArrayOrTupleType)) { + const constraint = getConstraintOfType(getConditionalFlowTypeOfType(typeParameter, node)); + if (constraint && everyType(constraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { constraints = append(constraints, getUnionType([numberType, numericStringType])); } } diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.symbols b/tests/baselines/reference/mappedArrayTupleIntersections.symbols index 354bdb031d901..6f7ac1a03dc70 100644 --- a/tests/baselines/reference/mappedArrayTupleIntersections.symbols +++ b/tests/baselines/reference/mappedArrayTupleIntersections.symbols @@ -60,3 +60,37 @@ type X = Hmm<[3, 4, 5]>; >X : Symbol(X, Decl(mappedArrayTupleIntersections.ts, 15, 10)) >Hmm : Symbol(Hmm, Decl(mappedArrayTupleIntersections.ts, 11, 38)) +type MustHaveFooBar = T; +>MustHaveFooBar : Symbol(MustHaveFooBar, Decl(mappedArrayTupleIntersections.ts, 17, 24)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 19, 20)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 19, 31)) +>bar : Symbol(bar, Decl(mappedArrayTupleIntersections.ts, 19, 45)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 19, 20)) + +type Hmm2 = T extends { foo: string }[] +>Hmm2 : Symbol(Hmm2, Decl(mappedArrayTupleIntersections.ts, 19, 66)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 21, 10)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 21, 10)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 21, 26)) + + ? T extends { bar: number }[] +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 21, 10)) +>bar : Symbol(bar, Decl(mappedArrayTupleIntersections.ts, 22, 15)) + + ? MustBeArray<{ [I in keyof T]: MustHaveFooBar }> +>MustBeArray : Symbol(MustBeArray, Decl(mappedArrayTupleIntersections.ts, 7, 43)) +>I : Symbol(I, Decl(mappedArrayTupleIntersections.ts, 23, 21)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 21, 10)) +>MustHaveFooBar : Symbol(MustHaveFooBar, Decl(mappedArrayTupleIntersections.ts, 17, 24)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 21, 10)) +>I : Symbol(I, Decl(mappedArrayTupleIntersections.ts, 23, 21)) + + : never + : never; + +type Y = Hmm2<[{ foo: string; bar: number }]>; +>Y : Symbol(Y, Decl(mappedArrayTupleIntersections.ts, 25, 10)) +>Hmm2 : Symbol(Hmm2, Decl(mappedArrayTupleIntersections.ts, 19, 66)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 27, 16)) +>bar : Symbol(bar, Decl(mappedArrayTupleIntersections.ts, 27, 29)) + diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.types b/tests/baselines/reference/mappedArrayTupleIntersections.types index d5e5354d64da2..0bd40954fda8c 100644 --- a/tests/baselines/reference/mappedArrayTupleIntersections.types +++ b/tests/baselines/reference/mappedArrayTupleIntersections.types @@ -50,3 +50,33 @@ type X = Hmm<[3, 4, 5]>; >X : [1, 1, 1] > : ^^^^^^^^^ +type MustHaveFooBar = T; +>MustHaveFooBar : T +> : ^ +>foo : unknown +> : ^^^^^^^ +>bar : unknown +> : ^^^^^^^ + +type Hmm2 = T extends { foo: string }[] +>Hmm2 : Hmm2 +> : ^^^^^^^ +>foo : string +> : ^^^^^^ + + ? T extends { bar: number }[] +>bar : number +> : ^^^^^^ + + ? MustBeArray<{ [I in keyof T]: MustHaveFooBar }> + : never + : never; + +type Y = Hmm2<[{ foo: string; bar: number }]>; +>Y : [{ foo: string; bar: number; }] +> : ^^^^^^^^ ^^^^^^^ ^^^^ +>foo : string +> : ^^^^^^ +>bar : number +> : ^^^^^^ + diff --git a/tests/cases/compiler/mappedArrayTupleIntersections.ts b/tests/cases/compiler/mappedArrayTupleIntersections.ts index 4947e71a5d39c..6dee0d816f1dc 100644 --- a/tests/cases/compiler/mappedArrayTupleIntersections.ts +++ b/tests/cases/compiler/mappedArrayTupleIntersections.ts @@ -19,3 +19,13 @@ type Hmm = T extends number[] ? never; type X = Hmm<[3, 4, 5]>; + +type MustHaveFooBar = T; + +type Hmm2 = T extends { foo: string }[] + ? T extends { bar: number }[] + ? MustBeArray<{ [I in keyof T]: MustHaveFooBar }> + : never + : never; + +type Y = Hmm2<[{ foo: string; bar: number }]>; From 2c4845de382e9276540ff12ef4952bba19134570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 27 Sep 2024 16:43:49 +0200 Subject: [PATCH 2/4] add extra tests --- .../mappedArrayTupleIntersections.errors.txt | 50 +++++++++++++++++++ .../mappedArrayTupleIntersections.symbols | 34 +++++++++++++ .../mappedArrayTupleIntersections.types | 35 +++++++++++++ .../compiler/mappedArrayTupleIntersections.ts | 9 ++++ 4 files changed, 128 insertions(+) create mode 100644 tests/baselines/reference/mappedArrayTupleIntersections.errors.txt diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.errors.txt b/tests/baselines/reference/mappedArrayTupleIntersections.errors.txt new file mode 100644 index 0000000000000..0033732d0ef59 --- /dev/null +++ b/tests/baselines/reference/mappedArrayTupleIntersections.errors.txt @@ -0,0 +1,50 @@ +mappedArrayTupleIntersections.ts(33,47): error TS2344: Type 'T[I]' does not satisfy the constraint '{ foo: unknown; }'. + Type 'T[keyof T]' is not assignable to type '{ foo: unknown; }'. + Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{ foo: unknown; }'. + Type 'T[string]' is not assignable to type '{ foo: unknown; }'. + + +==== mappedArrayTupleIntersections.ts (1 errors) ==== + type Box = { value: T }; + type Boxify = { [K in keyof T]: Box }; + + type T1 = Boxify; + type T2 = Boxify<[string, string]>; + type T3 = Boxify; + type T4 = Boxify; + type T5 = Boxify; + + // https://github.com/microsoft/TypeScript/issues/57744 + + type MustBeArray = T; + + type Hmm = T extends number[] ? + MustBeArray<{ [I in keyof T]: 1 }> : + never; + + type X = Hmm<[3, 4, 5]>; + + type MustHaveFooBar = T; + + type Hmm2 = T extends { foo: string }[] + ? T extends { bar: number }[] + ? MustBeArray<{ [I in keyof T]: MustHaveFooBar }> + : never + : never; + + type Y = Hmm2<[{ foo: string; bar: number }]>; + + type MustHaveFoo = T; + + type Hmm3 = T extends { bar: string } + ? MustBeArray<{ [I in keyof T]: MustHaveFoo }> + ~~~~ +!!! error TS2344: Type 'T[I]' does not satisfy the constraint '{ foo: unknown; }'. +!!! error TS2344: Type 'T[keyof T]' is not assignable to type '{ foo: unknown; }'. +!!! error TS2344: Type 'T[string] | T[number] | T[symbol]' is not assignable to type '{ foo: unknown; }'. +!!! error TS2344: Type 'T[string]' is not assignable to type '{ foo: unknown; }'. + : never; + + type Z1 = Hmm3<[{ foo: string }]>; + type Z2 = Hmm3<[{ foo: string }] & { bar: string }>; + \ No newline at end of file diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.symbols b/tests/baselines/reference/mappedArrayTupleIntersections.symbols index 6f7ac1a03dc70..e5b4f5d82c621 100644 --- a/tests/baselines/reference/mappedArrayTupleIntersections.symbols +++ b/tests/baselines/reference/mappedArrayTupleIntersections.symbols @@ -94,3 +94,37 @@ type Y = Hmm2<[{ foo: string; bar: number }]>; >foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 27, 16)) >bar : Symbol(bar, Decl(mappedArrayTupleIntersections.ts, 27, 29)) +type MustHaveFoo = T; +>MustHaveFoo : Symbol(MustHaveFoo, Decl(mappedArrayTupleIntersections.ts, 27, 46)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 29, 17)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 29, 28)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 29, 17)) + +type Hmm3 = T extends { bar: string } +>Hmm3 : Symbol(Hmm3, Decl(mappedArrayTupleIntersections.ts, 29, 49)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 31, 10)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 31, 21)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 31, 10)) +>bar : Symbol(bar, Decl(mappedArrayTupleIntersections.ts, 31, 52)) + + ? MustBeArray<{ [I in keyof T]: MustHaveFoo }> +>MustBeArray : Symbol(MustBeArray, Decl(mappedArrayTupleIntersections.ts, 7, 43)) +>I : Symbol(I, Decl(mappedArrayTupleIntersections.ts, 32, 19)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 31, 10)) +>MustHaveFoo : Symbol(MustHaveFoo, Decl(mappedArrayTupleIntersections.ts, 27, 46)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 31, 10)) +>I : Symbol(I, Decl(mappedArrayTupleIntersections.ts, 32, 19)) + + : never; + +type Z1 = Hmm3<[{ foo: string }]>; +>Z1 : Symbol(Z1, Decl(mappedArrayTupleIntersections.ts, 33, 10)) +>Hmm3 : Symbol(Hmm3, Decl(mappedArrayTupleIntersections.ts, 29, 49)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 35, 17)) + +type Z2 = Hmm3<[{ foo: string }] & { bar: string }>; +>Z2 : Symbol(Z2, Decl(mappedArrayTupleIntersections.ts, 35, 34)) +>Hmm3 : Symbol(Hmm3, Decl(mappedArrayTupleIntersections.ts, 29, 49)) +>foo : Symbol(foo, Decl(mappedArrayTupleIntersections.ts, 36, 17)) +>bar : Symbol(bar, Decl(mappedArrayTupleIntersections.ts, 36, 36)) + diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.types b/tests/baselines/reference/mappedArrayTupleIntersections.types index 0bd40954fda8c..84bb92164e628 100644 --- a/tests/baselines/reference/mappedArrayTupleIntersections.types +++ b/tests/baselines/reference/mappedArrayTupleIntersections.types @@ -1,5 +1,9 @@ //// [tests/cases/compiler/mappedArrayTupleIntersections.ts] //// +=== Performance Stats === +Type Count: 1,000 +Instantiation count: 1,000 -> 2,500 + === mappedArrayTupleIntersections.ts === type Box = { value: T }; >Box : Box @@ -80,3 +84,34 @@ type Y = Hmm2<[{ foo: string; bar: number }]>; >bar : number > : ^^^^^^ +type MustHaveFoo = T; +>MustHaveFoo : T +> : ^ +>foo : unknown +> : ^^^^^^^ + +type Hmm3 = T extends { bar: string } +>Hmm3 : Hmm3 +> : ^^^^^^^ +>foo : string +> : ^^^^^^ +>bar : string +> : ^^^^^^ + + ? MustBeArray<{ [I in keyof T]: MustHaveFoo }> + : never; + +type Z1 = Hmm3<[{ foo: string }]>; +>Z1 : never +> : ^^^^^ +>foo : string +> : ^^^^^^ + +type Z2 = Hmm3<[{ foo: string }] & { bar: string }>; +>Z2 : { [x: number]: { foo: string; }; 0: { foo: string; }; length: 1; toString: () => string; toLocaleString: () => string; pop: () => { foo: string; } | undefined; push: (...items: { foo: string; }[]) => number; concat: { (...items: ConcatArray<{ foo: string; }>[]): { foo: string; }[]; (...items: ({ foo: string; } | ConcatArray<{ foo: string; }>)[]): { foo: string; }[]; }; join: (separator?: string) => string; reverse: () => { foo: string; }[]; shift: () => { foo: string; } | undefined; slice: (start?: number, end?: number) => { foo: string; }[]; sort: (compareFn?: ((a: { foo: string; }, b: { foo: string; }) => number) | undefined) => [{ foo: string; }] & { bar: string; }; splice: { (start: number, deleteCount?: number): { foo: string; }[]; (start: number, deleteCount: number, ...items: { foo: string; }[]): { foo: string; }[]; }; unshift: (...items: { foo: string; }[]) => number; indexOf: (searchElement: { foo: string; }, fromIndex?: number) => number; lastIndexOf: (searchElement: { foo: string; }, fromIndex?: number) => number; every: { (predicate: (value: { foo: string; }, index: number, array: { foo: string; }[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: { foo: string; }, index: number, array: { foo: string; }[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: { foo: string; }, index: number, array: { foo: string; }[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: { foo: string; }, index: number, array: { foo: string; }[]) => void, thisArg?: any) => void; map: (callbackfn: (value: { foo: string; }, index: number, array: { foo: string; }[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: { foo: string; }, index: number, array: { foo: string; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { foo: string; }, index: number, array: { foo: string; }[]) => unknown, thisArg?: any): { foo: string; }[]; }; reduce: { (callbackfn: (previousValue: { foo: string; }, currentValue: { foo: string; }, currentIndex: number, array: { foo: string; }[]) => { foo: string; }): { foo: string; }; (callbackfn: (previousValue: { foo: string; }, currentValue: { foo: string; }, currentIndex: number, array: { foo: string; }[]) => { foo: string; }, initialValue: { foo: string; }): { foo: string; }; (callbackfn: (previousValue: U, currentValue: { foo: string; }, currentIndex: number, array: { foo: string; }[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: { foo: string; }, currentValue: { foo: string; }, currentIndex: number, array: { foo: string; }[]) => { foo: string; }): { foo: string; }; (callbackfn: (previousValue: { foo: string; }, currentValue: { foo: string; }, currentIndex: number, array: { foo: string; }[]) => { foo: string; }, initialValue: { foo: string; }): { foo: string; }; (callbackfn: (previousValue: U, currentValue: { foo: string; }, currentIndex: number, array: { foo: string; }[]) => U, initialValue: U): U; }; bar: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^ ^^^ ^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^^ ^^^^^^^^^^ ^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^ ^^^ ^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^ ^^^ ^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^ ^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^ ^^ ^^^ ^^^ ^^^^^^^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^ ^^ ^^^ ^^^^^ ^^^^^^^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^ ^^ ^^^ ^^^^^ ^^^^^^^^ ^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^ ^^ ^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^ ^^^ ^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^ ^^ ^^^ ^^^^^ ^^^^^^^^^ ^^^^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^ +>foo : string +> : ^^^^^^ +>bar : string +> : ^^^^^^ + diff --git a/tests/cases/compiler/mappedArrayTupleIntersections.ts b/tests/cases/compiler/mappedArrayTupleIntersections.ts index 6dee0d816f1dc..b6570712f9c81 100644 --- a/tests/cases/compiler/mappedArrayTupleIntersections.ts +++ b/tests/cases/compiler/mappedArrayTupleIntersections.ts @@ -29,3 +29,12 @@ type Hmm2 = T extends { foo: string }[] : never; type Y = Hmm2<[{ foo: string; bar: number }]>; + +type MustHaveFoo = T; + +type Hmm3 = T extends { bar: string } + ? MustBeArray<{ [I in keyof T]: MustHaveFoo }> + : never; + +type Z1 = Hmm3<[{ foo: string }]>; +type Z2 = Hmm3<[{ foo: string }] & { bar: string }>; From 470eccc358dc0b9f060b703bca769c4779c34f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 27 Sep 2024 16:59:58 +0200 Subject: [PATCH 3/4] update baselines --- tests/baselines/reference/deepComparisons.types | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/deepComparisons.types b/tests/baselines/reference/deepComparisons.types index ce329516adba8..d803925f0834d 100644 --- a/tests/baselines/reference/deepComparisons.types +++ b/tests/baselines/reference/deepComparisons.types @@ -1,7 +1,7 @@ //// [tests/cases/compiler/deepComparisons.ts] //// === Performance Stats === -Type Count: 2,500 +Type Count: 1,000 Instantiation count: 2,500 === deepComparisons.ts === From 68e95af3361344ecd4f52cfd09935cb8329c0e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 28 Sep 2024 12:02:33 +0200 Subject: [PATCH 4/4] rename to `isArrayOrTupleIntersection` --- src/compiler/checker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 12c56284f4028..68a98e40b4137 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15097,14 +15097,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // mapped type because we protect again circular constraints in getTypeFromMappedTypeNode. const modifiersType = getModifiersTypeFromMappedType(type); const baseConstraint = isGenericMappedType(modifiersType) ? getApparentTypeOfMappedType(modifiersType) : getBaseConstraintOfType(modifiersType); - if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { + if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleIntersection(t))) { return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } return type; } - function isArrayOrTupleOrIntersection(type: Type) { + function isArrayOrTupleIntersection(type: Type) { return !!(type.flags & TypeFlags.Intersection) && every((type as IntersectionType).types, isArrayOrTupleType); } @@ -16876,7 +16876,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParameter = getHomomorphicTypeVariable(mappedType); if (typeParameter) { const constraint = getConstraintOfType(getConditionalFlowTypeOfType(typeParameter, node)); - if (constraint && everyType(constraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { + if (constraint && everyType(constraint, t => isArrayOrTupleType(t) || isArrayOrTupleIntersection(t))) { constraints = append(constraints, getUnionType([numberType, numericStringType])); } } @@ -20493,7 +20493,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isTupleType(t)) { return instantiateMappedTupleType(t, type, typeVariable!, mapper); } - if (isArrayOrTupleOrIntersection(t)) { + if (isArrayOrTupleIntersection(t)) { return getIntersectionType(map((t as IntersectionType).types, instantiateConstituent)); } }