Skip to content

Instantly share code, notes, and snippets.

@hediet
Created March 11, 2019 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hediet/1daa00a21ef69dd8cabb86c6e6558223 to your computer and use it in GitHub Desktop.
Save hediet/1daa00a21ef69dd8cabb86c6e6558223 to your computer and use it in GitHub Desktop.
type SchemaType = PrimitiveSchema | ObjectSchema | ParametrizedObjectSchema;
interface PrimitiveSchema<T = any> {
kind: "primitive";
type: T;
}
interface Fields {
[name: string]: SchemaType;
}
interface ObjectSchema<TFields extends Fields = Fields> {
kind: "object";
fields: TFields;
}
interface ParametrizedObjectSchema<
TParams = object,
TFields extends Fields = Fields
> {
kind: "parametrized-object";
params: TParams;
fields: TFields;
}
type AsSchema<T extends SchemaType> = T;
type QueryIn<
TSchema extends { [key: string]: any }
> = TSchema extends ObjectSchema ? { [TName in keyof TSchema["fields"]]?: QueryIn<TSchema["fields"][TName]> }
: TSchema extends PrimitiveSchema ? true
: TSchema extends ParametrizedObjectSchema ? {
params: {
[TName in keyof TSchema["params"]]:
TSchema["params"][TName]
};
fields: {
[TName in keyof TSchema["fields"]]?: QueryIn<
TSchema["fields"][TName]
>
};
}
: never;
type QueryResult<
TSchema extends { [key: string]: any },
T extends { [key: string]: any }
> = TSchema extends ObjectSchema
? Pick<
{
[TName in keyof TSchema["fields"] & keyof T]: QueryResult<
TSchema["fields"][TName],
T[TName]
>
},
keyof T & keyof TSchema["fields"]
>
: TSchema extends PrimitiveSchema
? TSchema["type"]
: TSchema extends ParametrizedObjectSchema
? Pick<
{
[TName in keyof TSchema["fields"] &
keyof T["fields"]]: QueryResult<
TSchema["fields"][TName],
T["fields"][TName]
>
},
keyof T["fields"] & keyof TSchema["fields"]
>
: never;
class QueryBuilder<TSchema extends QuerySchema> {
public query<T extends QueryIn<TSchema>>(
type: T
): QueryResult<QuerySchema, T> {
throw "";
}
}
// generated
type QuerySchema = AsSchema<{
kind: "object";
fields: {
licenseByName: {
kind: "parametrized-object";
params: {
name: string;
};
fields: {
description: PrimitiveSchema<string>;
};
};
author: {
kind: "object";
fields: {
name: PrimitiveSchema<string>;
email: PrimitiveSchema<string>;
};
};
};
}>;
const schema: QueryBuilder<QuerySchema> = null!;
const r = schema.query({
licenseByName: {
params: {
name: "test"
},
fields: { description: true }
},
author: { email: true, name: true }
});
//r.licenseByName.description;
//r.author.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment