Skip to content

Commit 5e06bea

Browse files
authored
getConstraintDeclaration gets the first declaration with a constraint… (#33426)
* getConstraintDeclaration gets the first declaration with a constraint, rather than just the first declaration * Add type annotation * Update comment
1 parent 683e281 commit 5e06bea

10 files changed

+137
-20
lines changed

src/compiler/checker.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -8971,9 +8971,8 @@ namespace ts {
89718971
return undefined;
89728972
}
89738973

8974-
function getConstraintDeclaration(type: TypeParameter) {
8975-
const decl = type.symbol && getDeclarationOfKind<TypeParameterDeclaration>(type.symbol, SyntaxKind.TypeParameter);
8976-
return decl && getEffectiveConstraintOfTypeParameter(decl);
8974+
function getConstraintDeclaration(type: TypeParameter): TypeNode | undefined {
8975+
return mapDefined(filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), getEffectiveConstraintOfTypeParameter)[0];
89778976
}
89788977

89798978
function getInferredTypeParameterConstraint(typeParameter: TypeParameter) {
@@ -29242,11 +29241,10 @@ namespace ts {
2924229241
const constraint = getEffectiveConstraintOfTypeParameter(source);
2924329242
const sourceConstraint = constraint && getTypeFromTypeNode(constraint);
2924429243
const targetConstraint = getConstraintOfTypeParameter(target);
29245-
if (sourceConstraint) {
29246-
// relax check if later interface augmentation has no constraint
29247-
if (!targetConstraint || !isTypeIdenticalTo(sourceConstraint, targetConstraint)) {
29248-
return false;
29249-
}
29244+
// relax check if later interface augmentation has no constraint, it's more broad and is OK to merge with
29245+
// a more constrained interface (this could be generalized to a full heirarchy check, but that's maybe overkill)
29246+
if (sourceConstraint && targetConstraint && !isTypeIdenticalTo(sourceConstraint, targetConstraint)) {
29247+
return false;
2925029248
}
2925129249

2925229250
// If the type parameter node has a default and it is not identical to the default
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [tests/cases/compiler/interfaceMergedUnconstrainedNoErrorIrrespectiveOfOrder.ts] ////
2+
3+
//// [working.ts]
4+
// minmal samples from #33395
5+
export namespace ns {
6+
interface Function<T extends (...args: any) => any> {
7+
throttle(): Function<T>;
8+
}
9+
interface Function<T> {
10+
unary(): Function<() => ReturnType<T>>;
11+
}
12+
}
13+
//// [regression.ts]
14+
export namespace ns {
15+
interface Function<T> {
16+
unary(): Function<() => ReturnType<T>>;
17+
}
18+
interface Function<T extends (...args: any) => any> {
19+
throttle(): Function<T>;
20+
}
21+
}
22+
23+
//// [working.js]
24+
"use strict";
25+
exports.__esModule = true;
26+
//// [regression.js]
27+
"use strict";
28+
exports.__esModule = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
=== tests/cases/compiler/working.ts ===
2+
// minmal samples from #33395
3+
export namespace ns {
4+
>ns : Symbol(ns, Decl(working.ts, 0, 0))
5+
6+
interface Function<T extends (...args: any) => any> {
7+
>Function : Symbol(Function, Decl(working.ts, 1, 21), Decl(working.ts, 4, 5))
8+
>T : Symbol(T, Decl(working.ts, 2, 23), Decl(working.ts, 5, 23))
9+
>args : Symbol(args, Decl(working.ts, 2, 34))
10+
11+
throttle(): Function<T>;
12+
>throttle : Symbol(Function.throttle, Decl(working.ts, 2, 57))
13+
>Function : Symbol(Function, Decl(working.ts, 1, 21), Decl(working.ts, 4, 5))
14+
>T : Symbol(T, Decl(working.ts, 2, 23), Decl(working.ts, 5, 23))
15+
}
16+
interface Function<T> {
17+
>Function : Symbol(Function, Decl(working.ts, 1, 21), Decl(working.ts, 4, 5))
18+
>T : Symbol(T, Decl(working.ts, 2, 23), Decl(working.ts, 5, 23))
19+
20+
unary(): Function<() => ReturnType<T>>;
21+
>unary : Symbol(Function.unary, Decl(working.ts, 5, 27))
22+
>Function : Symbol(Function, Decl(working.ts, 1, 21), Decl(working.ts, 4, 5))
23+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
24+
>T : Symbol(T, Decl(working.ts, 2, 23), Decl(working.ts, 5, 23))
25+
}
26+
}
27+
=== tests/cases/compiler/regression.ts ===
28+
export namespace ns {
29+
>ns : Symbol(ns, Decl(regression.ts, 0, 0))
30+
31+
interface Function<T> {
32+
>Function : Symbol(Function, Decl(regression.ts, 0, 21), Decl(regression.ts, 3, 5))
33+
>T : Symbol(T, Decl(regression.ts, 1, 23), Decl(regression.ts, 4, 23))
34+
35+
unary(): Function<() => ReturnType<T>>;
36+
>unary : Symbol(Function.unary, Decl(regression.ts, 1, 27))
37+
>Function : Symbol(Function, Decl(regression.ts, 0, 21), Decl(regression.ts, 3, 5))
38+
>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
39+
>T : Symbol(T, Decl(regression.ts, 1, 23), Decl(regression.ts, 4, 23))
40+
}
41+
interface Function<T extends (...args: any) => any> {
42+
>Function : Symbol(Function, Decl(regression.ts, 0, 21), Decl(regression.ts, 3, 5))
43+
>T : Symbol(T, Decl(regression.ts, 1, 23), Decl(regression.ts, 4, 23))
44+
>args : Symbol(args, Decl(regression.ts, 4, 34))
45+
46+
throttle(): Function<T>;
47+
>throttle : Symbol(Function.throttle, Decl(regression.ts, 4, 57))
48+
>Function : Symbol(Function, Decl(regression.ts, 0, 21), Decl(regression.ts, 3, 5))
49+
>T : Symbol(T, Decl(regression.ts, 1, 23), Decl(regression.ts, 4, 23))
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/working.ts ===
2+
// minmal samples from #33395
3+
export namespace ns {
4+
interface Function<T extends (...args: any) => any> {
5+
>args : any
6+
7+
throttle(): Function<T>;
8+
>throttle : () => Function<T>
9+
}
10+
interface Function<T> {
11+
unary(): Function<() => ReturnType<T>>;
12+
>unary : () => Function<() => ReturnType<T>>
13+
}
14+
}
15+
=== tests/cases/compiler/regression.ts ===
16+
export namespace ns {
17+
interface Function<T> {
18+
unary(): Function<() => ReturnType<T>>;
19+
>unary : () => Function<() => ReturnType<T>>
20+
}
21+
interface Function<T extends (...args: any) => any> {
22+
>args : any
23+
24+
throttle(): Function<T>;
25+
>throttle : () => Function<T>
26+
}
27+
}

tests/baselines/reference/twoGenericInterfacesWithDifferentConstraints.errors.txt

+2-8
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDi
44
tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts(14,15): error TS2428: All declarations of 'B' must have identical type parameters.
55
tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts(32,22): error TS2428: All declarations of 'A' must have identical type parameters.
66
tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts(38,22): error TS2428: All declarations of 'A' must have identical type parameters.
7-
tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts(53,11): error TS2428: All declarations of 'C' must have identical type parameters.
8-
tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts(57,11): error TS2428: All declarations of 'C' must have identical type parameters.
97

108

11-
==== tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts (8 errors) ====
9+
==== tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts (6 errors) ====
1210
interface A<T extends Date> {
1311
~
1412
!!! error TS2428: All declarations of 'A' must have identical type parameters.
@@ -74,14 +72,10 @@ tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDi
7472
}
7573

7674
interface C<T> {
77-
~
78-
!!! error TS2428: All declarations of 'C' must have identical type parameters.
7975
x: T;
8076
}
8177

82-
interface C<T extends number> { // error
83-
~
84-
!!! error TS2428: All declarations of 'C' must have identical type parameters.
78+
interface C<T extends number> { // ok
8579
y: T;
8680
}
8781

tests/baselines/reference/twoGenericInterfacesWithDifferentConstraints.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ interface C<T> {
5555
x: T;
5656
}
5757

58-
interface C<T extends number> { // error
58+
interface C<T extends number> { // ok
5959
y: T;
6060
}
6161

tests/baselines/reference/twoGenericInterfacesWithDifferentConstraints.symbols

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ interface C<T> {
137137
>T : Symbol(T, Decl(twoGenericInterfacesWithDifferentConstraints.ts, 52, 12), Decl(twoGenericInterfacesWithDifferentConstraints.ts, 56, 12))
138138
}
139139

140-
interface C<T extends number> { // error
140+
interface C<T extends number> { // ok
141141
>C : Symbol(C, Decl(twoGenericInterfacesWithDifferentConstraints.ts, 50, 1), Decl(twoGenericInterfacesWithDifferentConstraints.ts, 54, 1))
142142
>T : Symbol(T, Decl(twoGenericInterfacesWithDifferentConstraints.ts, 52, 12), Decl(twoGenericInterfacesWithDifferentConstraints.ts, 56, 12))
143143

tests/baselines/reference/twoGenericInterfacesWithDifferentConstraints.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ interface C<T> {
7070
>x : T
7171
}
7272

73-
interface C<T extends number> { // error
73+
interface C<T extends number> { // ok
7474
y: T;
7575
>y : T
7676
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// @filename: working.ts
2+
// minmal samples from #33395
3+
export namespace ns {
4+
interface Function<T extends (...args: any) => any> {
5+
throttle(): Function<T>;
6+
}
7+
interface Function<T> {
8+
unary(): Function<() => ReturnType<T>>;
9+
}
10+
}
11+
// @filename: regression.ts
12+
export namespace ns {
13+
interface Function<T> {
14+
unary(): Function<() => ReturnType<T>>;
15+
}
16+
interface Function<T extends (...args: any) => any> {
17+
throttle(): Function<T>;
18+
}
19+
}

tests/cases/conformance/interfaces/declarationMerging/twoGenericInterfacesWithDifferentConstraints.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ interface C<T> {
5454
x: T;
5555
}
5656

57-
interface C<T extends number> { // error
57+
interface C<T extends number> { // ok
5858
y: T;
5959
}
6060

0 commit comments

Comments
 (0)