Repository: TypeScript
Issue: Suggestion: Improve type of `constructor` on the instance type of a class
Labels: Suggestion,In Discussion

## Search Terms
constructor type

## Suggestion

This was previously discussed in this thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/36660#discussion_r304173536

> I could see a possible future mechanism for `this.constructor` that returned the static side of the containing class without call or construct signatures (but retaining the apparent type of `Function`). 

Currently, the type of the `constructor` property on most objects is `Function`. It has been suggested that for any `class C {}`, the type of the `constructor` property on the instance should be `typeof C`. However this suffers a significant drawback in that it severely limits subclasses as any subclass of `C` must have the same (or compatible) construct signatures as `C`.

Here is an example of this issue: https://www.typescriptlang.org/play/index.html#code/MYGwhgzhAEDKCuAHApgJwMLitA3gKGmjAC5oIAXVASwDsBzAbgOmAHsaLV5hzXUAKEmUq06ASlzNC5ABZUIAOjDQAvESaEAvnm15QkGAgBGmA9GQAPcshoATQ0jSns+QkdKdRGlu07deAqyI5BCkOEQeIvQANNDuwtT00JoSroRkjoHBimBi3tJyikaq0EEhCkbe2rq01qgAZmDAyHCZzjBphGwclP58pOQAniis9a0oGFgQTDU0dY3NrSZTkuk+PVw8-dBDI2PG7TNAA

Instead, I would suggest a mechanism to type `constructor` as all of the static members of `typeof C` but none of the call/construct signatures of `typeof C`, yet still having an apparent type of `Function`.

## Use Cases

In @ljharb's `qs`, he'd like to be able to use the `constructor` property of a `Buffer`-like object to access the `isBuffer` method on the constructor in a type-safe way (i.e. `obj.constructor.isBuffer`).

## Examples

```ts
/// <reference types="node" />
function isBuffer(obj: { constructor: { isBuffer(obj: any): obj is Buffer; } }) {
  return obj.constructor.isBuffer(obj);
}
const buf = Buffer.alloc(10);
isBuffer(buf); // Buffer class would have a constructor that is `Buffer`
```

## Workaround

There exists a possible workaround for this currently, though it is somewhat complicated:

```ts
type StaticMembers<TClass extends Function> = Pick<TClass, keyof TClass> & Function;

class Buffer extends Uint8Array {
  ...
  static isBuffer(obj: any): obj is Buffer;
  ...
}

interface Buffer {
  readonly constructor: StaticMembers<typeof Buffer>;
}
```

Playground link: https://www.typescriptlang.org/play/index.html#code/MYGwhgzhAEDKCuAHApgJwMLitA3gKGmjAC5oIAXVASwDsBzAbgOmAHsaLV5hzXUAKEmUq06ASlzNC5ABZUIAOjDQAvESaEAvnm15QkGAgBGmA9GQAPcshoATQ0jSns+QkdKdRGlu07deAqyI5BCkOEQeIvQANNDuwtT00JoSroRkjoHBimBi3tJyikaq0EEhCkbe2rrkAJ4ocORg5FTAALLIALZGaBAAPAAqzjCW1nYwAGLwNDxU7AB8JQAKrQDWg8Oxq8i1rABm0ENYEIsAZNBTMy3sTHi01qh7YMDIcJnDkuk+HJT+fKSwJotdpdHqofp1FD7N4oDDHeZMXT3NBPF5vEzHT7pNg-Lg8f6NZqtDrdXp9SHIaHGYYInRAA

## Checklist

My suggestion meets these guidelines:

* [ ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  - Whether this is a breaking change needs to be tested.
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).