typescanner
Advanced tools
Comparing version 0.1.3 to 0.2.0
{ | ||
"name": "typescanner", | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"description": "A simple library for implementing type guards in TypeScript.", | ||
@@ -5,0 +5,0 @@ "author": "yona3", |
209
README.md
# typescanner | ||
A simple library for implementing type guards in TypeScript. | ||
typescanner is a simple library for implementing [Type Guard](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) in TypeScript. | ||
It can be easily implemented from basic primitive type guard to type guard for types defined in Type Aliases. | ||
## Install | ||
```shell | ||
npm i -D typescanner | ||
``` | ||
## Example | ||
```ts | ||
// 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. | ||
```ts | ||
type Condition<T> = (value: unknown) => value is T; | ||
``` | ||
```ts | ||
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" | ||
``` | ||
### scanner | ||
`scanner` is a function for implementing type guard for Objects. It returns a `Condition` of the type defined in Type Aliase by setting a field to the value of each property. | ||
```ts | ||
type Foo = { | ||
a: string; | ||
b: number; | ||
c: boolean; | ||
d: Date; | ||
e: string[]; | ||
f?: string; | ||
g: "a" | "b" | "c"; | ||
h: string | null; | ||
i: string | number; | ||
}; | ||
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), | ||
}); | ||
const foo = { | ||
a: "a", | ||
b: 2, | ||
c: true, | ||
d: new Date(), | ||
e: ["a", "b"], | ||
f: "f", | ||
g: "a", | ||
} as unknown; | ||
if (isFoo(foo)) { | ||
foo.a // OK | ||
} | ||
``` | ||
### 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. | ||
```ts | ||
// success | ||
const data = scan(foo, isFoo); | ||
data.a // OK | ||
// Error! | ||
const data = scan(bar, isFoo); // Error: type assertion is failed. | ||
``` | ||
### primitive | ||
```ts | ||
isString("a") | ||
isNumber(1) | ||
isBoolean(true) | ||
isUndefined(undefined) | ||
isNull(null) | ||
isDate(new Data()) | ||
isSymbol(Symbol("a")) | ||
isBigint(BigInt(1)) | ||
``` | ||
### isArray | ||
```ts | ||
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 | ||
```ts | ||
isOptional("a", isString) // true | ||
isOptional(undefined, isString) // true | ||
``` | ||
### isList | ||
```ts | ||
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) | ||
``` | ||
## Contribution | ||
wellcome | ||
## License | ||
MIT |
@@ -6,2 +6,3 @@ import { | ||
isDate, | ||
isInstanceOf, | ||
isList, | ||
@@ -46,1 +47,7 @@ isNull, | ||
}; | ||
export const instanceOf = <T>( | ||
constructor: new (...args: any[]) => T | ||
): ((value: unknown) => value is T) => { | ||
return (value: unknown): value is T => isInstanceOf(value, constructor); | ||
}; |
@@ -6,2 +6,3 @@ import { | ||
list, | ||
Null, | ||
number, | ||
@@ -12,2 +13,3 @@ optional, | ||
string, | ||
union, | ||
} from ".."; | ||
@@ -24,2 +26,4 @@ | ||
g: "a" | "b" | "c"; | ||
h: string | null; | ||
i: string | number; | ||
}; | ||
@@ -34,2 +38,4 @@ const foo = { | ||
g: "a", | ||
h: "", | ||
i: 3, | ||
} as unknown; | ||
@@ -45,2 +51,4 @@ | ||
g: list(["a", "b", "c"]), | ||
h: union(string, Null), | ||
i: union<string | number>(string, number), | ||
}); | ||
@@ -47,0 +55,0 @@ |
@@ -13,2 +13,3 @@ import { | ||
} from ".."; | ||
import { instanceOf } from "../fields"; | ||
@@ -24,2 +25,6 @@ describe("scan test", () => { | ||
class Timestamp { | ||
constructor(public seconds: number, public nanoseconds: number) {} | ||
} | ||
type Post = { | ||
@@ -34,2 +39,3 @@ id: number; | ||
foo: string | number; | ||
timestamp: Timestamp; | ||
}; | ||
@@ -56,2 +62,3 @@ | ||
foo: union<string | number>(string, number), | ||
timestamp: instanceOf(Timestamp), | ||
}); | ||
@@ -81,2 +88,3 @@ | ||
foo: "foo", | ||
timestamp: new Timestamp(1, 2), | ||
} as unknown; | ||
@@ -83,0 +91,0 @@ |
@@ -1,6 +0,14 @@ | ||
import { isArray, isBoolean, isDate, isNumber, isOptional, isString } from "."; | ||
import { | ||
isArray, | ||
isBoolean, | ||
isDate, | ||
isInstanceOf, | ||
isNumber, | ||
isOptional, | ||
isString, | ||
} from "."; | ||
// isArray | ||
describe("isArray", () => { | ||
it("primitive success", () => { | ||
it("to be true (primitive)", () => { | ||
expect(isArray(["foo", "hoge"], isString)).toBe(true); | ||
@@ -10,3 +18,3 @@ expect(isArray([1, 2, 3], isNumber)).toBe(true); | ||
}); | ||
it("primitive error", () => { | ||
it("to be false (primitive)", () => { | ||
expect(isArray([1, 2, 3], isString)).toBe(false); | ||
@@ -16,3 +24,3 @@ expect(isArray([1, "2"], isString)).toBe(false); | ||
it("union success", () => { | ||
it("to be true (union)", () => { | ||
expect( | ||
@@ -28,3 +36,3 @@ isArray<string | number | boolean | Date>( | ||
}); | ||
it("union error", () => { | ||
it("to be false (union)", () => { | ||
expect( | ||
@@ -43,3 +51,3 @@ isArray<string | number | boolean>( | ||
describe("isOptional", () => { | ||
it("primitive success", () => { | ||
it("to be true (primitive)", () => { | ||
expect(isOptional("", isString)).toBe(true); | ||
@@ -49,11 +57,11 @@ expect(isOptional(undefined, isString)).toBe(true); | ||
}); | ||
it("primitive error", () => { | ||
it("to be false (primitive)", () => { | ||
expect(isOptional(1, isString)).toBe(false); | ||
}); | ||
it("union success", () => { | ||
it("to be true (union)", () => { | ||
expect(isOptional<string | number>("", isString, isNumber)).toBe(true); | ||
}); | ||
it("union error", () => { | ||
it("to be false (union)", () => { | ||
expect(isOptional<string | number>(new Date(), isString, isNumber)).toBe( | ||
@@ -64,1 +72,18 @@ false | ||
}); | ||
// isInstanceOf | ||
describe("isInstanceOf", () => { | ||
class Timestamp { | ||
constructor(public seconds: number, public nanoseconds: number) {} | ||
} | ||
const timestamp = new Timestamp(1, 2) as unknown; | ||
it("to be true", () => { | ||
expect(isInstanceOf(timestamp, Timestamp)).toBe(true); | ||
}); | ||
it("to be false", () => { | ||
expect(isInstanceOf({}, Timestamp)).toBe(false); | ||
}); | ||
}); |
@@ -47,1 +47,6 @@ import type { WouldBe } from "../types"; | ||
): value is T => array.length !== 0 && array.includes(value as T); | ||
export const isInstanceOf = <T>( | ||
value: unknown, | ||
constructor: new (...args: any[]) => T | ||
): value is T => value instanceof constructor; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36027
797
210