Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a derived type from class, but omit the constructor (typescript)

I have an interface and class defined like this:

interface Foo {
  constructor: typeof Foo;
}

class Foo {
  static bar = 'bar';

  constructor(data: Partial<Foo>) {
    Object.assign(this, data);
  }

  someMethod() {
    return this.constructor.bar;
  }

  prop1: string;
  prop2: number;
}

The interface is necessary so that this.constructor is strongly typed. However, it breaks my ability to pass a plain object into the class constructor:

const foo = new Foo({ prop1: 'asdf', prop2: 1234 });

// Argument of type '{ prop1: string; prop2: number; }' is not assignable to parameter of type 'Partial<Foo>'.
//  Types of property 'constructor' are incompatible.
//    Type 'Function' is not assignable to type 'typeof Foo'.
//      Type 'Function' provides no match for the signature 'new (data: Partial<Foo>): Foo'.

I understand the error message, but I don't know a way around it. Is there any way have a Partial<Foo> which allows me to pass a plain object? Here's a playground:

Playground

like image 647
Ryan Wheale Avatar asked Sep 18 '25 04:09

Ryan Wheale


1 Answers

Here's the actual type creating a derived type from a class omitting the constructor (as in the question title) and keeping regular methods:

type NonConstructorKeys<T> = ({[P in keyof T]: T[P] extends new () => any ? never : P })[keyof T];
type NonConstructor<T> = Pick<T, NonConstructorKeys<T>>;

Usage with the Foo from the question:

type FooNonConstructorKeys = NonConstructorKeys<Foo>; // "prop1" | "prop2" | "someMethod"
type FooNonConstructor = NonConstructor<Foo>;
like image 174
Terite Avatar answered Sep 20 '25 19:09

Terite