TypeScript complaining about passing a type from a custom scope to custom helper function

I've got a bit of a wrapper around Arktype that i work with, honestly a very simple function
export function validateObject<T extends Type<any>>(
obj: unknown,
validator: T,
): T extends Type<infer R> ? R : never {
const data = validator(obj);

if (data instanceof type.errors) throw data;

return data;
}
export function validateObject<T extends Type<any>>(
obj: unknown,
validator: T,
): T extends Type<infer R> ? R : never {
const data = validator(obj);

if (data instanceof type.errors) throw data;

return data;
}
Recently in a project I tried to use it with a custom scope and found that while it did run just fine, TypeScript is really mad about the types not matching for the validator object something like this
const myScope = scope({
customId: 'string & /[A-HJKMNP-TV-Z]{26}/',
});

const typeWithCustomId = myScope.type({
id: 'customId',
});

const data = validateObject(
{ id: 'A'.repeat(26) },
typeWithCustomId,
);
const myScope = scope({
customId: 'string & /[A-HJKMNP-TV-Z]{26}/',
});

const typeWithCustomId = myScope.type({
id: 'customId',
});

const data = validateObject(
{ id: 'A'.repeat(26) },
typeWithCustomId,
);
The picture is the error, which happens over typesWithCustomId How can I type this helper function so that TypeScript isn't upset at it's usage?
No description
1 Reply
TizzySaurus
TizzySaurus2d ago
Iirc you just need to change Type<any> to Type<any, any>. I believe there's also type.Any as a shorthand. And the canonical return type would be T["infer"] rather than using a conditional type (the conditional type is unnecessary because of the extends in the generic declaration) And the canonical function body would be just return validator.assert(obj), which will automatically throw an error when the validation fails (so you don't need the instanceof type.errors) I.e. something like this should work:
export const validateObject = <T extends type.Any>(obj: unknown, validator: T): T["infer"] => validator.assert(obj)
export const validateObject = <T extends type.Any>(obj: unknown, validator: T): T["infer"] => validator.assert(obj)
You may not even need the explicit return type

Did you find this page helpful?