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:
I ended up finding what I needed in this wonderful answer:
how to remove properties via mapped type in TypeScript
The code in that answer creates a derived type containing only methods. I needed to do the inverse of that. The following NonMethods<T>
helper creates a derived type with all of the methods removed.
type NonMethodKeys<T> = ({[P in keyof T]: T[P] extends Function ? never : P })[keyof T];
type NonMethods<T> = Pick<T, NonMethodKeys<T>>;