@vicin/sigil 3.0.0 → 3.1.0
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/CHANGELOG.md +11 -0
- package/README.md +65 -9
- package/dist/index.d.mts +120 -196
- package/dist/index.d.ts +120 -196
- package/dist/index.global.js +530 -4
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +526 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +515 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [3.1.0] - 2026-02-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `isExactType` is added to check for exact instances (children are ingored as well)
|
|
10
|
+
|
|
11
|
+
### Removed
|
|
12
|
+
|
|
13
|
+
- `SigilOptions.skipLabelInheritanceCheck` is removed.
|
|
14
|
+
- `isOfTypeStrict` is removed.
|
|
15
|
+
|
|
5
16
|
## [3.0.0] - 2026-02-24
|
|
6
17
|
|
|
7
18
|
### Added
|
package/README.md
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
## Important Notes Before Using
|
|
17
17
|
|
|
18
18
|
- **Explicit class identity:** `Sigil` uses passed class label to identify classes, which means that the developer is responsible for uniqueness of classes by passing unique labels.
|
|
19
|
-
- **Performance:** Minimal overhead, `.isOfType()` is slightly slower than native `instanceof`. Avoid in ultra-hot paths.
|
|
20
19
|
- **Simple instanceof Fix:** If you just need runtime checks without extras, see the [minimal mode](#minimal-mode).
|
|
21
20
|
|
|
22
21
|
## Features
|
|
@@ -24,7 +23,8 @@
|
|
|
24
23
|
- ✅ **Drop-in `instanceof` replacement** that works across bundles, HMR, and monorepos
|
|
25
24
|
- ✅ **True nominal typing** with zero runtime cost
|
|
26
25
|
- ✅ **Inheritance-aware** checks (`isOfType` knows about subclasses)
|
|
27
|
-
- ✅
|
|
26
|
+
- ✅ **Tiny less than 1.5 KB minified and brotlied** measured using size-limit
|
|
27
|
+
- ✅ **Performant as native instanceof** but with guaranteed checks! Also can check for **exact class instance**
|
|
28
28
|
- ✅ Full TypeScript 5.0+ support + excellent JSDoc
|
|
29
29
|
|
|
30
30
|
---
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
- [Options & configuration](#options--configuration)
|
|
47
47
|
- [Minimal mode](#minimal-mode)
|
|
48
48
|
- [Strict mode](#strict-mode)
|
|
49
|
+
- [Benchmarks](#benchmarks)
|
|
49
50
|
- [Contributing](#contributing)
|
|
50
51
|
- [License](#license)
|
|
51
52
|
- [Author](#author)
|
|
@@ -151,7 +152,7 @@ Congratulations — you’ve opted into `Sigil` and you can start replacing `ins
|
|
|
151
152
|
|
|
152
153
|
### Terminology
|
|
153
154
|
|
|
154
|
-
- **Label**: An identity (string) such as `@scope/pkg.ClassName`, but can be random string (e.g. `@Sigil
|
|
155
|
+
- **Label**: An identity (string) such as `@scope/pkg.ClassName`, but can be random string (e.g. `@Sigil-auto:ClassName:mm2gkdwn:0:g1sq`) if no label passed.
|
|
155
156
|
- **EffectiveLabel:** A human-readable (string) such as `@scope/pkg.ClassName`, if no label is passed it inherit the last defined label.
|
|
156
157
|
- **Label lineage**: Array of labels for ancestry.
|
|
157
158
|
- **Label set**: Set of labels for fast checks.
|
|
@@ -171,6 +172,7 @@ if (obj instanceof User) { ... }
|
|
|
171
172
|
|
|
172
173
|
// With Sigil
|
|
173
174
|
if (User.isOfType(obj)) { ... } // This still works even if User was bundled twice.
|
|
175
|
+
if (User.isExactType(obj)) { ... } // Or check for exactly same constructor not its children
|
|
174
176
|
```
|
|
175
177
|
|
|
176
178
|
- **Manual Branding Overhead:** Custom identifiers lead to boilerplate and maintenance issues, `Sigil` add reliable inheritance-aware nominal branding with just one line of code.
|
|
@@ -235,9 +237,17 @@ class Admin extends User {
|
|
|
235
237
|
const admin = new Admin();
|
|
236
238
|
const user = new User();
|
|
237
239
|
|
|
240
|
+
// Instanceof like behavior
|
|
238
241
|
console.log(Admin.isOfType(admin)); // true
|
|
239
242
|
console.log(Admin.isOfType(user)); // false
|
|
240
243
|
console.log(User.isOfType(admin)); // true
|
|
244
|
+
console.log(User.isOfType(user)); // true
|
|
245
|
+
|
|
246
|
+
// Exact checks
|
|
247
|
+
console.log(Admin.isOfType(admin)); // true
|
|
248
|
+
console.log(Admin.isOfType(user)); // false
|
|
249
|
+
console.log(User.isOfType(user)); // true
|
|
250
|
+
console.log(User.isOfType(admin)); // false (Admin is child indeed but this checks for user specifically)
|
|
241
251
|
|
|
242
252
|
type test1 = Admin extends User ? true : false; // true
|
|
243
253
|
type test2 = User extends Admin ? true : false; // false
|
|
@@ -301,11 +311,11 @@ When a constructor is decorated/sigilified it will expose the following **static
|
|
|
301
311
|
|
|
302
312
|
- `SigilLabel` — the identity label string.
|
|
303
313
|
- `SigilEffectiveLabel` — the human label string.
|
|
304
|
-
- `SigilLabelLineage` — readonly array of labels representing parent → child.
|
|
305
|
-
- `SigilLabelSet` — readonly `Set<string>` for
|
|
314
|
+
- `SigilLabelLineage` — readonly array of labels representing parent → child for debugging.
|
|
315
|
+
- `SigilLabelSet` — readonly `Set<string>` for debugging.
|
|
306
316
|
- `isSigilified(obj)` — runtime predicate that delegates to `isSigilInstance`.
|
|
307
|
-
- `isOfType(other)` —
|
|
308
|
-
- `
|
|
317
|
+
- `isOfType(other)` — check if other is an instance of this constructor or its children.
|
|
318
|
+
- `isExactType(other) `— check if other is an instance exactly this constructor.
|
|
309
319
|
|
|
310
320
|
Instances of sigilified classes expose instance helpers:
|
|
311
321
|
|
|
@@ -313,8 +323,8 @@ Instances of sigilified classes expose instance helpers:
|
|
|
313
323
|
- `getSigilEffectiveLabel()` — returns the human label.
|
|
314
324
|
- `getSigilLabelLineage()` — returns lineage array.
|
|
315
325
|
- `getSigilLabelSet()` — returns readonly Set.
|
|
316
|
-
- `isOfType(other)` —
|
|
317
|
-
- `
|
|
326
|
+
- `isOfType(other)` — check if other is an instance of the same class or its children as this.
|
|
327
|
+
- `isExactType(other) `— check if other is an instance exactly the same constructor.
|
|
318
328
|
|
|
319
329
|
---
|
|
320
330
|
|
|
@@ -363,6 +373,52 @@ Now if you forgot to pass a label error is thrown.
|
|
|
363
373
|
|
|
364
374
|
---
|
|
365
375
|
|
|
376
|
+
## Benchmarks
|
|
377
|
+
|
|
378
|
+
Sigil is built for **real-world performance**. Below are the latest micro-benchmark results (run on **Node.js v20.12.0**).
|
|
379
|
+
To run benchmarks on your machine fetch source code from [github](https://github.com/ZiadTaha62/sigil) and run `npm run bench` in your console.
|
|
380
|
+
|
|
381
|
+
### 1. Runtime Type Checking
|
|
382
|
+
|
|
383
|
+
| Depth | `instanceof` (per op) | `isOfType` (ctor) | `isOfType` (instance) | `isExactType` (ctor) | `isExactType` (instance) |
|
|
384
|
+
| ----- | --------------------- | ----------------- | --------------------- | -------------------- | ------------------------ |
|
|
385
|
+
| 0 | 0.000010 ms | 0.000025 ms | **0.000010 ms** | 0.000027 ms | 0.000012 ms |
|
|
386
|
+
| 3 | 0.000032 ms | 0.000045 ms | **0.000027 ms** | 0.000038 ms | **0.000025 ms** |
|
|
387
|
+
| 5 | 0.000034 ms | 0.000046 ms | **0.000028 ms** | 0.000037 ms | **0.000026 ms** |
|
|
388
|
+
| 10 | 0.000044 ms | 0.000045 ms | **0.000029 ms** | 0.000038 ms | **0.000027 ms** |
|
|
389
|
+
| 15 | 0.000058 ms | 0.000063 ms | **0.000051 ms** | 0.000069 ms | **0.000053 ms** |
|
|
390
|
+
|
|
391
|
+
> **Key takeaway**:
|
|
392
|
+
> `isOfType` has **practically the same performance as native `instanceof`**, slightly **slower** on static calls and slightly **faster** on the instance side.
|
|
393
|
+
> `isExactType` adds only a tiny negligible cost and remains extremely fast even on deep hierarchies.
|
|
394
|
+
|
|
395
|
+
### 2. Class Definition & Instance Creation
|
|
396
|
+
|
|
397
|
+
| Scenario | Definition (per class) | Instantiation (per instance) |
|
|
398
|
+
| ------------------------------- | ---------------------- | ---------------------------- |
|
|
399
|
+
| Empty plain class | 0.0122 ms | 0.00019 ms |
|
|
400
|
+
| Empty Sigil class | 0.0672 ms | 0.00059 ms |
|
|
401
|
+
| Small (5 props + 3 methods) | 0.0172 ms | 0.00327 ms |
|
|
402
|
+
| Large (15 props + 10 methods) | 0.0212 ms | 0.00922 ms |
|
|
403
|
+
| Large Sigil | 0.0780 ms | 0.01177 ms |
|
|
404
|
+
| Extended chain depth 5 – plain | 0.0897 ms | 0.01809 ms |
|
|
405
|
+
| Extended chain depth 5 – Sigil | 0.3978 ms | 0.02020 ms |
|
|
406
|
+
| Extended chain depth 10 – plain | 0.2042 ms | 0.05759 ms |
|
|
407
|
+
| Extended chain depth 10 – Sigil | 0.8127 ms | 0.06675 ms |
|
|
408
|
+
|
|
409
|
+
> **Key takeaways**:
|
|
410
|
+
>
|
|
411
|
+
> - Class definition is a **one-time cost** at module load time. Even at depth 10 the cost stays well under 1 ms per class.
|
|
412
|
+
> - Instance creation adds a small fixed overhead of ~0.4–0.6 µs per object, which becomes completely negligible as your classes grow in size and complexity.
|
|
413
|
+
|
|
414
|
+
### Bundle Size
|
|
415
|
+
|
|
416
|
+
**less than 1.5 KB** (minified + Brotli, including all dependencies)
|
|
417
|
+
|
|
418
|
+
This makes Sigil one of the smallest full-featured solutions for nominal typing + reliable runtime identity.
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
366
422
|
## Contributing
|
|
367
423
|
|
|
368
424
|
Any contributions you make are **greatly appreciated**.
|