diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26299645537e6..421162a07f8d5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34838,11 +34838,17 @@ namespace ts { if (constraintType && defaultType) { checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); } - if (node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.ClassDeclaration || node.parent.kind === SyntaxKind.TypeAliasDeclaration) { + checkNodeDeferred(node); + addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0)); + } + + function checkTypeParameterDeferred(node: TypeParameterDeclaration) { + if (isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent)) { + const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); const modifiers = getVarianceModifiers(typeParameter); if (modifiers) { const symbol = getSymbolOfNode(node.parent); - if (node.parent.kind === SyntaxKind.TypeAliasDeclaration && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) { + if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) { error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types); } else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) { @@ -34855,7 +34861,6 @@ namespace ts { } } } - addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0)); } function checkParameter(node: ParameterDeclaration) { @@ -41354,6 +41359,9 @@ namespace ts { case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node as ClassExpression); break; + case SyntaxKind.TypeParameter: + checkTypeParameterDeferred(node as TypeParameterDeclaration); + break; case SyntaxKind.JsxSelfClosingElement: checkJsxSelfClosingElementDeferred(node as JsxSelfClosingElement); break; @@ -43551,8 +43559,7 @@ namespace ts { case SyntaxKind.OutKeyword: const inOutFlag = modifier.kind === SyntaxKind.InKeyword ? ModifierFlags.In : ModifierFlags.Out; const inOutText = modifier.kind === SyntaxKind.InKeyword ? "in" : "out"; - if (node.kind !== SyntaxKind.TypeParameter || (node.parent.kind !== SyntaxKind.InterfaceDeclaration && - node.parent.kind !== SyntaxKind.ClassDeclaration && node.parent.kind !== SyntaxKind.TypeAliasDeclaration)) { + if (node.kind !== SyntaxKind.TypeParameter || !(isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent))) { return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_type_parameter_of_a_class_interface_or_type_alias, inOutText); } if (flags & inOutFlag) { diff --git a/tests/baselines/reference/varianceAnnotations.errors.txt b/tests/baselines/reference/varianceAnnotations.errors.txt index 5cd036e723471..ee3d74ba561da 100644 --- a/tests/baselines/reference/varianceAnnotations.errors.txt +++ b/tests/baselines/reference/varianceAnnotations.errors.txt @@ -324,4 +324,18 @@ tests/cases/conformance/types/typeParameters/typeParameterLists/varianceAnnotati !!! error TS2345: Types of property '_storedEvent' are incompatible. !!! error TS2345: Type '{ type: "PLAY"; value: number; } | { type: "RESET"; }' is not assignable to type '{ type: "PLAY"; value: number; }'. !!! error TS2345: Type '{ type: "RESET"; }' is not assignable to type '{ type: "PLAY"; value: number; }'. + + // Repros from #48618 + + let Anon = class { + foo(): InstanceType<(typeof Anon)> { + return this; + } + } + + let OuterC = class C { + foo(): C { + return this; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/varianceAnnotations.js b/tests/baselines/reference/varianceAnnotations.js index 7e3fac5285ee3..aaecab6ac6803 100644 --- a/tests/baselines/reference/varianceAnnotations.js +++ b/tests/baselines/reference/varianceAnnotations.js @@ -159,6 +159,20 @@ interpret(machine); declare const qq: ActionObject<{ type: "PLAY"; value: number }>; createMachine<{ type: "PLAY"; value: number } | { type: "RESET" }>(qq); // Error + +// Repros from #48618 + +let Anon = class { + foo(): InstanceType<(typeof Anon)> { + return this; + } +} + +let OuterC = class C { + foo(): C { + return this; + } +} //// [varianceAnnotations.js] @@ -186,6 +200,23 @@ var notString = pu; // Error var machine = createMachine({}); interpret(machine); createMachine(qq); // Error +// Repros from #48618 +var Anon = /** @class */ (function () { + function class_1() { + } + class_1.prototype.foo = function () { + return this; + }; + return class_1; +}()); +var OuterC = /** @class */ (function () { + function C() { + } + C.prototype.foo = function () { + return this; + }; + return C; +}()); //// [varianceAnnotations.d.ts] @@ -293,3 +324,13 @@ declare const qq: ActionObject<{ type: "PLAY"; value: number; }>; +declare let Anon: { + new (): { + foo(): any; + }; +}; +declare let OuterC: { + new (): { + foo(): any; + }; +}; diff --git a/tests/baselines/reference/varianceAnnotations.symbols b/tests/baselines/reference/varianceAnnotations.symbols index 78a5b9be39322..a000fe43e794b 100644 --- a/tests/baselines/reference/varianceAnnotations.symbols +++ b/tests/baselines/reference/varianceAnnotations.symbols @@ -448,3 +448,35 @@ createMachine<{ type: "PLAY"; value: number } | { type: "RESET" }>(qq); // Erro >type : Symbol(type, Decl(varianceAnnotations.ts, 159, 49)) >qq : Symbol(qq, Decl(varianceAnnotations.ts, 157, 13)) +// Repros from #48618 + +let Anon = class { +>Anon : Symbol(Anon, Decl(varianceAnnotations.ts, 163, 3)) +>T : Symbol(T, Decl(varianceAnnotations.ts, 163, 18)) + + foo(): InstanceType<(typeof Anon)> { +>foo : Symbol(Anon.foo, Decl(varianceAnnotations.ts, 163, 26)) +>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --)) +>Anon : Symbol(Anon, Decl(varianceAnnotations.ts, 163, 3)) +>T : Symbol(T, Decl(varianceAnnotations.ts, 163, 18)) + + return this; +>this : Symbol(Anon, Decl(varianceAnnotations.ts, 163, 10)) + } +} + +let OuterC = class C { +>OuterC : Symbol(OuterC, Decl(varianceAnnotations.ts, 169, 3)) +>C : Symbol(C, Decl(varianceAnnotations.ts, 169, 12)) +>T : Symbol(T, Decl(varianceAnnotations.ts, 169, 21)) + + foo(): C { +>foo : Symbol(C.foo, Decl(varianceAnnotations.ts, 169, 29)) +>C : Symbol(C, Decl(varianceAnnotations.ts, 169, 12)) +>T : Symbol(T, Decl(varianceAnnotations.ts, 169, 21)) + + return this; +>this : Symbol(C, Decl(varianceAnnotations.ts, 169, 12)) + } +} + diff --git a/tests/baselines/reference/varianceAnnotations.types b/tests/baselines/reference/varianceAnnotations.types index e584d60a696c2..99c287766acee 100644 --- a/tests/baselines/reference/varianceAnnotations.types +++ b/tests/baselines/reference/varianceAnnotations.types @@ -346,3 +346,31 @@ createMachine<{ type: "PLAY"; value: number } | { type: "RESET" }>(qq); // Erro >type : "RESET" >qq : ActionObject<{ type: "PLAY"; value: number; }> +// Repros from #48618 + +let Anon = class { +>Anon : typeof Anon +>class { foo(): InstanceType<(typeof Anon)> { return this; }} : typeof Anon + + foo(): InstanceType<(typeof Anon)> { +>foo : () => InstanceType<(typeof Anon)> +>Anon : typeof Anon + + return this; +>this : this + } +} + +let OuterC = class C { +>OuterC : typeof C +>class C { foo(): C { return this; }} : typeof C +>C : typeof C + + foo(): C { +>foo : () => C + + return this; +>this : this + } +} + diff --git a/tests/cases/conformance/types/typeParameters/typeParameterLists/varianceAnnotations.ts b/tests/cases/conformance/types/typeParameters/typeParameterLists/varianceAnnotations.ts index 1a75b0c97a460..d2abd84ce6963 100644 --- a/tests/cases/conformance/types/typeParameters/typeParameterLists/varianceAnnotations.ts +++ b/tests/cases/conformance/types/typeParameters/typeParameterLists/varianceAnnotations.ts @@ -161,3 +161,17 @@ interpret(machine); declare const qq: ActionObject<{ type: "PLAY"; value: number }>; createMachine<{ type: "PLAY"; value: number } | { type: "RESET" }>(qq); // Error + +// Repros from #48618 + +let Anon = class { + foo(): InstanceType<(typeof Anon)> { + return this; + } +} + +let OuterC = class C { + foo(): C { + return this; + } +}