Skip to content

Commit 329cf49

Browse files
committed
chore: 🤖 try to implement self references
1 parent a56d939 commit 329cf49

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

src/type/TypeBuilder.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as schema from '../schema';
22
import * as classes from './classes';
3-
import type {Type, TypeOfAlias} from './types';
3+
import type {TypeRef, TypeRefToType, Type, TypeOfAlias} from './types';
44

55
const {s} = schema;
66

@@ -76,7 +76,7 @@ export class TypeBuilder {
7676

7777
// --------------------------------------------------------------- shorthands
7878

79-
public readonly or = <F extends Type[]>(...types: F) => this.Or(...types);
79+
public readonly or = <F extends TypeRef<any>[]>(...types: F) => this.Or(...types);
8080
public readonly undefined = () => this.undef;
8181
public readonly null = () => this.nil;
8282
public readonly boolean = () => this.bool;
@@ -94,7 +94,11 @@ export class TypeBuilder {
9494
options,
9595
);
9696

97-
public readonly tuple = <F extends Type[]>(...types: F) => this.Tuple(types);
97+
public readonly tuple = <F extends TypeRef<any>[]>(...types: F) => this.Tuple(types);
98+
99+
protected typeRefToType = <T extends Type>(type: TypeRef<T>): TypeRefToType<T> => {
100+
return typeof type === 'function' ? (type() as TypeRefToType<T>) : (type as TypeRefToType<T>);
101+
};
98102

99103
/**
100104
* Creates an object type with the specified properties. This is a shorthand for
@@ -117,10 +121,10 @@ export class TypeBuilder {
117121
* @param record A mapping of property names to types.
118122
* @returns An object type.
119123
*/
120-
public readonly object = <R extends Record<string, Type>>(record: R): classes.ObjType<RecordToFields<R>> => {
124+
public readonly object = <R extends Record<string, TypeRef<any>>>(record: R): classes.ObjType<RecordToFields<{[K in keyof R]: TypeRefToType<R[K]>}>> => {
121125
const keys: classes.KeyType<any, any>[] = [];
122-
for (const [key, value] of Object.entries(record)) keys.push(this.Key(key, value));
123-
return new classes.ObjType<RecordToFields<R>>(keys as any).sys(this.system);
126+
for (const [key, value] of Object.entries(record)) keys.push(this.Key(key, this.typeRefToType(value)));
127+
return new classes.ObjType<RecordToFields<{[K in keyof R]: TypeRefToType<R[K]>}>>(keys as any).sys(this.system);
124128
};
125129

126130
/**
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {ModuleType} from '../classes/ModuleType';
2+
import {ResolveType} from '../types';
3+
4+
test('...', () => {
5+
const mod = new ModuleType();
6+
const t = mod.t;
7+
8+
const Str = t.str;
9+
const Obj = t.object({
10+
x: () => Str,
11+
});
12+
13+
type asdf = ResolveType<typeof Obj>;
14+
t.Array(Str);
15+
16+
const Node = t.object({
17+
value: t.any,
18+
key: t.str,
19+
left: () => Node,
20+
right: () => Node,
21+
});
22+
23+
24+
});

src/type/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export type Type =
2424
| classes.FnType<any, any, any>
2525
| classes.FnRxType<any, any, any>;
2626

27+
export type TypeRef<T extends Type> = T | (() => AliasType<any, T>)
28+
export type TypeRefToType<T extends TypeRef<Type>> = T extends () => infer U ? U : T;
29+
2730
export type SchemaOf<T extends Type | Type[]> = T extends BaseType<infer U> ? U : never;
2831
export type SchemaOfMap<M extends Record<string, Type>> = {
2932
[K in keyof M]: SchemaOf<M[K]>;

0 commit comments

Comments
 (0)