mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-18 07:29:16 -05:00
Variance annotations on class expressions + deferred valiation (#48645)
* Variance annotations on class expressions + deferred validation * Add regression tests
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 <out T> {
|
||||
foo(): InstanceType<(typeof Anon<T>)> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
let OuterC = class C<out T> {
|
||||
foo(): C<T> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <out T> {
|
||||
foo(): InstanceType<(typeof Anon<T>)> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
let OuterC = class C<out T> {
|
||||
foo(): C<T> {
|
||||
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 <out T>(): {
|
||||
foo(): any;
|
||||
};
|
||||
};
|
||||
declare let OuterC: {
|
||||
new <out T>(): {
|
||||
foo(): any;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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 <out T> {
|
||||
>Anon : Symbol(Anon, Decl(varianceAnnotations.ts, 163, 3))
|
||||
>T : Symbol(T, Decl(varianceAnnotations.ts, 163, 18))
|
||||
|
||||
foo(): InstanceType<(typeof Anon<T>)> {
|
||||
>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<out T> {
|
||||
>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<T> {
|
||||
>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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <out T> {
|
||||
>Anon : typeof Anon
|
||||
>class <out T> { foo(): InstanceType<(typeof Anon<T>)> { return this; }} : typeof Anon
|
||||
|
||||
foo(): InstanceType<(typeof Anon<T>)> {
|
||||
>foo : () => InstanceType<(typeof Anon<T>)>
|
||||
>Anon : typeof Anon
|
||||
|
||||
return this;
|
||||
>this : this
|
||||
}
|
||||
}
|
||||
|
||||
let OuterC = class C<out T> {
|
||||
>OuterC : typeof C
|
||||
>class C<out T> { foo(): C<T> { return this; }} : typeof C
|
||||
>C : typeof C
|
||||
|
||||
foo(): C<T> {
|
||||
>foo : () => C<T>
|
||||
|
||||
return this;
|
||||
>this : this
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <out T> {
|
||||
foo(): InstanceType<(typeof Anon<T>)> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
let OuterC = class C<out T> {
|
||||
foo(): C<T> {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user