diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eddddb5cb2b..b9a8ab6cd2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14013,7 +14013,7 @@ namespace ts { } } - // Check each type parameter and check that list has no duplicate type parameter declarations + /** Check each type parameter and check that type parameters have no duplicate type parameter declarations */ function checkTypeParameters(typeParameterDeclarations: TypeParameterDeclaration[]) { if (typeParameterDeclarations) { for (let i = 0, n = typeParameterDeclarations.length; i < n; i++) { @@ -14031,6 +14031,23 @@ namespace ts { } } + /** Check that type parameter lists are identical across multiple declarations */ + function checkTypeParameterListsIdentical(node: ClassLikeDeclaration | InterfaceDeclaration, symbol: Symbol) { + let firstDecl: ClassLikeDeclaration | InterfaceDeclaration; + if (symbol.declarations.length > 1) { + for (const declaration of symbol.declarations) { + if (declaration.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.InterfaceDeclaration) { + if (!firstDecl) { + firstDecl = declaration; + } + else if (!areTypeParametersIdentical(firstDecl.typeParameters, node.typeParameters)) { + error(node.name, Diagnostics.All_declarations_must_have_identical_type_parameters); + } + } + } + } + } + function checkClassExpression(node: ClassExpression): Type { checkClassLikeDeclaration(node); checkNodeDeferred(node); @@ -14064,6 +14081,7 @@ namespace ts { const type = getDeclaredTypeOfSymbol(symbol); const typeWithThis = getTypeWithThisArgument(type); const staticType = getTypeOfSymbol(symbol); + checkTypeParameterListsIdentical(node, symbol); const baseTypeNode = getClassExtendsHeritageClauseElement(node); if (baseTypeNode) { @@ -14326,14 +14344,10 @@ namespace ts { checkExportsOnMergedDeclarations(node); const symbol = getSymbolOfNode(node); - const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); - if (symbol.declarations.length > 1) { - if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) { - error(node.name, Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters); - } - } + checkTypeParameterListsIdentical(node, symbol); // Only check this symbol once + const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); if (node === firstInterfaceDecl) { const type = getDeclaredTypeOfSymbol(symbol); const typeWithThis = getTypeWithThisArgument(type); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 16cf1911642..92396d005b7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1311,7 +1311,7 @@ "category": "Error", "code": 2427 }, - "All declarations of an interface must have identical type parameters.": { + "All declarations must have identical type parameters.": { "category": "Error", "code": 2428 }, @@ -2801,4 +2801,4 @@ "category": "Error", "code": 17009 } -} +}