Created
February 16, 2021 19:46
-
-
Save typomaker/af7241e04a609c9ac6a38e062d1eaa36 to your computer and use it in GitHub Desktop.
Strongly typed query condition as in Yii2 (PHP). [typscript 4.1 literal templates]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Path<T> = | |
T extends Array<infer S> ? Path<S> & string : | |
(T extends object ? { | |
[K in keyof T]: T[K] extends Array<any> ? Path.Item<T, K> : K & string | Path.Item<T, K> | |
}[keyof T] : never) | |
export namespace Path { | |
export type Item<T, K extends keyof T> = `${K & string}.${Path<T[K]> & string}` | |
export type Type<T, Q extends Path<T>> = | |
T extends Array<infer S> ? (Q extends Path<S> ? Type<S, Q> : never) : | |
Q extends keyof T ? T[Q] : | |
Q extends `${infer P}.${infer REST}` ? | |
P extends keyof T ? (REST extends Path<T[P]> ? Type<T[P], REST> : never) | |
: never | |
: never; | |
} | |
export type Expression<T> = Expression.Comparison<T> | Expression.Logical<T> | |
export namespace Expression { | |
export type Comparison<T> = { | |
[K in Path<T>]: [("<=" | ">=" | "!=") | ("=" | ">" | "<"), K, Path.Type<T, K>] | ["in" | "!in", K, Path.Type<T, K>[]] | |
}[Path<T>] | |
export type Logical<T> = Comparison<T> | [("&&" | "||"), ...Expression<T>[]] | |
} | |
type Entity = { id: number, items: [{ name: string }] }; | |
const validPath: Path<Entity> = "items.name" | |
const typeOfPath: Path.Type<Entity, "id"> = 123 | |
const expression: Expression<Entity> = ["||", ["<=", "items.name", "123"], ["&&", ["<", "items.name", ""], ["!in", "id", [1, 2, 2]]]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Try here TS Playground!