-
Notifications
You must be signed in to change notification settings - Fork 327
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
1.0.0 #112
1.0.0 #112
Conversation
1614eac
to
d61e873
Compare
For reference, an actual use case for this feature is I would like to add a static constraint on the |
@gcanti I had similar needs after the upgrade (and found 3 places where some bugs could have bitten us). |
b6809d0
to
cce9233
Compare
963d4a3
to
46232c4
Compare
46232c4
to
297e5e8
Compare
@gcanti I miss the ability to define the Output type with t.Type<A, Output, I> // <- that `Output` type I would like to be able to write: t.Tagged<'type', MyInnerType, MyOutputType> The reason is that I have some |
@sledorze the "input" type comes last // O = output type (encode to)
// I = input type (decode from)
export class Type<A, O = A, I = mixed> implements Decoder<I, A>, Encoder<A, O> {
...
} so not sure I understand the issue, have you got a self contained example I can try? |
@gcanti I messed with the naming, it's really the 'Output' type. |
@sledorze so you want to be able to define the export type Tagged<Tag extends string, A = any> to export type Tagged<Tag extends string, A = any, O = A> |
@gcanti here's the repro: let x: t.Type<string, t.mixed, t.mixed> = <any>1
interface Bar {
type: 'foo'
x: string
}
const Bar: t.Tagged<'type', Bar> = t.interface({
type: t.literal('foo'),
x
}) The compiler complains:
I think it's self explanatory :) If you change x definition to: let x: t.Type<string, t.mixed, t.mixed> = <any>1 Then everything types check as expected. Yes, your proposal would suit my needs (I'm not in need to specify the |
Ok thanks. So this should do the trick (?) export type TaggedProps<Tag extends string> = { [K in Tag]: LiteralType<any> }
export interface TaggedRefinement<Tag extends string, A, O = A> extends RefinementType<Tagged<Tag>, A, O> {}
export interface TaggedUnion<Tag extends string, A, O = A> extends UnionType<Array<Tagged<Tag>>, A, O> {}
export type TaggedIntersectionArgument<Tag extends string> =
| [Tagged<Tag>]
| [Tagged<Tag>, Mixed]
| [Mixed, Tagged<Tag>]
| [Tagged<Tag>, Mixed, Mixed]
| [Mixed, Tagged<Tag>, Mixed]
| [Mixed, Mixed, Tagged<Tag>]
| [Tagged<Tag>, Mixed, Mixed, Mixed]
| [Mixed, Tagged<Tag>, Mixed, Mixed]
| [Mixed, Mixed, Tagged<Tag>, Mixed]
| [Mixed, Mixed, Mixed, Tagged<Tag>]
| [Tagged<Tag>, Mixed, Mixed, Mixed, Mixed]
| [Mixed, Tagged<Tag>, Mixed, Mixed, Mixed]
| [Mixed, Mixed, Tagged<Tag>, Mixed, Mixed]
| [Mixed, Mixed, Mixed, Tagged<Tag>, Mixed]
| [Mixed, Mixed, Mixed, Mixed, Tagged<Tag>]
export interface TaggedIntersection<Tag extends string, A, O = A>
extends IntersectionType<TaggedIntersectionArgument<Tag>, A, O> {}
export type Tagged<Tag extends string, A = any, O = A> = // <= added O here
| InterfaceType<TaggedProps<Tag>, A, O>
| StrictType<TaggedProps<Tag>, A, O>
| TaggedRefinement<Tag, A, O>
| TaggedUnion<Tag, A, O>
| TaggedIntersection<Tag, A, O> Could you please try it out overriding your local definition file? If it's ok I'll push a commit accordingly |
@gcanti Yes that's exactly what was needed. |
Side note: the default signature are nice as they're conservative regarding the type and preserve more information. WondefulAliasName<Tag, A> = Tagged<Tag, A, t.mixed> |
// why mixed in output position here?
let x: t.Type<string, t.mixed, t.mixed> = <any>1 For example in case of declare const DateFromISOString: t.Type<Date, string, mixed>
declare const DateFromMillis: t.Type<Date, number, mixed> which are way better than |
@gcanti you are right, but the issue is that it introduces two types to build and maintain (think those dates can be deeply nested into structures) |
@gcanti it's a side note; it is really not required to be in the lib. |
Right, but only if you cast manually (like you do with On another point, one thing that currently concerns me is the readability of the derived types and compiler erros. Just pushed a commit that should improve the current situation: Example: From
to
|
@gcanti actually we cast types to interfaces in order to keep error messages lean AND work with meaningful types following our business requierements. |
@gcanti all code base migrated. |
Awesome, thanks a lot for your help. For what concerns the issue above, I'm interested in finding a solution, however I can't do much more right now. I propose to postpone the discussion after the release, I'll open an issue after some thoughts. |
@gcanti that's great! |
@sledorze done! |
@gcanti Awesome! Thanks a lot!!!!!!! |
This is a sneak view of a possible improvement on the serialization side.
Currently when we serialize a value of type
A
via a runtime typeType<S, A>
we get a value of typeS
which can be pretty loose.For example if I serialize a string via
t.string
I getmixed
though I know is actually a string. This PR adds a third type parameter toType
where
A
(old) is the type represented by the runtime typeI
(old) is the input typeO
(new) is the output typeThis change will allow to preserve informations about serialized values
Also it will allow for fine grained (static) constraints
/cc @sledorze @giogonzo