Skip to content

Commit 5b4795c

Browse files
authored
Merge pull request #57 from lambdalisue/impl-objmodify
👍 Add `isObjectOf` modify functions (`isReadonlyOf`, `isStrictOf`, `isRequiredOf`, `isPartialOf`, `isPickOf`, and `isOmitOf`)
2 parents f38987f + a3b2679 commit 5b4795c

19 files changed

+3128
-1822
lines changed

README.md

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ if (is.String(a)) {
3131
}
3232
```
3333

34-
Additionally, `is*Of` (or `is.*Of`) functions return type predicate functions to
35-
predicate types of `x` more precisely like:
34+
For more complex types, you can use `is*Of` (or `is.*Of`) functions like:
3635

3736
```typescript
3837
import {
@@ -44,16 +43,19 @@ const isArticle = is.ObjectOf({
4443
title: is.String,
4544
body: is.String,
4645
refs: is.ArrayOf(
47-
is.OneOf([
46+
is.UnionOf([
4847
is.String,
4948
is.ObjectOf({
5049
name: is.String,
5150
url: is.String,
5251
}),
5352
]),
5453
),
54+
createTime: is.OptionalOf(is.InstanceOf(Date)),
55+
updateTime: is.OptionalOf(is.InstanceOf(Date)),
5556
});
5657

58+
// Infer the type of `Article` from the definition of `isArticle`
5759
type Article = PredicateType<typeof isArticle>;
5860

5961
const a: unknown = {
@@ -76,6 +78,114 @@ if (isArticle(a)) {
7678
}
7779
```
7880

81+
Additionally, you can manipulate the predicate function returned from
82+
`isObjectOf` with `isPickOf`, `isOmitOf`, `isPartialOf`, and `isRequiredOf`
83+
similar to TypeScript's `Pick`, `Omit`, `Partial`, `Required` utility types.
84+
85+
```typescript
86+
import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
87+
88+
const isArticle = is.ObjectOf({
89+
title: is.String,
90+
body: is.String,
91+
refs: is.ArrayOf(
92+
is.UnionOf([
93+
is.String,
94+
is.ObjectOf({
95+
name: is.String,
96+
url: is.String,
97+
}),
98+
]),
99+
),
100+
createTime: is.OptionalOf(is.InstanceOf(Date)),
101+
updateTime: is.OptionalOf(is.InstanceOf(Date)),
102+
});
103+
104+
const isArticleCreateParams = is.PickOf(isArticle, ["title", "body", "refs"]);
105+
// is equivalent to
106+
//const isArticleCreateParams = is.ObjectOf({
107+
// title: is.String,
108+
// body: is.String,
109+
// refs: is.ArrayOf(
110+
// is.UnionOf([
111+
// is.String,
112+
// is.ObjectOf({
113+
// name: is.String,
114+
// url: is.String,
115+
// }),
116+
// ]),
117+
// ),
118+
//});
119+
120+
const isArticleUpdateParams = is.OmitOf(isArticleCreateParams, ["title"]);
121+
// is equivalent to
122+
//const isArticleUpdateParams = is.ObjectOf({
123+
// body: is.String,
124+
// refs: is.ArrayOf(
125+
// is.UnionOf([
126+
// is.String,
127+
// is.ObjectOf({
128+
// name: is.String,
129+
// url: is.String,
130+
// }),
131+
// ]),
132+
// ),
133+
//});
134+
135+
const isArticlePatchParams = is.PartialOf(isArticleUpdateParams);
136+
// is equivalent to
137+
//const isArticlePatchParams = is.ObjectOf({
138+
// body: is.OptionalOf(is.String),
139+
// refs: is.OptionalOf(is.ArrayOf(
140+
// is.UnionOf([
141+
// is.String,
142+
// is.ObjectOf({
143+
// name: is.String,
144+
// url: is.String,
145+
// }),
146+
// ]),
147+
// )),
148+
//});
149+
150+
const isArticleAvailableParams = is.RequiredOf(isArticle);
151+
// is equivalent to
152+
//const isArticlePutParams = is.ObjectOf({
153+
// body: is.String,
154+
// refs: is.ArrayOf(
155+
// is.UnionOf([
156+
// is.String,
157+
// is.ObjectOf({
158+
// name: is.String,
159+
// url: is.String,
160+
// }),
161+
// ]),
162+
// ),
163+
// createTime: is.InstanceOf(Date),
164+
// updateTime: is.InstanceOf(Date),
165+
//});
166+
```
167+
168+
If you need an union type or an intersection type, use `isUnionOf` and
169+
`isIntersectionOf` like:
170+
171+
```typescript
172+
import { is } from "https://deno.land/x/unknownutil@$MODULE_VERSION/mod.ts";
173+
174+
const isFoo = is.ObjectOf({
175+
foo: is.String,
176+
});
177+
178+
const isBar = is.ObjectOf({
179+
bar: is.String,
180+
});
181+
182+
const isFooOrBar = is.UnionOf([isFoo, isBar]);
183+
// { foo: string } | { bar: string }
184+
185+
const isFooAndBar = is.IntersectionOf([isFoo, isBar]);
186+
// { foo: string } & { bar: string }
187+
```
188+
79189
### assert
80190

81191
The `assert` function does nothing if a given value is expected type. Otherwise,

_typeutil.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export type FlatType<T> = T extends Record<PropertyKey, unknown>
2+
? { [K in keyof T]: FlatType<T[K]> }
3+
: T;
4+
5+
export type UnionToIntersection<U> =
6+
(U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void)
7+
? I
8+
: never;
9+
10+
export type Writable<T> = { -readonly [P in keyof T]: T[P] };

0 commit comments

Comments
 (0)