Ty
Write schema to bring TypeScript's types to runtime.
Which can be used to:
- Validate untyped data and return well typed result.
- Generate random data of a given schema, to do property-based testing.
- We also provide a library of logic theories, to be used as target of models.
Install
npm i @xieyuheng/ty
Examples
Validation untyped data
import ty, { Obtain } from "@xieyuheng/ty"
const userSchema = ty.object({
id: ty.int({ min: 0 }),
first_name: ty.string(),
last_name: ty.string(),
})
type User = Obtain<typeof userSchema>
// NOTE We can extract a `User` type from the type of `userSchema`,
// which will be the same as the following type definition:
// type User = {
// id: number
// first_name: string
// last_name: string
// }
{
const data: any = {
id: 1,
first_name: "Yuheng",
last_name: "Xie",
}
const user: User = userSchema.validate(data)
const userOmitId: Omit<User, "id"> = ty.omit(userSchema, "id").validate(data)
}
Generate random data of a given schema
{
const user: User = userSchema.generate()
userSchema.validate(user)
console.log(user)
// Will print something like:
// { id: 0, first_name: 'ada4a39ab0', last_name: '73be' }
}
Recursive and generic schema
type List<T> = null | { head: T; tail: List<T> }
function cons<T>(head: T, tail: List<T>): List<T> {
return { head, tail }
}
function listSchema<T>(itemSchema: Schema<T>): Schema<List<T>> {
const nullSchema = ty.null()
const consSchema = ty.object({
head: itemSchema,
tail: ty.lazy(() => listSchema(itemSchema)),
})
return ty.union(nullSchema, consSchema)
}
{
const schema = listSchema(ty.string())
const data0: List<string> = schema.validate(null)
const data1: List<string> = schema.validate(cons("a", null))
const data2: List<string> = schema.validate(cons("a", cons("b", null)))
const data3: List<string> = schema.validate(
cons("a", cons("b", cons("c", null)))
)
schema.assertInvalid(cons(1, null))
schema.assertInvalid(cons(1, cons(2, null)))
schema.assertInvalid(cons(1, cons(2, cons(3, null))))
}
{
const schema = listSchema(ty.number())
const data0: List<number> = schema.validate(null)
const data1: List<number> = schema.validate(cons(1, null))
const data2: List<number> = schema.validate(cons(1, cons(2, null)))
const data3: List<number> = schema.validate(cons(1, cons(2, cons(3, null))))
schema.assertInvalid(cons("a", null))
schema.assertInvalid(cons("a", cons("b", null)))
schema.assertInvalid(cons("a", cons("b", cons("c", null))))
}
Property-based testing
TODO
Logic theories (interface and typeclass of laws)
To be used as target of models, for property-based testing.
TODO
API Docs
Primitive:
- ty.string()
- ty.format(foramtName)
- ty.number()
- ty.int()
- ty.boolean()
- ty.null()
- ty.undefined()
- ty.any()
Collection:
Set-Theoretic:
Structural:
- ty.omit(schema, key)
- ty.omitMany(schema, keys)
- ty.pick(schema, key)
- ty.pickMany(schema, keys)
- ty.optional(schema)
Recursion:
Similar projects
Runtime typing:
Property-based testing and data generation:
Contributions
Be polite, do not bring negative emotion to others.
- TODO.md
- STYLE-GUIDE.md
- CODE-OF-CONDUCT.md
- When contributing, add yourself to AUTHORS