valibot
valibot copied to clipboard
Support classes with private constructors in v.instance
Use case
Encapsulating a class constructor and exposing a static factory method for instantiation
import * as v from 'valibot';
class Some {
private constructor(readonly value: number) {
}
static fromValue(value: number) {
return new Some(value);
}
}
// TS2345: Argument of type typeof Some is not assignable to parameter of type Class
// Cannot assign a private constructor type to a public constructor type.
const SomeSchema = v.instance(Some);
Issue
The error occurs because Valibot's Class type expects a class with a public constructor, but Some has a private constructor, making it incompatible.
Potential solution
To resolve this, Valibot's Class type can be redefined to be more flexible, allowing classes with private constructors to work with v.instance.
// Current
export type Class = new (...args: any[]) => any;
// Improved
export type Class<T> = {
new (...args: any[]): T;
};
the proposed solution does not solve the issue, the typescript error is still raised.
related: https://github.com/colinhacks/zod/issues/1065
I don't think there's a way to both check that a value is constructable while allowing private classes, unfortunately. NewableFunction allows assignment from private constructors, but it's then impossible to retrieve InstanceType<TClass>
As with the linked issue, you'd likely have to rely on v.custom<Some>((arg) => arg instanceof Some).
Unfortunately, the TypeScript type NewableFunction is not compatible with InstanceType. The only thing we could consider is adding // @ts-expect-error if there is no downside. I also recommend using custom in the meantime.
Hi, @eonicum. I'm Dosu, and I'm helping the Valibot team manage their backlog. I'm marking this issue as stale.
Issue Summary:
- The issue involves Valibot's
v.instancefunction not supporting classes with private constructors. - The current
Classtype definition is causing a TypeScript error. - @EskiMojo14 and @fabian-hiller have acknowledged the problem and discussed potential workarounds.
- Suggested workarounds include using
v.custom<Some>((arg) => arg instanceof Some)or// @ts-expect-error.
Next Steps:
- Please confirm if this issue is still relevant to the latest version of the Valibot repository by commenting on this issue.
- If no further activity occurs, this issue will be automatically closed in 30 days.
Thank you for your understanding and contribution!