Skip to content

Commit a03dda9

Browse files
authored
Merge pull request #21 from lambdalisue/v3-refine-add
💥 Reimplement for v3
2 parents 904f18e + 1dba5c0 commit a03dda9

File tree

15 files changed

+675
-1773
lines changed

15 files changed

+675
-1773
lines changed

.gitmessage

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
3+
# Guide (v1.0)
4+
#
5+
# 👍 :+1: Apply changes.
6+
#
7+
# 🌿 :herb: Add or update things for tests.
8+
# ☕ :coffee: Add or update things for developments.
9+
# 📦 :package: Add or update dependencies.
10+
# 📝 :memo: Add or update documentations.
11+
#
12+
# 🐛 :bug: Bugfixes.
13+
# 💋 :kiss: Critical hotfixes.
14+
# 🚿 :shower: Remove features, codes, or files.
15+
#
16+
# 🚀 :rocket: Improve performance.
17+
# 💪 :muscle: Refactor codes.
18+
# 💥 :boom: Breaking changes.
19+
# 💩 :poop: Bad codes needs to be improved.
20+
#
21+
# How to use:
22+
# git config commit.template .gitmessage
23+
#
24+
# Reference:
25+
# https://github.com/lambdalisue/emojiprefix

README.md

Lines changed: 72 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -12,228 +12,120 @@ A utility pack for handling `unknown` type.
1212

1313
## Usage
1414

15-
### isXXXXX
15+
It provides `is` module for type predicate functions and `assert`, `ensure`, and
16+
`maybe` helper functions.
1617

17-
The `unknownutil` provides the following predicate functions
18+
### is*
1819

19-
- `isString(x: unknown): x is string`
20-
- `isNumber(x: unknown): x is number`
21-
- `isBoolean(x: unknown): x is boolean`
22-
- `isArray<T extends unknown>(x: unknown, pred?: Predicate<T>): x is T[]`
23-
- `isObject<T extends unknown>(x: unknown, pred?: Predicate<T>): x is Record<string, T>`
24-
- `isFunction(x: unknown): x is (...args: unknown[]) => unknown`
25-
- `isNull(x: unknown): x is null`
26-
- `isUndefined(x: unknown): x is undefined`
27-
- `isNullish(x: unknown): x is null | undefined`
28-
- `isLike<R, T extends unknown>(ref: R, x: unknown, pred?: Predicate<T>): x is R`
29-
30-
The above function can be used to check the type of any variable and guarantee
31-
its type inside a closed `if` scope.
32-
33-
For example:
20+
Type predicate function is a function which returns `true` if a given value is
21+
expected type. For example, `isString` (or `is.String`) returns `true` if a
22+
given value is `string`.
3423

3524
```typescript
36-
import { isString } from "https://deno.land/x/unknownutil/mod.ts";
25+
import { is } from "./mod.ts";
3726

3827
const a: unknown = "Hello";
39-
40-
if (isString(a)) {
28+
if (is.String(a)) {
4129
// 'a' is 'string' in this block
4230
}
4331
```
4432

45-
Additionally, `isArray` and `isObject` supports an inner predicate function to
46-
predicate `x` more precisely like:
47-
48-
```typescript
49-
import { isArray, isString } from "https://deno.land/x/unknownutil/mod.ts";
50-
51-
const a: unknown = ["a", "b", "c"];
52-
53-
if (isArray(a)) {
54-
// 'a' is 'unknown[]' in this block
55-
}
56-
57-
if (isArray(a, isString)) {
58-
// 'a' is 'string[]' in this block
59-
}
60-
```
61-
62-
Use `isLike` if you need some complicated types like:
33+
Additionally, `is*Of` (or `is.*Of`) functions return type predicate functions to
34+
predicate types of `x` more precisely like:
6335

