@@ -23,6 +23,7 @@ export interface Type<T = unknown> {
2323 parse : ( obj : any ) => T
2424 map : ( obj : any , fn : ( this : Type < T > , obj : any , schema : Type < T > ) => any ) => any
2525 props : ( props : TypeProps ) => Type < T >
26+ extend : < O > ( obj : O ) => Type < T & InferObject < O > >
2627}
2728
2829export abstract class TypeClass < T = unknown > implements Type < T > {
@@ -78,6 +79,11 @@ export abstract class TypeClass<T = unknown> implements Type<T> {
7879 this . _props = props
7980 return this
8081 }
82+
83+ extend : < O > ( obj : O ) => Type < T & InferObject < O > > = ( obj : any ) => {
84+ const newObj = { ...this . _object , ...obj }
85+ return object ( newObj ) as any
86+ }
8187}
8288
8389export type Infer < T > = T extends Type < infer TT > ? TT : never
@@ -100,10 +106,12 @@ class TypeStringClass<T extends string> extends TypeClass<T> {
100106 }
101107}
102108
109+ /// Just a simple string type
103110export function string ( ) {
104111 return new TypeStringClass < string > ( 'string' , isString )
105112}
106113
114+ /// Number as in Javascript, could be float or int
107115export function number ( ) {
108116 return generic < number > ( 'number' , {
109117 _check : isNumber ,
@@ -114,12 +122,14 @@ export const float = number
114122export const double = number
115123export const real = number
116124
125+ /// Integer
117126export function int ( ) {
118127 return generic < number > ( 'int' , {
119128 _check : isInteger ,
120129 } )
121130}
122131
132+ /// Boolean
123133export function boolean ( ) {
124134 return generic < boolean > ( 'boolean' , {
125135 _check : isBoolean ,
@@ -134,7 +144,7 @@ export function none() {
134144 } )
135145}
136146
137- // todo: appears to result in optional inside object
147+ /// todo: appears to result in optional inside object
138148export function any ( ) {
139149 return generic < any > ( 'any' , {
140150 _check : v => v != null ,
@@ -198,6 +208,7 @@ export class TypeObjectClass<T, O = InferObject<T>> extends TypeClass<O> {
198208 }
199209}
200210
211+ /// Object that can have any properties
201212export function object < T > ( tobj : T ) : Type < InferObject < T > > {
202213 return new TypeObjectClass ( tobj )
203214}
@@ -215,23 +226,25 @@ export function union<T extends (Type<any>)[]>(options: T): Type<TransformToUnio
215226 } )
216227}
217228
218- // Literal
229+ // Literals
219230
220231type Literal = string | number | bigint | boolean
221232
233+ /// todo: string?
222234export function literal < T extends Literal > ( value : T ) : Type < T > {
223235 return generic < T > ( 'string' , {
224236 _check : v => v === value ,
225237 } )
226238}
227239
240+ /// Sting that can only be one of the values, like: `"a" | "b" | "c"``
228241export function stringLiterals < const T extends readonly string [ ] , O = T [ number ] > ( value : T ) : Type < O > {
229242 return generic < O > ( 'string' , {
230243 _check : v => value . includes ( v ) ,
231244 } )
232245}
233246
234- // Function
247+ // Functions
235248
236249type TupleOutput < T extends Type [ ] > = {
237250 [ K in keyof T ] : T [ K ] extends Type < infer U > ? U : never
@@ -247,6 +260,7 @@ type ArrayType<
247260 Rest extends Type | undefined = Type | undefined ,
248261> = Type < ArrayOutput < Head , Rest > >
249262
263+ // Like an array but with fixed length and types
250264export function tuple < T extends [ ] | [ Type , ...Type [ ] ] > ( items : T ) : ArrayType < T , undefined > {
251265 return generic ( 'tuple' , {
252266 _check : v => items . every ( ( item , i ) => item . _check ( v [ i ] ) ) ,
@@ -289,6 +303,7 @@ class TypeFuncClass<T, Args, Ret> extends TypeClass<T> {
289303 _ret ?: Ret
290304}
291305
306+ /// Regular function
292307export function func <
293308 Args extends [ Type < unknown > , ...Type < any > [ ] ] | [ ] ,
294309 Ret = Type ,
@@ -312,6 +327,7 @@ export class TypeRpcClass<T, Info, Ret> extends TypeClass<T> {
312327 _ret ?: Ret
313328}
314329
330+ /// RPC function that only takes one argument and returns a promise
315331export function rpc <
316332 Info extends Type < unknown > | undefined = undefined ,
317333 Ret extends Type < unknown > = Type < void > , // ReturnType<typeof none>,
@@ -320,9 +336,23 @@ export function rpc<
320336 return new TypeRpcClass < T , Info , Ret > ( 'rpc' , info , ret ?? none ( ) as Ret )
321337}
322338
323- // const fn = func([string(), boolean(), int()], string()) // typeof fn should be: Type<(...args: [string, boolean]) => string>
324-
325- // type typeFn = Infer<typeof fn> // typeFn should be: (...args: [string, boolean]) => string
326-
327- // type f1 = (a: number, b?: string) => boolean
328- // type xx = Parameters<f1>
339+ /// Reduce conflicts with real type names, use like z.string()
340+ export const z = {
341+ string,
342+ number,
343+ int,
344+ boolean,
345+ none,
346+ any,
347+ object,
348+ array,
349+ tuple,
350+ union,
351+ func,
352+ rpc,
353+ literal,
354+ stringLiterals,
355+ float,
356+ double,
357+ real,
358+ }
0 commit comments