Nancy's Preferred Machete

    typescanner
    TypeScript icon, indicating that this package has built-in type declarations

    0.5.3 • Public • Published

    typescanner

    Testing npm bundle size NPM

    A simple library for implementing Type Guard in TypeScript.

    Feature

    • 🛡 Basic Type Guard Functions + Custom Type Guard Functions
    • 💡 Intuitive definition of Object's type guard functions
    • Verify the type of a value in one line

    Demo

    https://codesandbox.io/s/typescanner-demo-ke7d4

    Install

    npm i typescanner

    Example

    // define the union type
    const Lang = {
      ja: "ja",
      en: "en",
    } as const;
    type Lang = typeof Lang[keyof typeof Lang]; // "ja" | "en"
    
    const langList = Object.values(Lang);
    
    type Post = {
      id: number;
      author: string | null;
      body: string;
      lang: Lang;
      isPublic: boolean;
      createdAt: Date;
      tags?: string[] | null;
    };
    
    // create a scanner
    const isPost = scanner<Post>({
      id: number,
      author: union(string, Null),
      body: string,
      lang: list(langList),
      isPublic: boolean,
      createdAt: date,
      tags: optional(array(string), Null),
    });
    
    const data = {
      id: 1,
      author: "taro",
      body: "Hello!",
      lang: "ja",
      isPublic: true,
      createdAt: new Date(),
      tags: ["tag1", "tag2"],
    } as unknown;
    
    // scan
    const post = scan(data, isPost);
    
    post.body; // OK

    Usage

    fields

    fields is used when creating a scanner. fields returns a Condition or an array of conditions as defined below.

    type Condition<T> = (value: unknown) => value is T;
    string; // string
    number; // number
    boolean; // boolean
    symbol; // symbol
    bigint; // bigint
    Undefined; // undefined
    Null; // null
    data; // Date
    
    union(string, null); // string | null
    // If you want to use multiple types other than null and undefined,
    // you need to write the types explicitly.
    union<string | number>(string, number); // string | number
    
    // Passes the Condition for the values in the array.
    array(string); // string[]
    array<string | number>(string, number); // (string | number)[]
    
    optional(string); // string | undefined
    optional<string | number>(string, number); // string | number | undefined
    
    // Check if the value passed when determining the type is contained 
    // in the array passed by list().
    list(["a", "b", "c"]); // "a" | "b" | "c"
    
    // Pass a constructor as argument
    instanceOf(Error)

    scanner

    scanner is a function to implement type guard for objects. It returns a "type guard function" of the type defined by Type Aliase by setting a field to the value of each property.

      type Foo = {
        a: string;
        b: number;
        c: boolean;
        d: Date;
        e: string[];
        f?: string;
        g: "a" | "b" | "c";
        h: string | null;
        i: string | number;
        j: number;
      };
      
      // You can extend fields by defining your own type guard functions.
      const even = (value: unknown): value is number =>
        isNumber(value) && value % 2 === 0;
      
      const isFoo = scanner<Foo>({
        a: string,
        b: number,
        c: boolean,
        d: date,
        e: array(string),
        f: optional(string),
        g: list(["a", "b", "c"]),
        h: union(string, Null),
        i: union<string | number>(string, number),
        j: even, // Custom field
      });
      
      const foo = {
        a: "a",
        b: 2,
        c: true,
        d: new Date(),
        e: ["a", "b"],
        f: "f",
        g: "a",
        j: 2,
      } as unknown;
      
      if (isFoo(foo)) {
        foo.a // OK
      }

    Debugging with scannar

    If you want to see which field has the problem, set outputLog to true.

    WARNING: If the scanner is nested, it may not output logs as expected.

    const isBar = scanner<Bar>({
      a: string,
      b: number,
    }, { outputLog: true })
    
    // throw error
    if (!isBar(data)) throw new Error("data is invalid")
    
    // Error: value.${key} does not meet the condition.

    scan

    scan is used with the first argument being the value you want to validate and the second argument being the Condition. If the verification is successful, the "narrowed value" will be returned. If it fails, it throws an exception.

      // success
      const data = scan(foo as unknown, isFoo);
      data.a // OK
      
      // Error!
      const data = scan(bar as unknown, isFoo); // Error: type assertion is failed.

    other

    Basic type guard functions with function names beginning with "is".

    // primitive
    
    isString("a")
    
    isNumber(1)
    
    isBoolean(true)
    
    isUndefined(undefined)
    
    isNull(null)
    
    isDate(new Data())
    
    isSymbol(Symbol("a"))
    
    isBigint(BigInt(1))
    
    // isUnion
    
    isUnion<string | number>(1, isString, isNumber)
    
    // isObject
    
    isObject(value) // (value: unknown) =>  value is { [P in keyof T]?: unknown }
    
    // isArray
    
    isArray(["a", "b"], isString) // string[]
    
    isArray<string | number>(["a", 1], isString, isNumber) // (string | number)[]
    
    isArray(["a", null, undefined], isString, isNull, isUndefined) // (string | null | undefined)[]
    
    // isOptional
    
    isOptional("a", isString) // true
    
    isOptional(undefined, isString) // true
    
    // isList
    
    const Lang = {
      ja: "ja",
      en: "en",
    } as const;
    
    type Lang = typeof Lang[keyof typeof Lang]; // "ja" | "en"
    const langList = Object.values(Lang);
    
    isList("ja", langList) // true
    
    // isInstanceOf
    
    try {
      ...
    } catch (error) {
      if (isInstanceOf(error, Error)) {
        error.message // OK
      }
    }

    Contribution

    wellcome

    License

    MIT

    Install

    npm i typescanner

    DownloadsWeekly Downloads

    50

    Version

    0.5.3

    License

    MIT

    Unpacked Size

    24.5 kB

    Total Files

    21

    Last publish

    Collaborators

    • yona3