type-plus 4.3.1 → 4.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -71
- package/cjs/utils/as.d.ts +2 -2
- package/cjs/utils/as.js +2 -2
- package/cjs/utils/as.js.map +1 -1
- package/esm/utils/as.js +2 -2
- package/esm/utils/as.js.map +1 -1
- package/package.json +6 -9
- package/ts/utils/as.spec.ts +33 -24
- package/ts/utils/as.ts +7 -7
package/README.md
CHANGED
|
@@ -15,9 +15,10 @@ Provides additional types and type adjusted utilities for [TypeScript](https://w
|
|
|
15
15
|
|
|
16
16
|
## Feature Highlights
|
|
17
17
|
|
|
18
|
-
- [Type
|
|
19
|
-
- [Nominal Types](#nominal-type)
|
|
18
|
+
- [Type assertions](#type-assertions)
|
|
20
19
|
- [Type Utilities](#type-utilities)
|
|
20
|
+
- [Nominal Types](#nominal-types)
|
|
21
|
+
- [Functional Types](#functional-types)
|
|
21
22
|
|
|
22
23
|
## Installation
|
|
23
24
|
|
|
@@ -27,12 +28,11 @@ npm install type-plus
|
|
|
27
28
|
yarn add type-plus
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
## Type
|
|
31
|
+
## Type Assertions
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
`type-plus` also provides a few other ways to do type assertions.
|
|
33
|
+
Type assertion is one of the main features of `type-plus`.
|
|
34
34
|
|
|
35
|
-
There are
|
|
35
|
+
There are 5 kinds of type assertions:
|
|
36
36
|
|
|
37
37
|
- `runtime`: validates during runtime.
|
|
38
38
|
- `immediate`: validates at compile time.
|
|
@@ -264,70 +264,6 @@ assertType.isTrue(notA({ a: 1 }))
|
|
|
264
264
|
notA({ a: '' }) // TypeScript complains
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
-
## Nominal Type
|
|
268
|
-
|
|
269
|
-
The TypeScript type system is structural.
|
|
270
|
-
|
|
271
|
-
In some cases, we want to express a type with nominal behavior.
|
|
272
|
-
`type-plus` provides two kinds of nominal types: `Brand` and `Flavor`.
|
|
273
|
-
|
|
274
|
-
`Brand<B, T>`:
|
|
275
|
-
|
|
276
|
-
`brand(type, subject?)`:
|
|
277
|
-
|
|
278
|
-
Branded nominal type is the stronger nominal type of the two.
|
|
279
|
-
It disallows unbranded type assigned to it:
|
|
280
|
-
|
|
281
|
-
```ts
|
|
282
|
-
const a = brand('a', { a: 1 })
|
|
283
|
-
const b = { a: 1 }
|
|
284
|
-
a = b // error
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
`subject` can be any type, from primitive to strings to objects.
|
|
288
|
-
|
|
289
|
-
`brand(type)`:
|
|
290
|
-
|
|
291
|
-
If you do not provide `subject`, `brand(type)` will return a brand creator,
|
|
292
|
-
so that you can use it to create multiple branded values:
|
|
293
|
-
|
|
294
|
-
```ts
|
|
295
|
-
const nike = brand('nike')
|
|
296
|
-
const shirt = nike('shirt')
|
|
297
|
-
const socks = nike('socks')
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
`Flavor<F, T>`:
|
|
301
|
-
|
|
302
|
-
`flavor(type, subject?)`:
|
|
303
|
-
|
|
304
|
-
The key difference between `Flavor` and `Brand` is that
|
|
305
|
-
unflavored type can be assigned to `Flavor`:
|
|
306
|
-
|
|
307
|
-
```ts
|
|
308
|
-
let f = flavor('orange', 'soda')
|
|
309
|
-
f = 'mist' // ok
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
Also, `Brand` of the same name can be assigned to `Flavor`,
|
|
313
|
-
but `Flavor` of the same name cannot be assigned to `Brand`.
|
|
314
|
-
|
|
315
|
-
`nominalMatch(a, b)`:
|
|
316
|
-
|
|
317
|
-
`nominalMatch()` can be used to compare `Brand` or `Flavor`.
|
|
318
|
-
|
|
319
|
-
```ts
|
|
320
|
-
const b1 = brand('x', 1)
|
|
321
|
-
const b2 = brand('y', 1)
|
|
322
|
-
|
|
323
|
-
nominalMatch(b1, b2) // false
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
## Functional Types
|
|
327
|
-
|
|
328
|
-
- `ChainFn<T>: T`: chain function that returns the input type.
|
|
329
|
-
- `compose(...fns): F`: compose functions
|
|
330
|
-
|
|
331
267
|
## Type Utilities
|
|
332
268
|
|
|
333
269
|
`type-plus` also provides additional type utilities.
|
|
@@ -415,7 +351,7 @@ JSONTypes.get<string>(someJson, 'a', 'b', 1, 'c') // miku
|
|
|
415
351
|
|
|
416
352
|
- `ANotB<A, B>`: get object with properties in `A` and not in `B`, including properties with a different value type.
|
|
417
353
|
- `BNotA<A, B>`: flip of `ANotB`
|
|
418
|
-
- `as<T>(subject)`: assert `subject` as `T`. Avoid ASI issues such as `;(x as
|
|
354
|
+
- `as<T>(subject)`: assert `subject` as `T`. Avoid ASI issues such as `;(x as T).abc`
|
|
419
355
|
- `asAny(subject)`: assert `subject` as `any`. Avoid ASI issue such as `;(x as any).abc`
|
|
420
356
|
- `Except<T, K>`: Deprecated. Same as `Omit<T, K>`.
|
|
421
357
|
- `ExcludePropType<T, U>`: excludes type `U` from properties in `T`.
|
|
@@ -516,6 +452,70 @@ const source = {
|
|
|
516
452
|
overrider(source, { foo: !!source.foo })
|
|
517
453
|
```
|
|
518
454
|
|
|
455
|
+
## Nominal Types
|
|
456
|
+
|
|
457
|
+
The TypeScript type system is structural.
|
|
458
|
+
|
|
459
|
+
In some cases, we want to express a type with nominal behavior.
|
|
460
|
+
`type-plus` provides two kinds of nominal types: `Brand` and `Flavor`.
|
|
461
|
+
|
|
462
|
+
`Brand<B, T>`:
|
|
463
|
+
|
|
464
|
+
`brand(type, subject?)`:
|
|
465
|
+
|
|
466
|
+
Branded nominal type is the stronger nominal type of the two.
|
|
467
|
+
It disallows unbranded type assigned to it:
|
|
468
|
+
|
|
469
|
+
```ts
|
|
470
|
+
const a = brand('a', { a: 1 })
|
|
471
|
+
const b = { a: 1 }
|
|
472
|
+
a = b // error
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
`subject` can be any type, from primitive to strings to objects.
|
|
476
|
+
|
|
477
|
+
`brand(type)`:
|
|
478
|
+
|
|
479
|
+
If you do not provide `subject`, `brand(type)` will return a brand creator,
|
|
480
|
+
so that you can use it to create multiple branded values:
|
|
481
|
+
|
|
482
|
+
```ts
|
|
483
|
+
const nike = brand('nike')
|
|
484
|
+
const shirt = nike('shirt')
|
|
485
|
+
const socks = nike('socks')
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
`Flavor<F, T>`:
|
|
489
|
+
|
|
490
|
+
`flavor(type, subject?)`:
|
|
491
|
+
|
|
492
|
+
The key difference between `Flavor` and `Brand` is that
|
|
493
|
+
unflavored type can be assigned to `Flavor`:
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
let f = flavor('orange', 'soda')
|
|
497
|
+
f = 'mist' // ok
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Also, `Brand` of the same name can be assigned to `Flavor`,
|
|
501
|
+
but `Flavor` of the same name cannot be assigned to `Brand`.
|
|
502
|
+
|
|
503
|
+
`nominalMatch(a, b)`:
|
|
504
|
+
|
|
505
|
+
`nominalMatch()` can be used to compare `Brand` or `Flavor`.
|
|
506
|
+
|
|
507
|
+
```ts
|
|
508
|
+
const b1 = brand('x', 1)
|
|
509
|
+
const b2 = brand('y', 1)
|
|
510
|
+
|
|
511
|
+
nominalMatch(b1, b2) // false
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Functional Types
|
|
515
|
+
|
|
516
|
+
- `ChainFn<T>: T`: chain function that returns the input type.
|
|
517
|
+
- `compose(...fns): F`: compose functions
|
|
518
|
+
|
|
519
519
|
## Attribution
|
|
520
520
|
|
|
521
521
|
Some of the code in this library is created by other people in the TypeScript community.
|
package/cjs/utils/as.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function as<T>(subject: unknown):
|
|
2
|
-
export declare function asAny(subject: unknown):
|
|
1
|
+
export declare function as<T>(subject: unknown): T;
|
|
2
|
+
export declare function asAny(subject: unknown): any;
|
package/cjs/utils/as.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.asAny = exports.as = void 0;
|
|
4
4
|
function as(subject) {
|
|
5
|
-
return
|
|
5
|
+
return subject;
|
|
6
6
|
}
|
|
7
7
|
exports.as = as;
|
|
8
8
|
function asAny(subject) {
|
|
9
|
-
return
|
|
9
|
+
return subject;
|
|
10
10
|
}
|
|
11
11
|
exports.asAny = asAny;
|
|
12
12
|
//# sourceMappingURL=as.js.map
|
package/cjs/utils/as.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":";;;AAAA,SAAgB,EAAE,CAAI,OAAgB;IACpC,OAAO,
|
|
1
|
+
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":";;;AAAA,SAAgB,EAAE,CAAI,OAAgB;IACpC,OAAO,OAAY,CAAA;AACrB,CAAC;AAFD,gBAEC;AAED,SAAgB,KAAK,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC;AAFD,sBAEC"}
|
package/esm/utils/as.js
CHANGED
package/esm/utils/as.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,EAAE,CAAI,OAAgB;IACpC,OAAO,
|
|
1
|
+
{"version":3,"file":"as.js","sourceRoot":"","sources":["../../ts/utils/as.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,EAAE,CAAI,OAAgB;IACpC,OAAO,OAAY,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "type-plus",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.2",
|
|
4
4
|
"description": "Provides additional types for TypeScript.",
|
|
5
5
|
"homepage": "https://github.com/unional/type-plus",
|
|
6
6
|
"bugs": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"ts"
|
|
27
27
|
],
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "run-p build:cjs build:esm
|
|
29
|
+
"build": "run-p build:cjs build:esm",
|
|
30
30
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
31
31
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
32
32
|
"build:doc": "typedoc",
|
|
@@ -44,12 +44,8 @@
|
|
|
44
44
|
"test:types": "tsc",
|
|
45
45
|
"verify": "run-p verify:build lint test:types coverage",
|
|
46
46
|
"verify:build": "npm-run-all clean build --parallel dependency-check size-limit",
|
|
47
|
-
"watch": "jest --watch"
|
|
48
|
-
|
|
49
|
-
"husky": {
|
|
50
|
-
"hooks": {
|
|
51
|
-
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
52
|
-
}
|
|
47
|
+
"watch": "jest --watch",
|
|
48
|
+
"prepare": "husky install"
|
|
53
49
|
},
|
|
54
50
|
"dependencies": {
|
|
55
51
|
"tersify": "^3.8.2",
|
|
@@ -72,7 +68,7 @@
|
|
|
72
68
|
"dependency-check": "^4.1.0",
|
|
73
69
|
"eslint": "^8.11.0",
|
|
74
70
|
"eslint-plugin-harmony": "^6.0.0",
|
|
75
|
-
"husky": "^7.0.
|
|
71
|
+
"husky": "^7.0.0",
|
|
76
72
|
"jest": "^27.5.1",
|
|
77
73
|
"jest-progress-tracker": "^3.0.3",
|
|
78
74
|
"jest-validate": "^27.5.1",
|
|
@@ -85,6 +81,7 @@
|
|
|
85
81
|
"satisfier": "^5.1.2",
|
|
86
82
|
"size-limit": "^7.0.8",
|
|
87
83
|
"typedoc": "^0.22.13",
|
|
84
|
+
"typedoc-plugin-extras": "^2.2.3",
|
|
88
85
|
"typescript": "^4.6.2"
|
|
89
86
|
},
|
|
90
87
|
"size-limit": [
|
package/ts/utils/as.spec.ts
CHANGED
|
@@ -1,24 +1,33 @@
|
|
|
1
|
-
import { as, asAny, isType } from '..'
|
|
2
|
-
|
|
3
|
-
describe('as<T>()', () => {
|
|
4
|
-
test('defaults subject type to unknown', () => {
|
|
5
|
-
const s: any = {}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
})
|
|
24
|
-
|
|
1
|
+
import { as, asAny, isType } from '..'
|
|
2
|
+
|
|
3
|
+
describe('as<T>()', () => {
|
|
4
|
+
test('defaults subject type to unknown', () => {
|
|
5
|
+
const s: any = {}
|
|
6
|
+
const a = as(s)
|
|
7
|
+
isType.equal<true, unknown, typeof a>()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('cast type to T', () => {
|
|
11
|
+
const s: any = {}
|
|
12
|
+
const n = as<number>(s)
|
|
13
|
+
isType.equal<true, number, typeof n>()
|
|
14
|
+
|
|
15
|
+
const str = as<string>(s)
|
|
16
|
+
isType.equal<true, string, typeof str>()
|
|
17
|
+
|
|
18
|
+
const o = as<{ a: number }>(s)
|
|
19
|
+
isType.equal<true, { a: number }, typeof o>()
|
|
20
|
+
|
|
21
|
+
const any = as<any>(s)
|
|
22
|
+
isType.equal<true, any, typeof any>()
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe('asAny()', () => {
|
|
27
|
+
test('cast type to any', () => {
|
|
28
|
+
const s: unknown = {}
|
|
29
|
+
const a = asAny(s)
|
|
30
|
+
isType.equal<true, any, typeof a>()
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
package/ts/utils/as.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export function as<T>(subject: unknown):
|
|
2
|
-
return
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export function asAny(subject: unknown):
|
|
6
|
-
return
|
|
7
|
-
}
|
|
1
|
+
export function as<T>(subject: unknown): T {
|
|
2
|
+
return subject as T
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function asAny(subject: unknown): any {
|
|
6
|
+
return subject
|
|
7
|
+
}
|