@@ -865,6 +865,11 @@ namespace ts {
865
865
error(errorLocation, Diagnostics.Static_members_cannot_reference_class_type_parameters);
866
866
return undefined;
867
867
}
868
+ // Only perform additional check if error reporting was requested
869
+ if (nameNotFoundMessage && !isTypeParameterSymbolDeclaredInContainer(result, location)) {
870
+ error(errorLocation, Diagnostics.Type_parameter_0_cannot_be_referenced_outside_of_the_declaration_that_defines_it, symbolToString(result));
871
+ return undefined;
872
+ }
868
873
break loop;
869
874
}
870
875
if (location.kind === SyntaxKind.ClassExpression && meaning & SymbolFlags.Class) {
@@ -1008,6 +1013,16 @@ namespace ts {
1008
1013
return result;
1009
1014
}
1010
1015
1016
+ function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) {
1017
+ for (const decl of symbol.declarations) {
1018
+ if (decl.kind === SyntaxKind.TypeParameter && decl.parent === container) {
1019
+ return true;
1020
+ }
1021
+ }
1022
+
1023
+ return false;
1024
+ }
1025
+
1011
1026
function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean {
1012
1027
if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(<Identifier>errorLocation)) || isInTypeQuery(errorLocation))) {
1013
1028
return false;
@@ -5226,18 +5241,11 @@ namespace ts {
5226
5241
// Map an unsatisfied type parameter with a default type.
5227
5242
// If a type parameter does not have a default type, or if the default type
5228
5243
// is a forward reference, the empty object type is used.
5229
- const mapper: TypeMapper = t => {
5230
- const i = indexOf(typeParameters, t);
5231
- if (i >= typeArguments.length) {
5232
- return emptyObjectType;
5233
- }
5234
- if (i >= 0) {
5235
- return typeArguments[i];
5236
- }
5237
- return t;
5238
- };
5239
-
5240
5244
for (let i = numTypeArguments; i < numTypeParameters; i++) {
5245
+ typeArguments[i] = emptyObjectType;
5246
+ }
5247
+ for (let i = numTypeArguments; i < numTypeParameters; i++) {
5248
+ const mapper = createTypeMapper(typeParameters, typeArguments);
5241
5249
const defaultType = getDefaultFromTypeParameter(typeParameters[i]);
5242
5250
typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : emptyObjectType;
5243
5251
}
@@ -6712,6 +6720,16 @@ namespace ts {
6712
6720
return createTypeMapper(sources, undefined);
6713
6721
}
6714
6722
6723
+ /**
6724
+ * Maps forward-references to later types parameters to the empty object type.
6725
+ * This is used during inference when instantiating type parameter defaults.
6726
+ */
6727
+ function createBackreferenceMapper(typeParameters: TypeParameter[], index: number) {
6728
+ const mapper: TypeMapper = t => indexOf(typeParameters, t) >= index ? emptyObjectType : t;
6729
+ mapper.mappedTypes = typeParameters;
6730
+ return mapper;
6731
+ }
6732
+
6715
6733
function getInferenceMapper(context: InferenceContext): TypeMapper {
6716
6734
if (!context.mapper) {
6717
6735
const mapper: TypeMapper = t => {
@@ -9194,9 +9212,12 @@ namespace ts {
9194
9212
// candidates with no common supertype.
9195
9213
const defaultType = getDefaultFromTypeParameter(context.signature.typeParameters[index]);
9196
9214
if (defaultType) {
9197
- const backreferenceMapper: TypeMapper = t => indexOf(context.signature.typeParameters, t) >= index ? emptyObjectType : t;
9198
- const mapper = combineTypeMappers(backreferenceMapper, getInferenceMapper(context));
9199
- inferredType = instantiateType(defaultType, mapper);
9215
+ // Instantiate the default type. Any forward reference to a type
9216
+ // parameter should be instantiated to the empty object type.
9217
+ inferredType = instantiateType(defaultType,
9218
+ combineTypeMappers(
9219
+ createBackreferenceMapper(context.signature.typeParameters, index),
9220
+ getInferenceMapper(context)));
9200
9221
}
9201
9222
else {
9202
9223
inferredType = emptyObjectType;
@@ -16216,9 +16237,6 @@ namespace ts {
16216
16237
checkTypeArgumentConstraints(typeParameters, node.typeArguments, minTypeArgumentCount);
16217
16238
}
16218
16239
}
16219
- if (type.flags & TypeFlags.TypeParameter && !(<TypeParameter>type).isThisType && type.symbol && !isTypeParameterInScope(<TypeParameter>type, node)) {
16220
- error(node, Diagnostics.Type_parameter_0_cannot_be_referenced_outside_of_the_declaration_that_defines_it, symbolToString(type.symbol));
16221
- }
16222
16240
if (type.flags & TypeFlags.Enum && !(<EnumType>type).memberTypes && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) {
16223
16241
error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
16224
16242
}
@@ -17657,23 +17675,6 @@ namespace ts {
17657
17675
}
17658
17676
}
17659
17677
17660
- function isTypeParameterInScope(typeParameter: TypeParameter, node: Node) {
17661
- const parents = map(filter(typeParameter.symbol.declarations, isTypeParameter), node => node.parent);
17662
- while (node) {
17663
- if (isFunctionLike(node) ||
17664
- isClassLike(node) ||
17665
- node.kind === SyntaxKind.InterfaceDeclaration ||
17666
- node.kind === SyntaxKind.TypeAliasDeclaration ||
17667
- node.kind === SyntaxKind.MappedType) {
17668
- if (contains(parents, node)) {
17669
- return true;
17670
- }
17671
- }
17672
- node = node.parent;
17673
- }
17674
- return false;
17675
- }
17676
-
17677
17678
function areDeclarationFlagsIdentical(left: Declaration, right: Declaration) {
17678
17679
if ((left.kind === SyntaxKind.Parameter && right.kind === SyntaxKind.VariableDeclaration) ||
17679
17680
(left.kind === SyntaxKind.VariableDeclaration && right.kind === SyntaxKind.Parameter)) {
0 commit comments