remutable-ts 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Dan Funder Christoffersen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # remutable-ts
2
+
3
+ remutable-ts provides a simple and **type-safe** way to remove readonly
4
+ modifiers from types in TypeScript.
5
+
6
+ This is useful when you:
7
+
8
+ - Need to **mutate objects** that are defined as **readonly** (e.g. libraries,
9
+ framework types).
10
+ - Prefer solutions with **no runtime** overhead.
11
+
12
+ ### ⚡ Why not just remove readonly?
13
+
14
+ Keeping `readonly` by default is safer as it prevents unintended mutations.
15
+ `remutable-ts` allows controlled mutation, even in external modules where
16
+ needed, giving you flexibility without sacrificing type safety.
17
+
18
+ ## Installation
19
+
20
+ For **usage as a devDependency with zero runtime**:
21
+
22
+ ```bash
23
+ npm install --save-dev remutable-ts
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### 1. Make any type mutable
29
+
30
+ ```typescript
31
+ type Example = {
32
+ readonly a: number;
33
+ readonly b: string;
34
+ readonly nested: {
35
+ readonly c: boolean; // Note nested properties will remain readonly
36
+ };
37
+ };
38
+
39
+ const example: Example = {
40
+ a: 1,
41
+ b: "hello",
42
+ nested: {
43
+ c: true
44
+ },
45
+ };
46
+
47
+ // Inline example usage
48
+ (example as Mutable<Example>).a = 2; ✅ allowed now
49
+
50
+ // Using Mutable<T> to get a fully writable type
51
+ const writableExample = example as Mutable<Example>;
52
+
53
+ writableExample.a = 2; ✅ allowed now
54
+ writableExample.b = "world"; ✅ allowed now
55
+ // writableExample.nested.c = false; // Error: Cannot assign to 'c' because it remains a read-only property.
56
+
57
+ console.log("Original example:", example);
58
+ console.log("Writable example before mutation:", writableExample);
59
+ ```
60
+
61
+ ### 2. Using mutable(this) inside a class to get a writable view
62
+
63
+ ```typescript
64
+ //
65
+ class MyClass {
66
+ readonly x: number = 5; // Always apply type to literal values
67
+ readonly name: string = "Alice"; // Always apply type to literal values
68
+
69
+ update() {
70
+ (this as Mutable<this>).x = 20; ✅ allowed now
71
+
72
+ // or using mutable helper function
73
+ mutable(this).name = "Bob"; ✅ allowed now
74
+ }
75
+ }
76
+
77
+ const myInstance = new MyClass();
78
+ console.log("Before update:", myInstance);
79
+ myInstance.update();
80
+ console.log("After update:", myInstance);
81
+ ```
82
+
83
+ #### ⚠️ Gotcha: literal types
84
+
85
+ When you initialize a readonly property with a literal value (e.g.,
86
+ `readonly score = 0`), TypeScript infers a literal type (`0`), not the broader
87
+ type (`number`). This can cause assignment errors when using `Mutable<T>` or
88
+ `mutable<T>()`, since you can't assign, say, `1` to a property of type `0`.
89
+
90
+ **Recommendation:** Explicitly type such properties to avoid this issue:
91
+
92
+ ```typescript
93
+ const score: Mutable<{ readonly score: number }> = { score: 0 }; // ✅ Use an explicit type
94
+ ```
95
+
96
+ This ensures `Mutable<T>` and `mutable<T>()` work as expected for assignments.
97
+
98
+ ## License
99
+
100
+ MIT
@@ -0,0 +1,12 @@
1
+ /**
2
+ * A utility type that removes readonly modifiers from all properties of T,
3
+ * keeping the type structure intact with no runtime impact.
4
+ */
5
+ export type Mutable<T> = {
6
+ -readonly [K in keyof T]: T[K];
7
+ };
8
+ /**
9
+ * Returns the given object typed as Mutable<T>, effectively removing readonly
10
+ * modifiers from its properties. This function preserves the original type shape and only has i minimal runtime impact.
11
+ */
12
+ export declare function mutable<T>(obj: T): Mutable<T>;
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mutable = mutable;
4
+ /**
5
+ * Returns the given object typed as Mutable<T>, effectively removing readonly
6
+ * modifiers from its properties. This function preserves the original type shape and only has i minimal runtime impact.
7
+ */
8
+ function mutable(obj) {
9
+ return obj;
10
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "remutable-ts",
3
+ "version": "0.0.1",
4
+ "description": "TypeScript utility to safely bypass readonly at compile-time with zero runtime overhead.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "example": "npx ts-node example/index.ts"
13
+ },
14
+ "keywords": [
15
+ "typescript",
16
+ "utility",
17
+ "types",
18
+ "readonly",
19
+ "mutable"
20
+ ],
21
+ "author": "FunderForge",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/Funder75/remutable-ts"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.11.24",
29
+ "typescript": "^5.3.3"
30
+ }
31
+ }