Skip to content

Commit bb2eb63

Browse files
committed
Merged classes and interfaces must have identical type constraints
Previously, only interfaces needed to check this, but now that classes and interfaces can merge, the check needs to happen in more places.
1 parent eacc092 commit bb2eb63

2 files changed

Lines changed: 23 additions & 9 deletions

File tree

src/compiler/checker.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14013,7 +14013,7 @@ namespace ts {
1401314013
}
1401414014
}
1401514015

14016-
// Check each type parameter and check that list has no duplicate type parameter declarations
14016+
/** Check each type parameter and check that type parameters have no duplicate type parameter declarations */
1401714017
function checkTypeParameters(typeParameterDeclarations: TypeParameterDeclaration[]) {
1401814018
if (typeParameterDeclarations) {
1401914019
for (let i = 0, n = typeParameterDeclarations.length; i < n; i++) {
@@ -14031,6 +14031,23 @@ namespace ts {
1403114031
}
1403214032
}
1403314033

14034+
/** Check that type parameter lists are identical across multiple declarations */
14035+
function checkTypeParameterListsIdentical(node: ClassLikeDeclaration | InterfaceDeclaration, symbol: Symbol) {
14036+
let firstDecl: ClassLikeDeclaration | InterfaceDeclaration;
14037+
if (symbol.declarations.length > 1) {
14038+
for (const declaration of symbol.declarations) {
14039+
if (declaration.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.InterfaceDeclaration) {
14040+
if (!firstDecl) {
14041+
firstDecl = <ClassLikeDeclaration | InterfaceDeclaration>declaration;
14042+
}
14043+
else if (!areTypeParametersIdentical(firstDecl.typeParameters, node.typeParameters)) {
14044+
error(node.name, Diagnostics.All_declarations_must_have_identical_type_parameters);
14045+
}
14046+
}
14047+
}
14048+
}
14049+
}
14050+
1403414051
function checkClassExpression(node: ClassExpression): Type {
1403514052
checkClassLikeDeclaration(node);
1403614053
checkNodeDeferred(node);
@@ -14064,6 +14081,7 @@ namespace ts {
1406414081
const type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
1406514082
const typeWithThis = getTypeWithThisArgument(type);
1406614083
const staticType = <ObjectType>getTypeOfSymbol(symbol);
14084+
checkTypeParameterListsIdentical(node, symbol);
1406714085

1406814086
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
1406914087
if (baseTypeNode) {
@@ -14326,14 +14344,10 @@ namespace ts {
1432614344

1432714345
checkExportsOnMergedDeclarations(node);
1432814346
const symbol = getSymbolOfNode(node);
14329-
const firstInterfaceDecl = <InterfaceDeclaration>getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration);
14330-
if (symbol.declarations.length > 1) {
14331-
if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
14332-
error(node.name, Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
14333-
}
14334-
}
14347+
checkTypeParameterListsIdentical(node, symbol);
1433514348

1433614349
// Only check this symbol once
14350+
const firstInterfaceDecl = <InterfaceDeclaration>getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration);
1433714351
if (node === firstInterfaceDecl) {
1433814352
const type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
1433914353
const typeWithThis = getTypeWithThisArgument(type);

src/compiler/diagnosticMessages.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@
13111311
"category": "Error",
13121312
"code": 2427
13131313
},
1314-
"All declarations of an interface must have identical type parameters.": {
1314+
"All declarations must have identical type parameters.": {
13151315
"category": "Error",
13161316
"code": 2428
13171317
},
@@ -2801,4 +2801,4 @@
28012801
"category": "Error",
28022802
"code": 17009
28032803
}
2804-
}
2804+
}

0 commit comments

Comments
 (0)