6436
```typescript
65-
import { isLike } from "https://deno.land/x/unknownutil/mod.ts";
66-
67-
const a: unknown = ["a", 0, "b"];
68-
const b: unknown = ["a", 0, "b", "c"];
69-
70-
if (isLike(["", 0, ""], a)) {
71-
// 'a' is [string, number, string] thus this block is called
72-
}
73-
74-
if (isLike(["", 0, ""], b)) {
75-
// 'b' is [string, number, string, string] thus this block is NOT called
76-
}
77-
78-
const c: unknown = { foo: "foo", bar: 100 };
79-
const d: unknown = { foo: "foo", bar: 100, hoge: "hoge" };
80-
const e: unknown = { foo: "foo", hoge: "hoge" };
81-
82-
if (isLike({ foo: "", bar: 0 }, c)) {
83-
// 'c' is {foo: string, bar: number} thus this block is called
84-
}
85-
86-
if (isLike({ foo: "", bar: 0 }, d)) {
87-
// 'd' contains {foo: string, bar: number} thus this block is called
88-
}
89-
90-
if (isLike({ foo: "", bar: 0 }, e)) {
91-
// 'e' does not contain {foo: '', bar: 0} thus this block is NOT called
37+
import { is } from "./mod.ts";
38+
39+
const isArticle = is.ObjectOf({
40+
title: is.String,
41+
body: is.String,
42+
refs: is.ArrayOf(is.OneOf([
43+
is.String,
44+
is.ObjectOf({
45+
name: is.String,
46+
url: is.String,
47+
}),
48+
])),
49+
});
50+
51+
const a: unknown = {
52+
title: "Awesome article",
53+
body: "This is an awesome article",
54+
refs: [
55+
{ name: "Deno", url: "https://deno.land/" },
56+
"https://github.com",
57+
],
58+
};
59+
if (isArticle(a)) {
60+
// a is narrowed to the type of `isArticle`
61+
console.log(a.title);
62+
console.log(a.body);
63+
for (const ref of a.refs) {
64+
if (is.String(ref)) {
65+
console.log(ref);
66+
} else {
67+
console.log(ref.name);
68+
console.log(ref.url);
69+
}
70+
}
9271
}
9372
```
9473

95-
### assertXXXXX
74+
### assert
9675

97-
The `unknownutil` provides the following assert functions
98-
99-
- `assertString(x: unknown): assert x is string`
100-
- `assertNumber(x: unknown): assert x is number`
101-
- `assertBoolean(x: unknown): assert x is boolean`
102-
- `assertArray<T extends unknown>(x: unknown, pred?: Predicate<T>): assert x is T[]`
103-
- `assertObject<T extends unknown>(x: unknown, pred?: Predicate<T>): assert x is Record<string, T>`
104-
- `assertFunction(x: unknown): assert x is (...args: unknown[]) => unknown`
105-
- `assertNull(x: unknown): assert x is null`
106-
- `assertUndefined(x: unknown): assert x is undefined`
107-
- `assertNullish(x: unknown): assert x is null | undefined`
108-
- `assertLike<R, T extends unknown>(ref: R, x: unknown, pred?: Predicate<T>): assert x is R`
109-
110-
The above function can be used to guarantee the type of any variable by throwing
111-
an exception if the type is not expected.
112-
113-
For example:
76+
The `assert` function does nothing if a given value is expected type. Otherwise,
77+
it throws an `AssertError` exception like:
11478

11579
```typescript
116-
import { assertString } from "https://deno.land/x/unknownutil/mod.ts";
117-
118-
function say(message: string): void {
119-
console.log(message);
120-
}
80+
import { assert, is } from "./mod.ts";
12181

12282
const a: unknown = "Hello";
123-
const b: unknown = 0;
124-
125-
// Because 'a' is 'unknown', TypeScript won't allow a code like below
126-
//say(a);
12783

128-
// But once the 'assertString(a)' is passed, TypeScript knows that 'a' is 'string'
129-
// thus it accepts the code that was not accepted before.
130-
assertString(a);
131-
say(a);
84+
// `assert` does nothing or throws an `AssertError`
85+
assert(a, is.String);
86+
// a is now narrowed to string
13287

133-
// Or raise 'AssertError' if a given value is not string
134-
assertString(b);
135-
say(b);
88+
// With custom message
89+
assert(a, is.String, { message: "a must be a string" });
13690
```
13791

138-
More complex type predications are available on `assertXXXXX` as well like
139-
`isXXXXX`.
92+
### ensure
14093

141-
### ensureXXXXX
142-
143-
The `unknownutil` provides the following ensure functions
144-
145-
- `ensureString(x: unknown): string`
146-
- `ensureNumber(x: unknown): number`
147-
- `ensureBoolean(x: unknown): boolean`
148-
- `ensureArray<T extends unknown>(x: unknown, pred?: Predicate<T>): T[]`
149-
- `ensureObject<T extends unknown>(x: unknown, pred?: Predicate<T>): Record<string, T>`
150-
- `ensureFunction(x: unknown): (...args: unknown[]) => unknown`
151-
- `ensureNull(x: unknown): null`
152-
- `ensureUndefined(x: unknown): undefined`
153-
- `ensureNullish(x: unknown): null | undefined`
154-
- `ensureLike<R, T extends unknown>(ref: R, x: unknown, pred?: Predicate<T>): R`
155-
156-
The above function can be used to guarantee the type of any variable by throwing
157-
an exception if the type is not expected. The difference between assert and
158-
ensure is whether to assert the argument or the return type.
159-
160-
For example:
94+
The `ensure` function return the value as-is if a given value is expected type.
95+
Otherwise, it throws an `AssertError` exception like:
16196

