I've come across an issue with the InstanceType
Utility Type. I am trying to create a function that takes a class constructor and an instance of that class.
For instance:
export type Class<T=any> = { new(...args: any[]): T; };
function acceptClassAndInstance<T extends Class>(model: T, instance: InstanceType<T>) {
}
The problem is that the function accepts any object as long as it has the properties defined in the type, but it also allows objects with additional properties not specified in the type. Here's an example scenario:
export type Class<T=any> = { new(...args: any[]): T; };
class AModel {
foo: string;
constructor(params: Partial<Pick<AModel, keyof AModel>>) {
Object.assign(this, params)
}
}
class BModel {
foo: string;
bar: string;
constructor(params: Partial<Pick<BModel, keyof BModel>>) {
Object.assign(this, params)
}
}
function acceptClassAndInstance<T extends Class>(model: T, instance: InstanceType<T>) {
}
/* This should be correct */
const instance = new AModel({ foo: "bar" })
acceptClassAndInstance(AModel, instance)
/* This should fail, but doesn't */
const instance2 = new BModel({ foo: "bar", bar: "baz"})
acceptClassAndInstance(AModel, instance2)
/* And this should fail too, but it doesn't */
const notAnInstance = { "foo": "bizz", "bar": "barrrrr", "anotherProperty": "should fail" }
acceptClassAndInstance(AModel, notAnInstance)
/* This fails as expected */
const notAnInstance2 = { "bar": "barrrrr", "anotherProperty": "should fail" }
acceptClassAndInstance(AModel, notAnInstance2)
Why is this happening? Is it a bug in TypeScript? Is there anything else I can do to achieve the desired outcome?
https://stackblitz.com/edit/vitejs-vite-bkqfyq?file=src%2Fmain.ts,tsconfig.json&terminal=dev