-
Notifications
You must be signed in to change notification settings - Fork 163
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
Fix importing optional properties #1096
Fix importing optional properties #1096
Conversation
I think TReadonly works in a similar way so it probably has the same issue. |
@michaelcollabai Hi, thanks for the PR I think Optional and Readonly inference should have been resolved on 0.34.1 (there's actually been a lot of extra work done to the Module implementation to support computed types, Readonly and Optional inference were added as part of the new TComputed implementation). Can you try the install import { Type, Static } from '@sinclair/typebox'
const Module = Type.Module({
// Explicit
A: Type.Object({
x: Type.Optional(Type.Number()),
y: Type.Optional(Type.Number()),
z: Type.Optional(Type.Number()),
}),
// Partial
B: Type.Partial(Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number(),
})),
// Ref Target
T: Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number(),
}),
R: Type.Partial(Type.Ref('T'))
})
type A = Static<typeof A>
type B = Static<typeof B>
type T = Static<typeof T> // expect required
type R = Static<typeof R>
const A = Module.Import('A')
const B = Module.Import('B')
const T = Module.Import('T') // required
const R = Module.Import('R') If you can provide a repro of the Optional types not coming through, will definitely flag that as an issue for fixing. But think things might be all good on the latest version. Keep me posted |
Hey @sinclairzx81 The bug only happens for properties like TArray or TObject. It does indeed work for basic types. This is still true for 0.34.7. import { Type, Static } from '@sinclair/typebox'
const Module = Type.Module({
// Explicit
A: Type.Object({
x: Type.Optional(Type.Number()),
a: Type.Optional(Type.Array(Type.Number())),
o: Type.Optional(Type.Object({ foo: Type.Number() }))
})
})
const A = Module.Import("A");
type A = Static<typeof A>
/*
type A = {
x?: number | undefined;
a: number[];
o: {
foo: number;
};
}*/ The test case "Object 1" in the PR also fails at HEAD without my change. I don't think this is how it should work, is it? Not ruling out that I don't understand the feature, but it seems off to me that the state in type diverges from run time. |
@michaelcollabai Hi! Ah! Yes, this is a totally a bug (thanks for the follow up + repro!). This fix will need to be applied to both Optional and Readonly. You will want to update both // ...
Type extends TOptional<infer Type extends TSchema> ? TOptional<TFromType<ModuleProperties, Type>> :
Type extends TReadonly<infer Type extends TSchema> ? TReadonly<TFromType<ModuleProperties, Type>> : Will need to test for multiple assigned modifiers ( const Module = Type.Module({
T: Type.Object({
// will want to ensure the unwrap works for Readonly and Optional applied modifiers
x: Type.ReadonlyOptional(Type.Array(Type.Literal(1))),
y: Type.Readonly(Type.Array(Type.Literal(1))),
z: Type.Optional(Type.Array(Type.Literal(1))),
w: Type.Array(Type.Literal(1))
})
}) If you can get the Readonly mapping in + this test, this PR should be good to go. |
@michaelcollabai Hi, Have gone ahead and fixed up Readonly on this PR and merged through (this issue was a breaking bug and wanted to get it sorted pretty quickly). Will be publishing the fix out to NPM push within the hour. Thanks again for finding this issue and for the PR to resolve, this was really good catch (and happy to hear the code wasn't to bad to navigate!) Will notify once published |
@michaelcollabai Hiya, Fix published on 0.34.8. Thanks again! All the best |
Module types look like a great idea to simplify some of our recursive schemas.
I tried them out and noticed a problem with optional object properties:
When importing an object schema, the optional status is lost for all properties with the more complex types handled in
TFromType
.This does not happen at run time as
[OptionalKind]
is carried over in the spread op inCreateType
.I added type and run time tests to verify my assumptions.
Hats off for building something so complex with such clean and readable code!