Skip to content

Instantly share code, notes, and snippets.

@mattiamanzati
Created August 30, 2017 15:03
Show Gist options
  • Save mattiamanzati/7644674c0e94ad32c2cc71bf9887ad37 to your computer and use it in GitHub Desktop.
Save mattiamanzati/7644674c0e94ad32c2cc71bf9887ad37 to your computer and use it in GitHub Desktop.
type StringContains<S extends string, L extends string> = ({ [K in S]: "true" } & {
[key: string]: "false"
})[L]
interface IJSONSchemaNumber {
type: "number"
}
interface IJSONSchemaInteger {
type: "integer"
}
interface IJSONSchemaNull {
type: "null"
}
interface IJSONSchemaString {
type: "string"
}
interface IJSONSchemaBoolean {
type: "boolean"
}
interface IJSONSchemaArray {
type: "array"
items: IJSONSchemaType
}
interface IJSONSchemaObject {
type: "object"
properties: { [K: string]: IJSONSchemaType }
}
interface IJSONSchemaUnion {
anyOf: IJSONSchemaType[]
}
type IJSONSchemaPrimitive =
| IJSONSchemaInteger
| IJSONSchemaNull
| IJSONSchemaNumber
| IJSONSchemaString
| IJSONSchemaBoolean
type IJSONSchemaType =
| IJSONSchemaPrimitive
| IJSONSchemaObject
| IJSONSchemaArray
| IJSONSchemaUnion
type ObjectType<T extends IJSONSchemaObject> = {
[K in keyof T["properties"]]: InterfaceFromSchema<T["properties"][K]>
}
type PrimitiveFromSchema<T extends IJSONSchemaPrimitive> = {
number: number
integer: number
null: null
string: string
boolean: boolean
array: InterfaceFromSchema<T["items"]>[]
object: ObjectType<T>
}[T["type"]]
type InterfaceFromSchema<T extends IJSONSchemaType> = {
true: 42
false: PrimitiveFromSchema<T>
}[StringContains<keyof T, "anyOf">]
declare function compile<T extends IJSONSchemaType>(schema: T): InterfaceFromSchema<T>
const number = compile({ type: "number" })
const integer = compile({ type: "integer" })
const nulls = compile({ type: "null" })
const string = compile({ type: "string" })
const boolean = compile({ type: "boolean" })
const object = compile({ type: "object", properties: { amount: { type: "boolean" } } })
const array = compile({ type: "array", items: { type: "boolean" } })
const arrayOfObject = compile({
type: "array",
items: { type: "object", properties: { amount: { type: "boolean" } } }
})
const objectWithArray = compile({
type: "object",
properties: { amount: { type: "array", items: { type: "boolean" } } }
})
const complex = compile({
type: "object",
properties: {
_id: { type: "string" },
document_id: { type: "integer" },
article_id: { type: "integer" },
qty: { type: "number" },
price: { type: "number" },
value: { type: "number" },
rows: {
type: "array",
items: {
type: "object",
properties: {
_id: { type: "string" },
document_id: { type: "integer" },
article_id: { type: "integer" },
qty: { type: "number" },
price: { type: "number" },
value: { type: "number" }
}
}
}
}
})
// qui va sempre in false
const a = compile({
anyOf: [{ type: "number" }, { type: "boolean" }]
})
// anche se qui è true :/
const b: StringContains<
keyof {
anyOf: [{ type: "number" }, { type: "boolean" }]
},
"anyOf"
>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment