Merge pull request #15537 from Microsoft/emit-declaration-of-class-extending-intersection
Emit declaration of class extending intersection
This commit is contained in:
commit
4303a294f9
23 changed files with 303 additions and 128 deletions
|
@ -22750,16 +22750,6 @@ namespace ts {
|
|||
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
|
||||
}
|
||||
|
||||
function writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
|
||||
const classType = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(node));
|
||||
resolveBaseTypesOfClass(classType);
|
||||
const baseType = classType.resolvedBaseTypes.length ? classType.resolvedBaseTypes[0] : unknownType;
|
||||
if (!baseType.symbol) {
|
||||
writer.reportIllegalExtends();
|
||||
}
|
||||
getSymbolDisplayBuilder().buildTypeDisplay(baseType, writer, enclosingDeclaration, flags);
|
||||
}
|
||||
|
||||
function hasGlobalName(name: string): boolean {
|
||||
return globals.has(name);
|
||||
}
|
||||
|
@ -22853,7 +22843,6 @@ namespace ts {
|
|||
writeTypeOfDeclaration,
|
||||
writeReturnTypeOfSignatureDeclaration,
|
||||
writeTypeOfExpression,
|
||||
writeBaseConstructorTypeOfClass,
|
||||
isSymbolAccessible,
|
||||
isEntityNameVisible,
|
||||
getConstantValue: node => {
|
||||
|
|
|
@ -594,12 +594,11 @@ namespace ts {
|
|||
emitLines(node.statements);
|
||||
}
|
||||
|
||||
// Return a temp variable name to be used in `export default` statements.
|
||||
// Return a temp variable name to be used in `export default`/`export class ... extends` statements.
|
||||
// The temp name will be of the form _default_counter.
|
||||
// Note that export default is only allowed at most once in a module, so we
|
||||
// do not need to keep track of created temp names.
|
||||
function getExportDefaultTempVariableName(): string {
|
||||
const baseName = "_default";
|
||||
function getExportTempVariableName(baseName: string): string {
|
||||
if (!currentIdentifiers.has(baseName)) {
|
||||
return baseName;
|
||||
}
|
||||
|
@ -613,24 +612,31 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function emitTempVariableDeclaration(expr: Expression, baseName: string, diagnostic: SymbolAccessibilityDiagnostic): string {
|
||||
const tempVarName = getExportTempVariableName(baseName);
|
||||
if (!noDeclare) {
|
||||
write("declare ");
|
||||
}
|
||||
write("const ");
|
||||
write(tempVarName);
|
||||
write(": ");
|
||||
writer.getSymbolAccessibilityDiagnostic = () => diagnostic;
|
||||
resolver.writeTypeOfExpression(expr, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
write(";");
|
||||
writeLine();
|
||||
return tempVarName;
|
||||
}
|
||||
|
||||
function emitExportAssignment(node: ExportAssignment) {
|
||||
if (node.expression.kind === SyntaxKind.Identifier) {
|
||||
write(node.isExportEquals ? "export = " : "export default ");
|
||||
writeTextOfNode(currentText, node.expression);
|
||||
}
|
||||
else {
|
||||
// Expression
|
||||
const tempVarName = getExportDefaultTempVariableName();
|
||||
if (!noDeclare) {
|
||||
write("declare ");
|
||||
}
|
||||
write("var ");
|
||||
write(tempVarName);
|
||||
write(": ");
|
||||
writer.getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic;
|
||||
resolver.writeTypeOfExpression(node.expression, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
write(";");
|
||||
writeLine();
|
||||
const tempVarName = emitTempVariableDeclaration(node.expression, "_default", {
|
||||
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
|
||||
errorNode: node
|
||||
});
|
||||
write(node.isExportEquals ? "export = " : "export default ");
|
||||
write(tempVarName);
|
||||
}
|
||||
|
@ -644,13 +650,6 @@ namespace ts {
|
|||
// write each of these declarations asynchronously
|
||||
writeAsynchronousModuleElements(nodes);
|
||||
}
|
||||
|
||||
function getDefaultExportAccessibilityDiagnostic(): SymbolAccessibilityDiagnostic {
|
||||
return {
|
||||
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
|
||||
errorNode: node
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function isModuleElementVisible(node: Declaration) {
|
||||
|
@ -1097,7 +1096,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function emitHeritageClause(className: Identifier, typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
function emitHeritageClause(typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
if (typeReferences) {
|
||||
write(isImplementsList ? " implements " : " extends ");
|
||||
emitCommaList(typeReferences, emitTypeOfTypeReference);
|
||||
|
@ -1110,12 +1109,6 @@ namespace ts {
|
|||
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {
|
||||
write("null");
|
||||
}
|
||||
else {
|
||||
writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError;
|
||||
errorNameNode = className;
|
||||
resolver.writeBaseConstructorTypeOfClass(<ClassLikeDeclaration>enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
|
||||
function getHeritageClauseVisibilityError(): SymbolAccessibilityDiagnostic {
|
||||
let diagnosticMessage: DiagnosticMessage;
|
||||
|
@ -1151,23 +1144,43 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
const prevEnclosingDeclaration = enclosingDeclaration;
|
||||
enclosingDeclaration = node;
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
let tempVarName: string;
|
||||
if (baseTypeNode && !isEntityNameExpression(baseTypeNode.expression)) {
|
||||
tempVarName = baseTypeNode.expression.kind === SyntaxKind.NullKeyword ?
|
||||
"null" :
|
||||
emitTempVariableDeclaration(baseTypeNode.expression, `${node.name.text}_base`, {
|
||||
diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
|
||||
errorNode: baseTypeNode,
|
||||
typeName: node.name
|
||||
});
|
||||
}
|
||||
|
||||
emitJsDocComments(node);
|
||||
emitModuleElementDeclarationFlags(node);
|
||||
if (hasModifier(node, ModifierFlags.Abstract)) {
|
||||
write("abstract ");
|
||||
}
|
||||
|
||||
write("class ");
|
||||
writeTextOfNode(currentText, node.name);
|
||||
const prevEnclosingDeclaration = enclosingDeclaration;
|
||||
enclosingDeclaration = node;
|
||||
emitTypeParameters(node.typeParameters);
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
if (baseTypeNode) {
|
||||
node.name;
|
||||
emitHeritageClause(node.name, [baseTypeNode], /*isImplementsList*/ false);
|
||||
if (!isEntityNameExpression(baseTypeNode.expression)) {
|
||||
write(" extends ");
|
||||
write(tempVarName);
|
||||
if (baseTypeNode.typeArguments) {
|
||||
write("<");
|
||||
emitCommaList(baseTypeNode.typeArguments, emitType);
|
||||
write(">");
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
|
||||
}
|
||||
}
|
||||
emitHeritageClause(node.name, getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
|
||||
emitHeritageClause(getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
|
||||
write(" {");
|
||||
writeLine();
|
||||
increaseIndent();
|
||||
|
@ -1189,7 +1202,7 @@ namespace ts {
|
|||
emitTypeParameters(node.typeParameters);
|
||||
const interfaceExtendsTypes = filter(getInterfaceBaseTypeNodes(node), base => isEntityNameExpression(base.expression));
|
||||
if (interfaceExtendsTypes && interfaceExtendsTypes.length) {
|
||||
emitHeritageClause(node.name, interfaceExtendsTypes, /*isImplementsList*/ false);
|
||||
emitHeritageClause(interfaceExtendsTypes, /*isImplementsList*/ false);
|
||||
}
|
||||
write(" {");
|
||||
writeLine();
|
||||
|
|
|
@ -2734,7 +2734,6 @@ namespace ts {
|
|||
writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult;
|
||||
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
|
||||
|
|
|
@ -7,5 +7,5 @@ export default 1 + 2;
|
|||
|
||||
|
||||
//// [declarationEmitDefaultExport5.d.ts]
|
||||
declare var _default: number;
|
||||
declare const _default: number;
|
||||
export default _default;
|
||||
|
|
|
@ -12,5 +12,5 @@ export default new A();
|
|||
//// [declarationEmitDefaultExport6.d.ts]
|
||||
export declare class A {
|
||||
}
|
||||
declare var _default: A;
|
||||
declare const _default: A;
|
||||
export default _default;
|
||||
|
|
|
@ -13,5 +13,5 @@ export default 1 + 2;
|
|||
//// [declarationEmitDefaultExport8.d.ts]
|
||||
declare var _default: number;
|
||||
export { _default as d };
|
||||
declare var _default_1: number;
|
||||
declare const _default_1: number;
|
||||
export default _default_1;
|
||||
|
|
|
@ -15,5 +15,5 @@ System.register([], function (exports_1, context_1) {
|
|||
|
||||
|
||||
//// [pi.d.ts]
|
||||
declare var _default: 3.14159;
|
||||
declare const _default: 3.14159;
|
||||
export default _default;
|
||||
|
|
|
@ -16,6 +16,6 @@ System.register("pi", [], function (exports_1, context_1) {
|
|||
|
||||
//// [app.d.ts]
|
||||
declare module "pi" {
|
||||
var _default: 3.14159;
|
||||
const _default: 3.14159;
|
||||
export default _default;
|
||||
}
|
||||
|
|
|
@ -45,5 +45,6 @@ declare class C<T, U> {
|
|||
y: U;
|
||||
}
|
||||
declare function getClass<T>(c: T): typeof C;
|
||||
declare class MyClass extends C<string, number> {
|
||||
declare const MyClass_base: typeof C;
|
||||
declare class MyClass extends MyClass_base<string, number> {
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
tests/cases/compiler/declarationEmitExpressionInExtends3.ts(28,30): error TS4020: 'extends' clause of exported class 'MyClass' has or is using private name 'LocalClass'.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends3.ts(36,31): error TS4020: 'extends' clause of exported class 'MyClass3' has or is using private name 'LocalInterface'.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends3.ts(36,75): error TS4020: 'extends' clause of exported class 'MyClass3' has or is using private name 'LocalInterface'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/declarationEmitExpressionInExtends3.ts (2 errors) ====
|
||||
|
@ -41,7 +41,7 @@ tests/cases/compiler/declarationEmitExpressionInExtends3.ts(36,31): error TS4020
|
|||
|
||||
|
||||
export class MyClass3 extends getExportedClass<LocalInterface>(undefined)<LocalInterface> { // Error LocalInterface is inaccisble
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS4020: 'extends' clause of exported class 'MyClass3' has or is using private name 'LocalInterface'.
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(1,10): error TS4060: Return type of exported function has or is using private name 'D'.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(5,7): error TS4093: 'extends' clause of exported class 'C' refers to a type whose name cannot be referenced.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(5,17): error TS2315: Type 'D' is not generic.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(9,7): error TS4093: 'extends' clause of exported class 'C2' refers to a type whose name cannot be referenced.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(5,17): error TS4020: 'extends' clause of exported class 'C' has or is using private name 'D'.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(9,18): error TS2304: Cannot find name 'SomeUndefinedFunction'.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(14,18): error TS2304: Cannot find name 'SomeUndefinedFunction'.
|
||||
tests/cases/compiler/declarationEmitExpressionInExtends4.ts(14,18): error TS4020: 'extends' clause of exported class 'C3' has or is using private name 'SomeUndefinedFunction'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/declarationEmitExpressionInExtends4.ts (7 errors) ====
|
||||
==== tests/cases/compiler/declarationEmitExpressionInExtends4.ts (6 errors) ====
|
||||
function getSomething() {
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS4060: Return type of exported function has or is using private name 'D'.
|
||||
|
@ -15,16 +14,14 @@ tests/cases/compiler/declarationEmitExpressionInExtends4.ts(14,18): error TS4020
|
|||
}
|
||||
|
||||
class C extends getSomething()<number, string> {
|
||||
~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C' refers to a type whose name cannot be referenced.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2315: Type 'D' is not generic.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS4020: 'extends' clause of exported class 'C' has or is using private name 'D'.
|
||||
|
||||
}
|
||||
|
||||
class C2 extends SomeUndefinedFunction()<number, string> {
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C2' refers to a type whose name cannot be referenced.
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'SomeUndefinedFunction'.
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ exports["default"] = {
|
|||
|
||||
|
||||
//// [declarationEmitInferedDefaultExportType.d.ts]
|
||||
declare var _default: {
|
||||
declare const _default: {
|
||||
foo: any[];
|
||||
bar: any;
|
||||
baz: any;
|
||||
|
|
|
@ -16,7 +16,7 @@ module.exports = {
|
|||
|
||||
|
||||
//// [declarationEmitInferedDefaultExportType2.d.ts]
|
||||
declare var _default: {
|
||||
declare const _default: {
|
||||
foo: any[];
|
||||
bar: any;
|
||||
baz: any;
|
||||
|
|
|
@ -9,5 +9,5 @@ exports.default = (1 + 2);
|
|||
|
||||
|
||||
//// [es5ExportDefaultExpression.d.ts]
|
||||
declare var _default: number;
|
||||
declare const _default: number;
|
||||
export default _default;
|
||||
|
|
|
@ -7,5 +7,5 @@ export default (1 + 2);
|
|||
|
||||
|
||||
//// [es6ExportDefaultExpression.d.ts]
|
||||
declare var _default: number;
|
||||
declare const _default: number;
|
||||
export default _default;
|
||||
|
|
|
@ -48,6 +48,6 @@ var x1 = es6ImportDefaultBindingFollowedWithNamedImport_0_5.m;
|
|||
export declare var a: number;
|
||||
export declare var x: number;
|
||||
export declare var m: number;
|
||||
declare var _default: {};
|
||||
declare const _default: {};
|
||||
export default _default;
|
||||
//// [es6ImportDefaultBindingFollowedWithNamedImport_1.d.ts]
|
||||
|
|
|
@ -47,7 +47,7 @@ define(["require", "exports", "server", "server", "server", "server", "server"],
|
|||
export declare var a: number;
|
||||
export declare var x: number;
|
||||
export declare var m: number;
|
||||
declare var _default: {};
|
||||
declare const _default: {};
|
||||
export default _default;
|
||||
//// [client.d.ts]
|
||||
export declare var x1: number;
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
tests/cases/compiler/FinalClass.ts(4,14): error TS4093: 'extends' clause of exported class 'MyExtendedClass' refers to a type whose name cannot be referenced.
|
||||
|
||||
|
||||
==== tests/cases/compiler/BaseClass.ts (0 errors) ====
|
||||
export type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
export class MyBaseClass<T> {
|
||||
baseProperty: string;
|
||||
constructor(value: T) {}
|
||||
}
|
||||
==== tests/cases/compiler/MixinClass.ts (0 errors) ====
|
||||
import { Constructor, MyBaseClass } from './BaseClass';
|
||||
|
||||
export interface MyMixin {
|
||||
mixinProperty: string;
|
||||
}
|
||||
|
||||
export function MyMixin<T extends Constructor<MyBaseClass<any>>>(base: T): T & Constructor<MyMixin> {
|
||||
return class extends base {
|
||||
mixinProperty: string;
|
||||
}
|
||||
}
|
||||
==== tests/cases/compiler/FinalClass.ts (1 errors) ====
|
||||
import { MyBaseClass } from './BaseClass';
|
||||
import { MyMixin } from './MixinClass';
|
||||
|
||||
export class MyExtendedClass extends MyMixin(MyBaseClass)<string> {
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'MyExtendedClass' refers to a type whose name cannot be referenced.
|
||||
extendedClassProperty: number;
|
||||
}
|
||||
==== tests/cases/compiler/Main.ts (0 errors) ====
|
||||
import { MyExtendedClass } from './FinalClass';
|
||||
import { MyMixin } from './MixinClass';
|
||||
|
||||
const myExtendedClass = new MyExtendedClass('string');
|
||||
|
||||
const AnotherMixedClass = MyMixin(MyExtendedClass);
|
||||
|
|
@ -111,4 +111,11 @@ export interface MyMixin {
|
|||
mixinProperty: string;
|
||||
}
|
||||
export declare function MyMixin<T extends Constructor<MyBaseClass<any>>>(base: T): T & Constructor<MyMixin>;
|
||||
//// [FinalClass.d.ts]
|
||||
import { MyBaseClass } from './BaseClass';
|
||||
import { MyMixin } from './MixinClass';
|
||||
declare const MyExtendedClass_base: typeof MyBaseClass & (new (...args: any[]) => MyMixin);
|
||||
export declare class MyExtendedClass extends MyExtendedClass_base<string> {
|
||||
extendedClassProperty: number;
|
||||
}
|
||||
//// [Main.d.ts]
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
=== tests/cases/compiler/BaseClass.ts ===
|
||||
export type Constructor<T> = new (...args: any[]) => T;
|
||||
>Constructor : Symbol(Constructor, Decl(BaseClass.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(BaseClass.ts, 0, 24))
|
||||
>args : Symbol(args, Decl(BaseClass.ts, 0, 34))
|
||||
>T : Symbol(T, Decl(BaseClass.ts, 0, 24))
|
||||
|
||||
export class MyBaseClass<T> {
|
||||
>MyBaseClass : Symbol(MyBaseClass, Decl(BaseClass.ts, 0, 55))
|
||||
>T : Symbol(T, Decl(BaseClass.ts, 2, 25))
|
||||
|
||||
baseProperty: string;
|
||||
>baseProperty : Symbol(MyBaseClass.baseProperty, Decl(BaseClass.ts, 2, 29))
|
||||
|
||||
constructor(value: T) {}
|
||||
>value : Symbol(value, Decl(BaseClass.ts, 4, 16))
|
||||
>T : Symbol(T, Decl(BaseClass.ts, 2, 25))
|
||||
}
|
||||
=== tests/cases/compiler/MixinClass.ts ===
|
||||
import { Constructor, MyBaseClass } from './BaseClass';
|
||||
>Constructor : Symbol(Constructor, Decl(MixinClass.ts, 0, 8))
|
||||
>MyBaseClass : Symbol(MyBaseClass, Decl(MixinClass.ts, 0, 21))
|
||||
|
||||
export interface MyMixin {
|
||||
>MyMixin : Symbol(MyMixin, Decl(MixinClass.ts, 0, 55), Decl(MixinClass.ts, 4, 1))
|
||||
|
||||
mixinProperty: string;
|
||||
>mixinProperty : Symbol(MyMixin.mixinProperty, Decl(MixinClass.ts, 2, 26))
|
||||
}
|
||||
|
||||
export function MyMixin<T extends Constructor<MyBaseClass<any>>>(base: T): T & Constructor<MyMixin> {
|
||||
>MyMixin : Symbol(MyMixin, Decl(MixinClass.ts, 0, 55), Decl(MixinClass.ts, 4, 1))
|
||||
>T : Symbol(T, Decl(MixinClass.ts, 6, 24))
|
||||
>Constructor : Symbol(Constructor, Decl(MixinClass.ts, 0, 8))
|
||||
>MyBaseClass : Symbol(MyBaseClass, Decl(MixinClass.ts, 0, 21))
|
||||
>base : Symbol(base, Decl(MixinClass.ts, 6, 65))
|
||||
>T : Symbol(T, Decl(MixinClass.ts, 6, 24))
|
||||
>T : Symbol(T, Decl(MixinClass.ts, 6, 24))
|
||||
>Constructor : Symbol(Constructor, Decl(MixinClass.ts, 0, 8))
|
||||
>MyMixin : Symbol(MyMixin, Decl(MixinClass.ts, 0, 55), Decl(MixinClass.ts, 4, 1))
|
||||
|
||||
return class extends base {
|
||||
>base : Symbol(base, Decl(MixinClass.ts, 6, 65))
|
||||
|
||||
mixinProperty: string;
|
||||
>mixinProperty : Symbol((Anonymous class).mixinProperty, Decl(MixinClass.ts, 7, 31))
|
||||
}
|
||||
}
|
||||
=== tests/cases/compiler/FinalClass.ts ===
|
||||
import { MyBaseClass } from './BaseClass';
|
||||
>MyBaseClass : Symbol(MyBaseClass, Decl(FinalClass.ts, 0, 8))
|
||||
|
||||
import { MyMixin } from './MixinClass';
|
||||
>MyMixin : Symbol(MyMixin, Decl(FinalClass.ts, 1, 8))
|
||||
|
||||
export class MyExtendedClass extends MyMixin(MyBaseClass)<string> {
|
||||
>MyExtendedClass : Symbol(MyExtendedClass, Decl(FinalClass.ts, 1, 39))
|
||||
>MyMixin : Symbol(MyMixin, Decl(FinalClass.ts, 1, 8))
|
||||
>MyBaseClass : Symbol(MyBaseClass, Decl(FinalClass.ts, 0, 8))
|
||||
|
||||
extendedClassProperty: number;
|
||||
>extendedClassProperty : Symbol(MyExtendedClass.extendedClassProperty, Decl(FinalClass.ts, 3, 67))
|
||||
}
|
||||
=== tests/cases/compiler/Main.ts ===
|
||||
import { MyExtendedClass } from './FinalClass';
|
||||
>MyExtendedClass : Symbol(MyExtendedClass, Decl(Main.ts, 0, 8))
|
||||
|
||||
import { MyMixin } from './MixinClass';
|
||||
>MyMixin : Symbol(MyMixin, Decl(Main.ts, 1, 8))
|
||||
|
||||
const myExtendedClass = new MyExtendedClass('string');
|
||||
>myExtendedClass : Symbol(myExtendedClass, Decl(Main.ts, 3, 5))
|
||||
>MyExtendedClass : Symbol(MyExtendedClass, Decl(Main.ts, 0, 8))
|
||||
|
||||
const AnotherMixedClass = MyMixin(MyExtendedClass);
|
||||
>AnotherMixedClass : Symbol(AnotherMixedClass, Decl(Main.ts, 5, 5))
|
||||
>MyMixin : Symbol(MyMixin, Decl(Main.ts, 1, 8))
|
||||
>MyExtendedClass : Symbol(MyExtendedClass, Decl(Main.ts, 0, 8))
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
=== tests/cases/compiler/BaseClass.ts ===
|
||||
export type Constructor<T> = new (...args: any[]) => T;
|
||||
>Constructor : Constructor<T>
|
||||
>T : T
|
||||
>args : any[]
|
||||
>T : T
|
||||
|
||||
export class MyBaseClass<T> {
|
||||
>MyBaseClass : MyBaseClass<T>
|
||||
>T : T
|
||||
|
||||
baseProperty: string;
|
||||
>baseProperty : string
|
||||
|
||||
constructor(value: T) {}
|
||||
>value : T
|
||||
>T : T
|
||||
}
|
||||
=== tests/cases/compiler/MixinClass.ts ===
|
||||
import { Constructor, MyBaseClass } from './BaseClass';
|
||||
>Constructor : any
|
||||
>MyBaseClass : typeof MyBaseClass
|
||||
|
||||
export interface MyMixin {
|
||||
>MyMixin : MyMixin
|
||||
|
||||
mixinProperty: string;
|
||||
>mixinProperty : string
|
||||
}
|
||||
|
||||
export function MyMixin<T extends Constructor<MyBaseClass<any>>>(base: T): T & Constructor<MyMixin> {
|
||||
>MyMixin : <T extends Constructor<MyBaseClass<any>>>(base: T) => T & Constructor<MyMixin>
|
||||
>T : T
|
||||
>Constructor : Constructor<T>
|
||||
>MyBaseClass : MyBaseClass<T>
|
||||
>base : T
|
||||
>T : T
|
||||
>T : T
|
||||
>Constructor : Constructor<T>
|
||||
>MyMixin : MyMixin
|
||||
|
||||
return class extends base {
|
||||
>class extends base { mixinProperty: string; } : { new (...args: any[]): (Anonymous class); prototype: MyMixin<any>.(Anonymous class); } & T
|
||||
>base : MyBaseClass<any>
|
||||
|
||||
mixinProperty: string;
|
||||
>mixinProperty : string
|
||||
}
|
||||
}
|
||||
=== tests/cases/compiler/FinalClass.ts ===
|
||||
import { MyBaseClass } from './BaseClass';
|
||||
>MyBaseClass : typeof MyBaseClass
|
||||
|
||||
import { MyMixin } from './MixinClass';
|
||||
>MyMixin : <T extends new (...args: any[]) => MyBaseClass<any>>(base: T) => T & (new (...args: any[]) => MyMixin)
|
||||
|
||||
export class MyExtendedClass extends MyMixin(MyBaseClass)<string> {
|
||||
>MyExtendedClass : MyExtendedClass
|
||||
>MyMixin(MyBaseClass) : MyBaseClass<string> & MyMixin
|
||||
>MyMixin : <T extends new (...args: any[]) => MyBaseClass<any>>(base: T) => T & (new (...args: any[]) => MyMixin)
|
||||
>MyBaseClass : typeof MyBaseClass
|
||||
|
||||
extendedClassProperty: number;
|
||||
>extendedClassProperty : number
|
||||
}
|
||||
=== tests/cases/compiler/Main.ts ===
|
||||
import { MyExtendedClass } from './FinalClass';
|
||||
>MyExtendedClass : typeof MyExtendedClass
|
||||
|
||||
import { MyMixin } from './MixinClass';
|
||||
>MyMixin : <T extends new (...args: any[]) => MyBaseClass<any>>(base: T) => T & (new (...args: any[]) => MyMixin)
|
||||
|
||||
const myExtendedClass = new MyExtendedClass('string');
|
||||
>myExtendedClass : MyExtendedClass
|
||||
>new MyExtendedClass('string') : MyExtendedClass
|
||||
>MyExtendedClass : typeof MyExtendedClass
|
||||
>'string' : "string"
|
||||
|
||||
const AnotherMixedClass = MyMixin(MyExtendedClass);
|
||||
>AnotherMixedClass : typeof MyExtendedClass & (new (...args: any[]) => MyMixin)
|
||||
>MyMixin(MyExtendedClass) : typeof MyExtendedClass & (new (...args: any[]) => MyMixin)
|
||||
>MyMixin : <T extends new (...args: any[]) => MyBaseClass<any>>(base: T) => T & (new (...args: any[]) => MyMixin)
|
||||
>MyExtendedClass : typeof MyExtendedClass
|
||||
|
|
@ -5,25 +5,19 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(50,4): error TS2445: Pro
|
|||
tests/cases/conformance/classes/mixinAccessModifiers.ts(65,7): error TS2415: Class 'C1' incorrectly extends base class 'Private & Private2'.
|
||||
Type 'C1' is not assignable to type 'Private'.
|
||||
Property 'p' has conflicting declarations and is inaccessible in type 'C1'.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(65,7): error TS4093: 'extends' clause of exported class 'C1' refers to a type whose name cannot be referenced.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(66,7): error TS2415: Class 'C2' incorrectly extends base class 'Private & Protected'.
|
||||
Type 'C2' is not assignable to type 'Private'.
|
||||
Property 'p' has conflicting declarations and is inaccessible in type 'C2'.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(66,7): error TS4093: 'extends' clause of exported class 'C2' refers to a type whose name cannot be referenced.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(67,7): error TS2415: Class 'C3' incorrectly extends base class 'Private & Public'.
|
||||
Type 'C3' is not assignable to type 'Private'.
|
||||
Property 'p' has conflicting declarations and is inaccessible in type 'C3'.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(67,7): error TS4093: 'extends' clause of exported class 'C3' refers to a type whose name cannot be referenced.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(69,7): error TS4093: 'extends' clause of exported class 'C4' refers to a type whose name cannot be referenced.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(82,7): error TS4093: 'extends' clause of exported class 'C5' refers to a type whose name cannot be referenced.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(84,6): error TS2445: Property 'p' is protected and only accessible within class 'C4' and its subclasses.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(89,6): error TS2445: Property 's' is protected and only accessible within class 'typeof C4' and its subclasses.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(95,7): error TS4093: 'extends' clause of exported class 'C6' refers to a type whose name cannot be referenced.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(97,6): error TS2445: Property 'p' is protected and only accessible within class 'C4' and its subclasses.
|
||||
tests/cases/conformance/classes/mixinAccessModifiers.ts(102,6): error TS2445: Property 's' is protected and only accessible within class 'typeof C4' and its subclasses.
|
||||
|
||||
|
||||
==== tests/cases/conformance/classes/mixinAccessModifiers.ts (17 errors) ====
|
||||
==== tests/cases/conformance/classes/mixinAccessModifiers.ts (11 errors) ====
|
||||
type Constructable = new (...args: any[]) => object;
|
||||
|
||||
class Private {
|
||||
|
@ -101,26 +95,18 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(102,6): error TS2445: Pr
|
|||
!!! error TS2415: Class 'C1' incorrectly extends base class 'Private & Private2'.
|
||||
!!! error TS2415: Type 'C1' is not assignable to type 'Private'.
|
||||
!!! error TS2415: Property 'p' has conflicting declarations and is inaccessible in type 'C1'.
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C1' refers to a type whose name cannot be referenced.
|
||||
class C2 extends Mix(Private, Protected) {}
|
||||
~~
|
||||
!!! error TS2415: Class 'C2' incorrectly extends base class 'Private & Protected'.
|
||||
!!! error TS2415: Type 'C2' is not assignable to type 'Private'.
|
||||
!!! error TS2415: Property 'p' has conflicting declarations and is inaccessible in type 'C2'.
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C2' refers to a type whose name cannot be referenced.
|
||||
class C3 extends Mix(Private, Public) {}
|
||||
~~
|
||||
!!! error TS2415: Class 'C3' incorrectly extends base class 'Private & Public'.
|
||||
!!! error TS2415: Type 'C3' is not assignable to type 'Private'.
|
||||
!!! error TS2415: Property 'p' has conflicting declarations and is inaccessible in type 'C3'.
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C3' refers to a type whose name cannot be referenced.
|
||||
|
||||
class C4 extends Mix(Protected, Protected2) {
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C4' refers to a type whose name cannot be referenced.
|
||||
f(c4: C4, c5: C5, c6: C6) {
|
||||
c4.p;
|
||||
c5.p;
|
||||
|
@ -134,8 +120,6 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(102,6): error TS2445: Pr
|
|||
}
|
||||
|
||||
class C5 extends Mix(Protected, Public) {
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C5' refers to a type whose name cannot be referenced.
|
||||
f(c4: C4, c5: C5, c6: C6) {
|
||||
c4.p; // Error, not in class deriving from Protected2
|
||||
~
|
||||
|
@ -153,8 +137,6 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(102,6): error TS2445: Pr
|
|||
}
|
||||
|
||||
class C6 extends Mix(Public, Public2) {
|
||||
~~
|
||||
!!! error TS4093: 'extends' clause of exported class 'C6' refers to a type whose name cannot be referenced.
|
||||
f(c4: C4, c5: C5, c6: C6) {
|
||||
c4.p; // Error, not in class deriving from Protected2
|
||||
~
|
||||
|
|
|
@ -263,3 +263,66 @@ var C6 = (function (_super) {
|
|||
};
|
||||
return C6;
|
||||
}(Mix(Public, Public2)));
|
||||
|
||||
|
||||
//// [mixinAccessModifiers.d.ts]
|
||||
declare type Constructable = new (...args: any[]) => object;
|
||||
declare class Private {
|
||||
constructor(...args: any[]);
|
||||
private p;
|
||||
}
|
||||
declare class Private2 {
|
||||
constructor(...args: any[]);
|
||||
private p;
|
||||
}
|
||||
declare class Protected {
|
||||
constructor(...args: any[]);
|
||||
protected p: string;
|
||||
protected static s: string;
|
||||
}
|
||||
declare class Protected2 {
|
||||
constructor(...args: any[]);
|
||||
protected p: string;
|
||||
protected static s: string;
|
||||
}
|
||||
declare class Public {
|
||||
constructor(...args: any[]);
|
||||
p: string;
|
||||
static s: string;
|
||||
}
|
||||
declare class Public2 {
|
||||
constructor(...args: any[]);
|
||||
p: string;
|
||||
static s: string;
|
||||
}
|
||||
declare function f1(x: Private & Private2): void;
|
||||
declare function f2(x: Private & Protected): void;
|
||||
declare function f3(x: Private & Public): void;
|
||||
declare function f4(x: Protected & Protected2): void;
|
||||
declare function f5(x: Protected & Public): void;
|
||||
declare function f6(x: Public & Public2): void;
|
||||
declare function Mix<T, U>(c1: T, c2: U): T & U;
|
||||
declare const C1_base: typeof Private & typeof Private2;
|
||||
declare class C1 extends C1_base {
|
||||
}
|
||||
declare const C2_base: typeof Private & typeof Protected;
|
||||
declare class C2 extends C2_base {
|
||||
}
|
||||
declare const C3_base: typeof Private & typeof Public;
|
||||
declare class C3 extends C3_base {
|
||||
}
|
||||
declare const C4_base: typeof Protected & typeof Protected2;
|
||||
declare class C4 extends C4_base {
|
||||
f(c4: C4, c5: C5, c6: C6): void;
|
||||
static g(): void;
|
||||
}
|
||||
declare const C5_base: typeof Protected & typeof Public;
|
||||
declare class C5 extends C5_base {
|
||||
f(c4: C4, c5: C5, c6: C6): void;
|
||||
static g(): void;
|
||||
}
|
||||
declare const C6_base: typeof Public & typeof Public2;
|
||||
declare class C6 extends C6_base {
|
||||
f(c4: C4, c5: C5, c6: C6): void;
|
||||
static g(): void;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue