Run a loose pre-check before preprocessStaticConfig
This loose pre-check checks the config schema by treating every object as partial. This means that if a property exists, it's guaranteed to be the correct type (e.g. object). However, there's no guarantee that all or any properties exist. This allows preprocessStaticConfig implementations to be much less defensive and thus reduce boilerplate.
This commit is contained in:
parent
279a8fe7ae
commit
ba2873a29a
4 changed files with 124 additions and 1 deletions
|
@ -48,6 +48,69 @@ export function tNullable<T extends t.Type<any, any>>(type: T) {
|
|||
return t.union([type, t.undefined, t.null], `Nullable<${type.name}>`);
|
||||
}
|
||||
|
||||
function typeHasProps(type: any): type is t.TypeC<any> {
|
||||
return type.props != null;
|
||||
}
|
||||
|
||||
function typeIsArray(type: any): type is t.ArrayC<any> {
|
||||
return type._tag === "ArrayType";
|
||||
}
|
||||
|
||||
export type TDeepPartial<T> = T extends t.InterfaceType<any>
|
||||
? TDeepPartialProps<T["props"]>
|
||||
: T extends t.DictionaryType<any, any>
|
||||
? t.DictionaryType<T["domain"], TDeepPartial<T["codomain"]>>
|
||||
: T extends t.UnionType<any[]>
|
||||
? t.UnionType<Array<TDeepPartial<T["types"][number]>>>
|
||||
: T extends t.IntersectionType<any>
|
||||
? t.IntersectionType<Array<TDeepPartial<T["types"][number]>>>
|
||||
: T extends t.ArrayType<any>
|
||||
? t.ArrayType<TDeepPartial<T["type"]>>
|
||||
: T;
|
||||
|
||||
// Based on t.PartialC
|
||||
export interface TDeepPartialProps<P extends t.Props>
|
||||
extends t.PartialType<
|
||||
P,
|
||||
{
|
||||
[K in keyof P]?: TDeepPartial<t.TypeOf<P[K]>>;
|
||||
},
|
||||
{
|
||||
[K in keyof P]?: TDeepPartial<t.OutputOf<P[K]>>;
|
||||
}
|
||||
> {}
|
||||
|
||||
export function tDeepPartial<T>(type: T): TDeepPartial<T> {
|
||||
if (type instanceof t.InterfaceType) {
|
||||
const newProps = {};
|
||||
for (const [key, prop] of Object.entries(type.props)) {
|
||||
newProps[key] = tDeepPartial(prop);
|
||||
}
|
||||
return t.partial(newProps) as TDeepPartial<T>;
|
||||
} else if (type instanceof t.DictionaryType) {
|
||||
return t.record(type.domain, tDeepPartial(type.codomain)) as TDeepPartial<T>;
|
||||
} else if (type instanceof t.UnionType) {
|
||||
return t.union(type.types.map(unionType => tDeepPartial(unionType))) as TDeepPartial<T>;
|
||||
} else if (type instanceof t.IntersectionType) {
|
||||
const types = type.types.map(intersectionType => tDeepPartial(intersectionType));
|
||||
return (t.intersection(types as [t.Mixed, t.Mixed]) as unknown) as TDeepPartial<T>;
|
||||
} else if (type instanceof t.ArrayType) {
|
||||
return t.array(tDeepPartial(type.type)) as TDeepPartial<T>;
|
||||
} else {
|
||||
return type as TDeepPartial<T>;
|
||||
}
|
||||
}
|
||||
|
||||
function tDeepPartialProp(prop: any) {
|
||||
if (typeHasProps(prop)) {
|
||||
return tDeepPartial(prop);
|
||||
} else if (typeIsArray(prop)) {
|
||||
return t.array(tDeepPartialProp(prop.type));
|
||||
} else {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors EmbedOptions from Eris
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue