Type parameter defaults can only reference previously declared type parameters

This commit is contained in:
Anders Hejlsberg
2018-12-27 13:45:13 -10:00
parent b8def16e92
commit 3f7a9a906b
2 changed files with 27 additions and 9 deletions

View File

@@ -7928,22 +7928,17 @@ namespace ts {
const numTypeArguments = length(typeArguments);
if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
const result = typeArguments ? typeArguments.slice() : [];
// Map an unsatisfied type parameter with a default type.
// If a type parameter does not have a default type, or if the default type
// is a forward reference, the empty object type is used.
const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
const circularityMapper = createTypeMapper(typeParameters!, map(typeParameters!, () => baseDefaultType));
// Map invalid forward references in default types to the error type
for (let i = numTypeArguments; i < numTypeParameters; i++) {
result[i] = instantiateType(getConstraintFromTypeParameter(typeParameters![i]) || baseDefaultType, circularityMapper);
result[i] = errorType;
}
const baseDefaultType = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
for (let i = numTypeArguments; i < numTypeParameters; i++) {
const mapper = createTypeMapper(typeParameters!, result);
let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
defaultType = anyType;
}
result[i] = defaultType ? instantiateType(defaultType, mapper) : baseDefaultType;
result[i] = defaultType ? instantiateType(defaultType, createTypeMapper(typeParameters!, result)) : baseDefaultType;
}
result.length = typeParameters!.length;
return result;
@@ -26465,6 +26460,7 @@ namespace ts {
if (produceDiagnostics) {
if (node.default) {
seenDefault = true;
checkTypeParametersNotReferenced(node.default, typeParameterDeclarations, i);
}
else if (seenDefault) {
error(node, Diagnostics.Required_type_parameters_may_not_follow_optional_type_parameters);
@@ -26479,6 +26475,24 @@ namespace ts {
}
}
/** Check that type parameter defaults only reference previously declared type parameters */
function checkTypeParametersNotReferenced(root: TypeNode, typeParameters: ReadonlyArray<TypeParameterDeclaration>, index: number) {
visit(root);
function visit(node: Node) {
if (node.kind === SyntaxKind.TypeReference) {
const type = getTypeFromTypeReference(<TypeReferenceNode>node);
if (type.flags & TypeFlags.TypeParameter) {
for (let i = index; i < typeParameters.length; i++) {
if (type.symbol === getSymbolOfNode(typeParameters[i])) {
error(node, Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters);
}
}
}
}
forEachChild(node, visit);
}
}
/** Check that type parameter lists are identical across multiple declarations */
function checkTypeParameterListsIdentical(symbol: Symbol) {
if (symbol.declarations.length === 1) {

View File

@@ -2537,6 +2537,10 @@
"category": "Error",
"code": 2743
},
"Type parameter defaults can only reference previously declared type parameters.": {
"category": "Error",
"code": 2744
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",