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!}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 0interfaceUser{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.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.
Add | undefined to type.
Add Readonly<...> to type.
isly.object() returns a type which has more modifiers.
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")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")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")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!
...
}
...