-
-
Notifications
You must be signed in to change notification settings - Fork 222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider migrating from Type to Interface #257
Comments
I can open a PR to resolve this later this afternoon maybe. Should be a relatively quick fix. |
My comment from issue #258: There is a reason why I did not include To make a long story short. My current recommendation is not to use |
I'll need to investigate this further when I have more time. Will be busy for the rest of today so I can probably get back to this tomorrow. I'm confident that there is a path forward for #259 and the solution I am proposing here. |
Adding import * as v from 'valibot';
type Schema =
| v.BaseSchema
| v.StringSchema
| v.ObjectSchema<v.ObjectEntries>
| v.ArraySchema<v.BaseSchema>;
function schemaToJson(schema: Schema) {
if ('type' in schema) {
switch (schema.type) {
// String
case 'string':
return { type: 'string' };
// Object
case 'object':
return {
type: 'object',
entries: Object.fromEntries(
Object.entries(schema.entries).map(([key, value]) => [
key,
schemaToJson(value),
])
),
};
// Array
case 'array':
return {
type: 'array',
item: schemaToJson(schema.item),
};
}
}
// Error
throw new Error('Not implemented');
} |
Your example highlights a limitation of TypeScript 5.3 added better narrowing support to Since your example has an unrelated typescript error (TS can't infer the return type of the function given as-is), I'll have to follow-up when I have some more time to investigate. Could you provide me with some other examples where this appears problematic to you? I'm not yet seeing where this "adds more problems than it solves". |
I am not sure what exactly you mean with Can you provide me with your full code example from above so that I can investigate it? |
Hey just wanted to give a quick status update: I've been rather busy this week and I haven't spent more than an hour investigating a path forward yet. I'll circle back when I can. |
With the
That is because of the inner types I should probably walk what I was saying about So then, what really marks the difference between type and interface for that code sample? It's actually the In my PR, since I have At present, I don't believe there are any schemas in Valibot that do not have a So that being the case, I don't think having In the PR I created, I added some utilities for type narrowing: export const isOfType = <U extends { type: string }, const T extends string>(
val: U,
type: T
): val is Extract<U, { type: T }> => val?.type === type; Here's how it is used in the context of your example: function schemaToJson<S extends Schema>(schema: S) {
if (isOfType(schema, "string")) {
// schema: StringSchema
return { type: 'string' };
}
if (isOfType(schema, 'object')) {
// schema: ObjectSchema<ObjectEntries>
return {
type: 'object',
entries: Object.fromEntries(
Object.entries(schema.entries).map(([key, value]) => [
key,
schemaToJson(value),
])
),
};
}
if (isOfType(schema, 'array')) {
// schema: ArraySchema<BaseSchema>
return {
type: 'array',
item: schemaToJson(schema.item),
};
}
throw new Error('Not implemented');
} This utility can be used with any object that has a Now I want to throw it back to you again @fabian-hiller, are there other examples you can think of that are problematic? I'll be busy for the next several days FYI. Don't think there's any need to rush this change if you have concerns still. |
Please take a look at this code example. Adding |
Maybe just I only really think the type signature on the function is critical here, as we want Then it's important to note that when using this function, narrowing only works if the type of the provided A usage comment with maybe a minimal example might be a good idea to communicate how this function works to library authors. It really only needs to emphasize the above, that it only narrows when |
Hey, opening this as a follow-up to #211 as I'm noticing some type errors that have come up as a result of changes to the base types that were made at the end of that PR. Here's a small example:
We have a root type most Validation functions extend from, BaseValidation:
And in the codebase these are "extended" via type intersections like so:
But this introduces a problem... because all Validation functions have a
type
and arequirement
, but BaseValidation doesn 't include those! This causes what should be a good way to build a type guard for Validation functions to fail:This is a case where we should be using
interface
instead oftype
, because here we're adhering to a common set of properties that each individual validation function narrows for its specific signature. This also applies to BaseSchema too, which suffers from this same problem.So instead of the above, we should do this instead:
And with that we can validate that all Validations share a common set of properties! (Also, we get a nice side benefit of Typescript running slightly faster too!)
The text was updated successfully, but these errors were encountered: