diff --git a/source/basic.d.ts b/source/basic.d.ts index fdd78b1ee..d4d8f9839 100644 --- a/source/basic.d.ts +++ b/source/basic.d.ts @@ -3,7 +3,10 @@ Matches a [`class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe @category Class */ -export type Class = Constructor & {prototype: T}; +export type Class = { + prototype: T; + new(...arguments_: Arguments): T; +}; /** Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). @@ -16,8 +19,14 @@ export type Constructor = new(...argumen Matches an [`abstract class`](https://www.typescriptlang.org/docs/handbook/classes.html#abstract-classes). @category Class + +@privateRemarks +We cannot use a `type` here because TypeScript throws: 'abstract' modifier cannot appear on a type member. (1070) */ -export type AbstractClass = AbstractConstructor & {prototype: T}; +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export interface AbstractClass extends AbstractConstructor { + prototype: T; +} /** Matches an [`abstract class`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html#abstract-construct-signatures) constructor. diff --git a/test-d/abstract-class.ts b/test-d/abstract-class.ts index 102e08df1..69252a3f5 100644 --- a/test-d/abstract-class.ts +++ b/test-d/abstract-class.ts @@ -1,7 +1,11 @@ -import {expectError} from 'tsd'; +import {expectError, expectAssignable, expectNotAssignable} from 'tsd'; import type {AbstractConstructor, AbstractClass} from '../index'; abstract class Foo { + constructor(x: number) { + void (x); + } + abstract fooMethod(): void; } @@ -9,7 +13,7 @@ abstract class Bar { abstract barMethod(): void; } -function functionRecevingAbsClass(cls: AbstractClass) { +function functionReceivingAbsClass(cls: AbstractClass) { return cls; } @@ -21,20 +25,37 @@ function withBar>(Ctor: T) { return ExtendedBar; } -function assertWithBar() { - // This lacks `barMethod`. - // @ts-expect-error - class WrongConcreteExtendedBar extends withBar(Bar) {} +// This lacks `barMethod`. +// @ts-expect-error +class WrongConcreteExtendedBar extends withBar(Bar) {} - // This should be alright since `barMethod` is implemented. - class CorrectConcreteExtendedBar extends withBar(Bar) { - // eslint-disable-next-line @typescript-eslint/no-empty-function - barMethod() {} +// This should be alright since `barMethod` is implemented. +class CorrectConcreteExtendedBar extends withBar(Bar) { + constructor(x: number, y: number) { + super(); + void (x); + void (y); } - functionRecevingAbsClass(withBar(Bar)); - functionRecevingAbsClass(CorrectConcreteExtendedBar); + + // eslint-disable-next-line @typescript-eslint/no-empty-function + barMethod() {} } -functionRecevingAbsClass(Foo); -expectError(functionRecevingAbsClass(Foo)); +function assertWithBar() { + functionReceivingAbsClass(withBar(Bar)); + functionReceivingAbsClass(CorrectConcreteExtendedBar); +} + +functionReceivingAbsClass(Foo); +expectError(functionReceivingAbsClass(Foo)); assertWithBar(); + +expectAssignable>(Bar); +expectAssignable>(Bar); + +// Prototype test +expectAssignable<{barMethod(): void}>(Bar.prototype); +expectNotAssignable<{fooMethod(): void}>(Bar.prototype); +expectError(new CorrectConcreteExtendedBar(12)); +expectAssignable<{barMethod(): void}>(new CorrectConcreteExtendedBar(12, 15)); +// /Prototype test diff --git a/test-d/class.ts b/test-d/class.ts index de40cfafb..0326479ed 100644 --- a/test-d/class.ts +++ b/test-d/class.ts @@ -1,5 +1,5 @@ -import {expectError} from 'tsd'; -import type {Constructor} from '../index'; +import {expectAssignable, expectError, expectNotAssignable, expectType} from 'tsd'; +import type {Class, Constructor, IsAny} from '../index'; class Foo { constructor(x: number, y: any) { @@ -21,3 +21,36 @@ function fn2(Cls: Constructor): Foo { fn(Foo); fn2(Foo); + +// Prototype test +type PositionProps = { + top: number; + left: number; +}; + +class Position { + public top: number; + + public left: number; + + constructor(parameterTop: number, parameterLeft: number) { + this.top = parameterTop; + this.left = parameterLeft; + } +} + +declare const Bar: Class; + +expectAssignable>(Position); + +expectNotAssignable>(Position); + +expectAssignable>(Position); +expectAssignable>(Position); + +expectType>(false); +expectType(Position.prototype); +// /Prototype test + +expectError(new Position(17)); +expectAssignable(new Position(17, 34));