Skip to content

Latest commit

History

155 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

isly

Library for type checking.

Usage:

typeDemoType={anyNumber: numbernumberOf: numbertemperature: numbermessage: stringemail: stringcurrency: "SEK"|"EUR"new: booleanfromServer: truemyTuple: [string,number]myUnion: string|numbermyArray: string[]myIntersection: {a: string}&{b: string}children?: DemoType[]regExp: RegExptestMethod?: ()=>boolean}consttype: isly.Type<DemoType>=isly.object({// numberanyNumber: isly.number(),numberOf: isly.number("positive"),temperature: isly.number(value=>value>-273.15),// stringmessage: isly.string(),email: isly.string(/\S+@\S+\.\S+/),currency: isly.string(["SEK","EUR"]),// booleannew: isly.boolean(),fromServer: isly.boolean(true),myTuple: isly.tuple(isly.string(),isly.number()),myUnion: isly.union(isly.string(),isly.number()),myArray: isly.array(isly.string(),{criteria: "minLength",value: 1}),myIntersection: isly.intersection(isly.object<{a: string}>({a: isly.string()}),isly.object<{b: string}>({b: isly.string()})),// Recursive, optional:children: isly.array(isly.lazy(()=>type,"DemoType")).optional(),// Instanceof-test is made with a custom is-function.regExp: isly.fromIs<RegExp>("RegExp",value=>valueinstanceofRegExp),// function:// This only validate if it is a function,// not the signature of it.// JSON do not support this type but exists for// completeness.testMethod: isly.function<DemoType["testMethod"]>().optional(),})constdata: DemoType|any=api.getMyExternalData()if(!type.is(data)){consterror=type.flaw(data)}else{// `data` is for sure DemoType, use it!}

type.get(value: any)

Returns the value only if it fits the type, otherwise undefined. Make it easy to use with the Nullish coalescing operator (??).

For object, a filtered object is returned, with only known properties.

constmyNumber=234/0// Infinityconsole.log(isly.number().get(myNumber)??"(No number)")// Outputs (No number)console.log(isly.number().get(0)??"(No number)")// Outputs 0
interfaceUser{name: string}interfaceUserWithCredentialsextendsUser{password: string}constuserType=isly.object<User>({name: isly.string()})constuserWithCredentialsType=userType.extend<UserWithCredentials>({password: isly.string()})constmyUser: UserWithCredentials={name: "Joe",password: "12345678",}console.log(userType.get(myUser))// Prints myUser without password.

Modifiers

.array()

Make an array type.

It is possible to add restrictions to the type as parameters.

isly.string().array({criteria: "minLength",value: 3})

Note, in some circumstances type inference might not always be working the same for isly.object({ a: isly.string() }).array() and isly.array(isly.object({ a: isly.string() }))

Try the second if the object isn't provided an generic type and the first doesn't work.

.optional()

Add | undefined to type.

.readonly()

Add Readonly<...> to type.

Modifiers for isly.object

isly.object() returns a type which has more modifiers.

.extend()

interfaceItem1{i1: number}interfaceItem2extendsItem1{i2: number}interfaceItem3extendsItem2{i3: number}consttypeItem1=isly.object<Item1>({i1: isly.number()},"Item1")// It is possible (but optional) to add conditions to properties in the base-type:consttypeItem2=typeItem1.extend<Item2>({i2: isly.number(),i1: isly.number(value=>value>=400)},"Item2")consttypeItem3=typeItem2.extend<Item3>({i3: isly.number()},"Item3")

.pick()

interfaceUser{firstName: stringlastName: stringpassword: string}typeUserWithoutCredentials=Pick<User,"firstName"|"lastName">constuserType=isly.object<User>({firstName: isly.string(),lastName: isly.string(),password: isly.string()})constUserWithoutCredentials=userType.pick(["firstName","lastName"],"UserWithoutCredentials")

.omit()

interfaceUser{firstName: stringlastName: stringpassword: string}typeUserWithoutCredentials=Omit<User,"password">constuserType=isly.object<User>({firstName: isly.string(),lastName: isly.string(),password: isly.string()})constUserWithoutCredentials=userType.omit(["password"],"UserWithoutCredentials")

Usage patterns

This is a possible usage pattern.

// model/Event.tsimport{isly}from"isly"exportinterfaceEvent{name: stringdescription?: string}exportnamespaceEvent{exportconsttype=isly.object<Event>({name: isly.string(),description: isly.string().optional(),},"Event")exportconstis=type.isexportconstflaw=type.flaw// You can put more stuff here:
...
}

Which is used like:

import{Event}from"model/Event"
...
if(!Event.is(myValue)){returnEvent.flaw(myValue)}else{// use myValue here!
...
}
...

About

Library for creating runtime type checks.

Resources

Contributing

Stars

0 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages

Generated from utily/library-template