diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2a3f2390cf3cd..f0637ba31ad95 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17135,7 +17135,7 @@ namespace ts { const symbol = getResolvedSymbol(node); return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); case SyntaxKind.ThisKeyword: - return checkThisExpression(node); + return getExplicitThisType(node); case SyntaxKind.PropertyAccessExpression: const type = getTypeOfDottedName((node).expression); const prop = type && getPropertyOfType(type, (node).name.escapedText); @@ -18720,6 +18720,20 @@ namespace ts { } } + function getExplicitThisType(node: Expression) { + const container = getThisContainer(node, /*includeArrowFunctions*/ false); + if (isFunctionLike(container)) { + const signature = getSignatureFromDeclaration(container); + if (signature.thisParameter) { + return getExplicitTypeOfSymbol(signature.thisParameter); + } + } + if (isClassLike(container.parent)) { + const symbol = getSymbolOfNode(container.parent); + return hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; + } + } + function getClassNameFromPrototypeMethod(container: Node) { // Check if it's the RHS of a x.prototype.y = function [name]() { .... } if (container.kind === SyntaxKind.FunctionExpression && diff --git a/tests/baselines/reference/neverReturningFunctions1.errors.txt b/tests/baselines/reference/neverReturningFunctions1.errors.txt index f8656bbed0843..5eb6659427c46 100644 --- a/tests/baselines/reference/neverReturningFunctions1.errors.txt +++ b/tests/baselines/reference/neverReturningFunctions1.errors.txt @@ -224,4 +224,73 @@ tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(153,5): error TS ~~ !!! error TS7027: Unreachable code detected. } + + // Repro from #33582 + + export interface Component { + attrName?: string; + data: T; + dependencies?: string[]; + el: any; + id: string; + multiple?: boolean; + name: string; + schema: unknown; + system: any; + + init(data?: T): void; + pause(): void; + play(): void; + remove(): void; + tick?(time: number, timeDelta: number): void; + update(oldData: T): void; + updateSchema?(): void; + + extendSchema(update: unknown): void; + flushToDOM(): void; + } + + export interface ComponentConstructor { + new (el: unknown, attrValue: string, id: string): T & Component; + prototype: T & { + name: string; + system: unknown; + play(): void; + pause(): void; + }; + } + + declare function registerComponent( + name: string, + component: ComponentDefinition + ): ComponentConstructor; + + export type ComponentDefinition = T & Partial & ThisType; + + const Component = registerComponent('test-component', { + schema: { + myProperty: { + default: [], + parse() { + return [true]; + } + }, + string: { type: 'string' }, + num: 0 + }, + init() { + this.data.num = 0; + this.el.setAttribute('custom-attribute', 'custom-value'); + }, + update() {}, + tick() {}, + remove() {}, + pause() {}, + play() {}, + + multiply(f: number) { + // Reference to system because both were registered with the same name. + return f * this.data.num * this.system!.data.counter; + } + }); \ No newline at end of file diff --git a/tests/baselines/reference/neverReturningFunctions1.js b/tests/baselines/reference/neverReturningFunctions1.js index cce75c6668aed..a99cc51e06dad 100644 --- a/tests/baselines/reference/neverReturningFunctions1.js +++ b/tests/baselines/reference/neverReturningFunctions1.js @@ -153,10 +153,80 @@ function f42(x: number) { } x; // Unreachable } + +// Repro from #33582 + +export interface Component { + attrName?: string; + data: T; + dependencies?: string[]; + el: any; + id: string; + multiple?: boolean; + name: string; + schema: unknown; + system: any; + + init(data?: T): void; + pause(): void; + play(): void; + remove(): void; + tick?(time: number, timeDelta: number): void; + update(oldData: T): void; + updateSchema?(): void; + + extendSchema(update: unknown): void; + flushToDOM(): void; +} + +export interface ComponentConstructor { + new (el: unknown, attrValue: string, id: string): T & Component; + prototype: T & { + name: string; + system: unknown; + play(): void; + pause(): void; + }; +} + +declare function registerComponent( + name: string, + component: ComponentDefinition +): ComponentConstructor; + +export type ComponentDefinition = T & Partial & ThisType; + +const Component = registerComponent('test-component', { + schema: { + myProperty: { + default: [], + parse() { + return [true]; + } + }, + string: { type: 'string' }, + num: 0 + }, + init() { + this.data.num = 0; + this.el.setAttribute('custom-attribute', 'custom-value'); + }, + update() {}, + tick() {}, + remove() {}, + pause() {}, + play() {}, + + multiply(f: number) { + // Reference to system because both were registered with the same name. + return f * this.data.num * this.system!.data.counter; + } +}); //// [neverReturningFunctions1.js] "use strict"; +exports.__esModule = true; function fail(message) { throw new Error(message); } @@ -305,33 +375,61 @@ function f42(x) { } x; // Unreachable } +var Component = registerComponent('test-component', { + schema: { + myProperty: { + "default": [], + parse: function () { + return [true]; + } + }, + string: { type: 'string' }, + num: 0 + }, + init: function () { + this.data.num = 0; + this.el.setAttribute('custom-attribute', 'custom-value'); + }, + update: function () { }, + tick: function () { }, + remove: function () { }, + pause: function () { }, + play: function () { }, + multiply: function (f) { + // Reference to system because both were registered with the same name. + return f * this.data.num * this.system.data.counter; + } +}); //// [neverReturningFunctions1.d.ts] -declare function fail(message?: string): never; -declare function f01(x: string | undefined): void; -declare function f02(x: number): number; -declare function f03(x: string): void; -declare function f11(x: string | undefined, fail: (message?: string) => never): void; -declare function f12(x: number, fail: (message?: string) => never): number; -declare function f13(x: string, fail: (message?: string) => never): void; -declare namespace Debug { - function fail(message?: string): never; +export interface Component { + attrName?: string; + data: T; + dependencies?: string[]; + el: any; + id: string; + multiple?: boolean; + name: string; + schema: unknown; + system: any; + init(data?: T): void; + pause(): void; + play(): void; + remove(): void; + tick?(time: number, timeDelta: number): void; + update(oldData: T): void; + updateSchema?(): void; + extendSchema(update: unknown): void; + flushToDOM(): void; } -declare function f21(x: string | undefined): void; -declare function f22(x: number): number; -declare function f23(x: string): void; -declare function f24(x: string): void; -declare class Test { - fail(message?: string): never; - f1(x: string | undefined): void; - f2(x: number): number; - f3(x: string): void; +export interface ComponentConstructor { + new (el: unknown, attrValue: string, id: string): T & Component; + prototype: T & { + name: string; + system: unknown; + play(): void; + pause(): void; + }; } -declare function f30(x: string | number | undefined): void; -declare function f31(x: { - a: string | number; -}): void; -declare function f40(x: number): void; -declare function f41(x: number): void; -declare function f42(x: number): void; +export declare type ComponentDefinition = T & Partial & ThisType; diff --git a/tests/baselines/reference/neverReturningFunctions1.symbols b/tests/baselines/reference/neverReturningFunctions1.symbols index 7f1b5c489ac14..2ec4c5f93d38a 100644 --- a/tests/baselines/reference/neverReturningFunctions1.symbols +++ b/tests/baselines/reference/neverReturningFunctions1.symbols @@ -385,3 +385,196 @@ function f42(x: number) { >x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13)) } +// Repro from #33582 + +export interface Component { +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) + + attrName?: string; +>attrName : Symbol(Component.attrName, Decl(neverReturningFunctions1.ts, 157, 52)) + + data: T; +>data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) + + dependencies?: string[]; +>dependencies : Symbol(Component.dependencies, Decl(neverReturningFunctions1.ts, 159, 9)) + + el: any; +>el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 160, 25)) + + id: string; +>id : Symbol(Component.id, Decl(neverReturningFunctions1.ts, 161, 9)) + + multiple?: boolean; +>multiple : Symbol(Component.multiple, Decl(neverReturningFunctions1.ts, 162, 12)) + + name: string; +>name : Symbol(Component.name, Decl(neverReturningFunctions1.ts, 163, 20)) + + schema: unknown; +>schema : Symbol(Component.schema, Decl(neverReturningFunctions1.ts, 164, 14)) + + system: any; +>system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 165, 17)) + + init(data?: T): void; +>init : Symbol(Component.init, Decl(neverReturningFunctions1.ts, 166, 13)) +>data : Symbol(data, Decl(neverReturningFunctions1.ts, 168, 6)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) + + pause(): void; +>pause : Symbol(Component.pause, Decl(neverReturningFunctions1.ts, 168, 22)) + + play(): void; +>play : Symbol(Component.play, Decl(neverReturningFunctions1.ts, 169, 15)) + + remove(): void; +>remove : Symbol(Component.remove, Decl(neverReturningFunctions1.ts, 170, 14)) + + tick?(time: number, timeDelta: number): void; +>tick : Symbol(Component.tick, Decl(neverReturningFunctions1.ts, 171, 16)) +>time : Symbol(time, Decl(neverReturningFunctions1.ts, 172, 7)) +>timeDelta : Symbol(timeDelta, Decl(neverReturningFunctions1.ts, 172, 20)) + + update(oldData: T): void; +>update : Symbol(Component.update, Decl(neverReturningFunctions1.ts, 172, 46)) +>oldData : Symbol(oldData, Decl(neverReturningFunctions1.ts, 173, 8)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 157, 27)) + + updateSchema?(): void; +>updateSchema : Symbol(Component.updateSchema, Decl(neverReturningFunctions1.ts, 173, 26)) + + extendSchema(update: unknown): void; +>extendSchema : Symbol(Component.extendSchema, Decl(neverReturningFunctions1.ts, 174, 23)) +>update : Symbol(update, Decl(neverReturningFunctions1.ts, 176, 14)) + + flushToDOM(): void; +>flushToDOM : Symbol(Component.flushToDOM, Decl(neverReturningFunctions1.ts, 176, 37)) +} + +export interface ComponentConstructor { +>ComponentConstructor : Symbol(ComponentConstructor, Decl(neverReturningFunctions1.ts, 178, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 180, 38)) + + new (el: unknown, attrValue: string, id: string): T & Component; +>el : Symbol(el, Decl(neverReturningFunctions1.ts, 181, 6)) +>attrValue : Symbol(attrValue, Decl(neverReturningFunctions1.ts, 181, 18)) +>id : Symbol(id, Decl(neverReturningFunctions1.ts, 181, 37)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 180, 38)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) + + prototype: T & { +>prototype : Symbol(ComponentConstructor.prototype, Decl(neverReturningFunctions1.ts, 181, 65)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 180, 38)) + + name: string; +>name : Symbol(name, Decl(neverReturningFunctions1.ts, 182, 17)) + + system: unknown; +>system : Symbol(system, Decl(neverReturningFunctions1.ts, 183, 15)) + + play(): void; +>play : Symbol(play, Decl(neverReturningFunctions1.ts, 184, 18)) + + pause(): void; +>pause : Symbol(pause, Decl(neverReturningFunctions1.ts, 185, 15)) + + }; +} + +declare function registerComponent( +>registerComponent : Symbol(registerComponent, Decl(neverReturningFunctions1.ts, 188, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 190, 35)) + + name: string, +>name : Symbol(name, Decl(neverReturningFunctions1.ts, 190, 53)) + + component: ComponentDefinition +>component : Symbol(component, Decl(neverReturningFunctions1.ts, 191, 17)) +>ComponentDefinition : Symbol(ComponentDefinition, Decl(neverReturningFunctions1.ts, 193, 27)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 190, 35)) + +): ComponentConstructor; +>ComponentConstructor : Symbol(ComponentConstructor, Decl(neverReturningFunctions1.ts, 178, 1)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 190, 35)) + +export type ComponentDefinition = T & Partial & ThisType; +>ComponentDefinition : Symbol(ComponentDefinition, Decl(neverReturningFunctions1.ts, 193, 27)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 195, 32)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 195, 32)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) +>ThisType : Symbol(ThisType, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(neverReturningFunctions1.ts, 195, 32)) +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1)) + +const Component = registerComponent('test-component', { +>Component : Symbol(Component, Decl(neverReturningFunctions1.ts, 153, 1), Decl(neverReturningFunctions1.ts, 197, 5)) +>registerComponent : Symbol(registerComponent, Decl(neverReturningFunctions1.ts, 188, 1)) + + schema: { +>schema : Symbol(schema, Decl(neverReturningFunctions1.ts, 197, 55)) + + myProperty: { +>myProperty : Symbol(myProperty, Decl(neverReturningFunctions1.ts, 198, 10)) + + default: [], +>default : Symbol(default, Decl(neverReturningFunctions1.ts, 199, 15)) + + parse() { +>parse : Symbol(parse, Decl(neverReturningFunctions1.ts, 200, 15)) + + return [true]; + } + }, + string: { type: 'string' }, +>string : Symbol(string, Decl(neverReturningFunctions1.ts, 204, 4)) +>type : Symbol(type, Decl(neverReturningFunctions1.ts, 205, 11)) + + num: 0 +>num : Symbol(num, Decl(neverReturningFunctions1.ts, 205, 29)) + + }, + init() { +>init : Symbol(init, Decl(neverReturningFunctions1.ts, 207, 3)) + + this.data.num = 0; +>this.data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) +>data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) + + this.el.setAttribute('custom-attribute', 'custom-value'); +>this.el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 160, 25)) +>el : Symbol(Component.el, Decl(neverReturningFunctions1.ts, 160, 25)) + + }, + update() {}, +>update : Symbol(update, Decl(neverReturningFunctions1.ts, 211, 3)) + + tick() {}, +>tick : Symbol(tick, Decl(neverReturningFunctions1.ts, 212, 13)) + + remove() {}, +>remove : Symbol(remove, Decl(neverReturningFunctions1.ts, 213, 11)) + + pause() {}, +>pause : Symbol(pause, Decl(neverReturningFunctions1.ts, 214, 13)) + + play() {}, +>play : Symbol(play, Decl(neverReturningFunctions1.ts, 215, 12)) + + multiply(f: number) { +>multiply : Symbol(multiply, Decl(neverReturningFunctions1.ts, 216, 11)) +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 218, 10)) + + // Reference to system because both were registered with the same name. + return f * this.data.num * this.system!.data.counter; +>f : Symbol(f, Decl(neverReturningFunctions1.ts, 218, 10)) +>this.data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) +>data : Symbol(Component.data, Decl(neverReturningFunctions1.ts, 158, 19)) +>this.system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 165, 17)) +>system : Symbol(Component.system, Decl(neverReturningFunctions1.ts, 165, 17)) + } +}); + diff --git a/tests/baselines/reference/neverReturningFunctions1.types b/tests/baselines/reference/neverReturningFunctions1.types index e7d6afa36a5d9..ed49d1841b878 100644 --- a/tests/baselines/reference/neverReturningFunctions1.types +++ b/tests/baselines/reference/neverReturningFunctions1.types @@ -437,3 +437,205 @@ function f42(x: number) { >x : number } +// Repro from #33582 + +export interface Component { + attrName?: string; +>attrName : string | undefined + + data: T; +>data : T + + dependencies?: string[]; +>dependencies : string[] | undefined + + el: any; +>el : any + + id: string; +>id : string + + multiple?: boolean; +>multiple : boolean | undefined + + name: string; +>name : string + + schema: unknown; +>schema : unknown + + system: any; +>system : any + + init(data?: T): void; +>init : (data?: T | undefined) => void +>data : T | undefined + + pause(): void; +>pause : () => void + + play(): void; +>play : () => void + + remove(): void; +>remove : () => void + + tick?(time: number, timeDelta: number): void; +>tick : ((time: number, timeDelta: number) => void) | undefined +>time : number +>timeDelta : number + + update(oldData: T): void; +>update : (oldData: T) => void +>oldData : T + + updateSchema?(): void; +>updateSchema : (() => void) | undefined + + extendSchema(update: unknown): void; +>extendSchema : (update: unknown) => void +>update : unknown + + flushToDOM(): void; +>flushToDOM : () => void +} + +export interface ComponentConstructor { + new (el: unknown, attrValue: string, id: string): T & Component; +>el : unknown +>attrValue : string +>id : string + + prototype: T & { +>prototype : T & { name: string; system: unknown; play(): void; pause(): void; } + + name: string; +>name : string + + system: unknown; +>system : unknown + + play(): void; +>play : () => void + + pause(): void; +>pause : () => void + + }; +} + +declare function registerComponent( +>registerComponent : (name: string, component: ComponentDefinition) => ComponentConstructor + + name: string, +>name : string + + component: ComponentDefinition +>component : ComponentDefinition + +): ComponentConstructor; + +export type ComponentDefinition = T & Partial & ThisType; +>ComponentDefinition : ComponentDefinition + +const Component = registerComponent('test-component', { +>Component : ComponentConstructor<{ schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; }> +>registerComponent('test-component', { schema: { myProperty: { default: [], parse() { return [true]; } }, string: { type: 'string' }, num: 0 }, init() { this.data.num = 0; this.el.setAttribute('custom-attribute', 'custom-value'); }, update() {}, tick() {}, remove() {}, pause() {}, play() {}, multiply(f: number) { // Reference to system because both were registered with the same name. return f * this.data.num * this.system!.data.counter; }}) : ComponentConstructor<{ schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; }> +>registerComponent : (name: string, component: ComponentDefinition) => ComponentConstructor +>'test-component' : "test-component" +>{ schema: { myProperty: { default: [], parse() { return [true]; } }, string: { type: 'string' }, num: 0 }, init() { this.data.num = 0; this.el.setAttribute('custom-attribute', 'custom-value'); }, update() {}, tick() {}, remove() {}, pause() {}, play() {}, multiply(f: number) { // Reference to system because both were registered with the same name. return f * this.data.num * this.system!.data.counter; }} : { schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; } + + schema: { +>schema : { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; } +>{ myProperty: { default: [], parse() { return [true]; } }, string: { type: 'string' }, num: 0 } : { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; } + + myProperty: { +>myProperty : { default: never[]; parse(): boolean[]; } +>{ default: [], parse() { return [true]; } } : { default: never[]; parse(): boolean[]; } + + default: [], +>default : never[] +>[] : never[] + + parse() { +>parse : () => boolean[] + + return [true]; +>[true] : true[] +>true : true + } + }, + string: { type: 'string' }, +>string : { type: string; } +>{ type: 'string' } : { type: string; } +>type : string +>'string' : "string" + + num: 0 +>num : number +>0 : 0 + + }, + init() { +>init : () => void + + this.data.num = 0; +>this.data.num = 0 : 0 +>this.data.num : any +>this.data : any +>this : { schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; } & Component +>data : any +>num : any +>0 : 0 + + this.el.setAttribute('custom-attribute', 'custom-value'); +>this.el.setAttribute('custom-attribute', 'custom-value') : any +>this.el.setAttribute : any +>this.el : any +>this : { schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; } & Component +>el : any +>setAttribute : any +>'custom-attribute' : "custom-attribute" +>'custom-value' : "custom-value" + + }, + update() {}, +>update : () => void + + tick() {}, +>tick : () => void + + remove() {}, +>remove : () => void + + pause() {}, +>pause : () => void + + play() {}, +>play : () => void + + multiply(f: number) { +>multiply : (f: number) => number +>f : number + + // Reference to system because both were registered with the same name. + return f * this.data.num * this.system!.data.counter; +>f * this.data.num * this.system!.data.counter : number +>f * this.data.num : number +>f : number +>this.data.num : any +>this.data : any +>this : { schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; } & Component +>data : any +>num : any +>this.system!.data.counter : any +>this.system!.data : any +>this.system! : any +>this.system : any +>this : { schema: { myProperty: { default: never[]; parse(): boolean[]; }; string: { type: string; }; num: number; }; init(): void; update(): void; tick(): void; remove(): void; pause(): void; play(): void; multiply(f: number): number; } & Component +>system : any +>data : any +>counter : any + } +}); + diff --git a/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts b/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts index 63e7ecf786f4a..72dd0a13b5ae0 100644 --- a/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts +++ b/tests/cases/conformance/controlFlow/neverReturningFunctions1.ts @@ -156,3 +156,72 @@ function f42(x: number) { } x; // Unreachable } + +// Repro from #33582 + +export interface Component { + attrName?: string; + data: T; + dependencies?: string[]; + el: any; + id: string; + multiple?: boolean; + name: string; + schema: unknown; + system: any; + + init(data?: T): void; + pause(): void; + play(): void; + remove(): void; + tick?(time: number, timeDelta: number): void; + update(oldData: T): void; + updateSchema?(): void; + + extendSchema(update: unknown): void; + flushToDOM(): void; +} + +export interface ComponentConstructor { + new (el: unknown, attrValue: string, id: string): T & Component; + prototype: T & { + name: string; + system: unknown; + play(): void; + pause(): void; + }; +} + +declare function registerComponent( + name: string, + component: ComponentDefinition +): ComponentConstructor; + +export type ComponentDefinition = T & Partial & ThisType; + +const Component = registerComponent('test-component', { + schema: { + myProperty: { + default: [], + parse() { + return [true]; + } + }, + string: { type: 'string' }, + num: 0 + }, + init() { + this.data.num = 0; + this.el.setAttribute('custom-attribute', 'custom-value'); + }, + update() {}, + tick() {}, + remove() {}, + pause() {}, + play() {}, + + multiply(f: number) { + // Reference to system because both were registered with the same name. + return f * this.data.num * this.system!.data.counter; + } +});