16297
```typescript
163-
import { ensureString } from "https://deno.land/x/unknownutil/mod.ts";
164-
165-
function say(message: string): void {
166-
console.log(message);
167-
}
98+
import { ensure, is } from "./mod.ts";
16899

169100
const a: unknown = "Hello";
170-
const b: unknown = 0;
171-
172-
// Because 'a' is 'unknown', TypeScript won't allow a code like below
173-
//say(a);
174101

175-
// But once the 'ensureString(a)' is passed, TypeScript knows that return value is 'string'
176-
// thus it accepts the code.
177-
say(ensureString(a));
102+
// `ensure` returns `string` or throws an `AssertError`
103+
const _: string = ensure(a, is.String);
178104

179-
// Or raise 'AssertError' if a given value is not string
180-
say(ensureString(b));
105+
// With custom message
106+
const __: string = ensure(a, is.String, { message: "a must be a string" });
181107
```
182108

183-
More complex type predications are available on `ensureXXXXX` as well like
184-
`isXXXXX`.
185-
186-
### maybeXXXXX
187-
188-
The `unknownutil` provides the following maybe functions
189-
190-
- `maybeString(x: unknown): string | undefined`
191-
- `maybeNumber(x: unknown): number | undefined`
192-
- `maybeBoolean(x: unknown): boolean | undefined`
193-
- `maybeArray<T extends unknown>(x: unknown, pred?: Predicate<T>): T[] | undefined`
194-
- `maybeObject<T extends unknown>(x: unknown, pred?: Predicate<T>): Record<string, T> | undefined`
195-
- `maybeFunction(x: unknown): ((...args: unknown[]) => unknown) | undefined`
196-
- `maybeLike<R, T extends unknown>(ref: R, x: unknown, pred?: Predicate<T>): R | undefined`
197-
198-
The above function will return `undefined` if the type of any variable is not
199-
expected, so it is possible to give an alternative value using the Nullish
200-
coalescing operator (`??`).
109+
### maybe
201110

202-
For example:
111+
The `maybe` function return the value as-is if a given value is expected type.
112+
Otherwise, it returns `undefined` that suites with
113+
[nullish coalescing operator (`??`)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing)
114+
like:
203115

204116
```typescript
205-
import { maybeString } from "https://deno.land/x/unknownutil/mod.ts";
206-
207-
function say(message: string): void {
208-
console.log(message);
209-
}
117+
import { is, maybe } from "./mod.ts";
210118

211119
const a: unknown = "Hello";
212-
const b: unknown = 0;
213-
214-
// Because 'a' is 'unknown', TypeScript won't allow a code like below
215-
//say(a);
216120

217-
// But the 'maybeString(a)' returns 'string | undefined' thus users can use
218-
// Nullish coalescing operator to give an alternative value to ensure that the
219-
// value given to the 'say()' is 'string'.
220-
// The following code print "Hello" to the console.
221-
say(maybeString(a) ?? "World");
222-
223-
// The following code print "World" to the console.
224-
say(maybeString(b) ?? "World");
121+
// `maybe` returns `string | undefined` so it suites with `??`
122+
const _: string = maybe(a, is.String) ?? "default value";
225123
```
226124

227-
More complex type predications are available on `maybeXXXXX` as well like
228-
`isXXXXX`.
229-
230-
## Migration from v1 to v2
125+
## Migration
231126

232-
1. Replace `ensure` or `assert` to corresponding specific functions (e.g.
233-
`ensureString` or `assertNumber`)
234-
2. Rename `xxxxxNone` to `xxxxxNullish` (e.g. `isNone` to `isNullish`)
235-
3. Rename `ensureXXXXX` to `assertXXXXX` (e.g. `ensureString` to `assertString`)
236-
4. Rename `assumeXXXXX` to `ensureXXXXX` (e.g. `assumeNumber` to `ensureNumber`)
127+
See [GitHub Wiki](https://github.com/lambdalisue/deno-unknownutil/wiki) for
128+
migration to v3 from v2 or v2 from v1.
237129

238130
## License
239131

0 commit comments

Comments
 (0)