@macroforge/mcp-server 0.1.17 → 0.1.21
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/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +108 -0
- package/dist/tools/index.js.map +1 -1
- package/docs/builtin-macros/clone.md +18 -77
- package/docs/builtin-macros/debug.md +19 -118
- package/docs/builtin-macros/default.md +13 -98
- package/docs/builtin-macros/deserialize.md +38 -383
- package/docs/builtin-macros/hash.md +16 -98
- package/docs/builtin-macros/macros-overview.md +33 -9
- package/docs/builtin-macros/ord.md +16 -115
- package/docs/builtin-macros/partial-eq.md +26 -128
- package/docs/builtin-macros/partial-ord.md +19 -99
- package/docs/builtin-macros/serialize.md +28 -126
- package/docs/concepts/architecture.md +27 -58
- package/docs/concepts/derive-system.md +17 -45
- package/docs/concepts/how-macros-work.md +11 -50
- package/docs/custom-macros/custom-overview.md +4 -5
- package/docs/custom-macros/rust-setup.md +3 -4
- package/docs/custom-macros/ts-macro-derive.md +4 -5
- package/docs/custom-macros/ts-quote.md +2 -2
- package/docs/getting-started/first-macro.md +6 -72
- package/docs/getting-started/installation.md +2 -2
- package/docs/integration/integration-overview.md +21 -14
- package/docs/integration/mcp-server.md +84 -0
- package/docs/integration/svelte-preprocessor.md +152 -0
- package/docs/language-servers/svelte.md +80 -0
- package/docs/language-servers/zed.md +84 -0
- package/docs/roadmap/roadmap.md +131 -0
- package/docs/sections.json +29 -5
- package/package.json +4 -3
|
@@ -4,18 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Basic Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
/** @derive(PartialEq) */
|
|
9
|
-
class Point {
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
|
|
13
|
-
constructor(x: number, y: number) {
|
|
14
|
-
this.x = x;
|
|
15
|
-
this.y = y;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
7
|
+
<MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
|
|
18
8
|
|
|
9
|
+
```typescript
|
|
19
10
|
const p1 = new Point(10, 20);
|
|
20
11
|
const p2 = new Point(10, 20);
|
|
21
12
|
const p3 = new Point(5, 5);
|
|
@@ -25,19 +16,6 @@ console.log(p1.equals(p3)); // false (different values)
|
|
|
25
16
|
console.log(p1 === p2); // false (different references)
|
|
26
17
|
```
|
|
27
18
|
|
|
28
|
-
## Generated Code
|
|
29
|
-
|
|
30
|
-
The PartialEq macro generates an equals method that compares each field:
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
equals(other: unknown): boolean {
|
|
34
|
-
if (this === other) return true;
|
|
35
|
-
if (!(other instanceof Point)) return false;
|
|
36
|
-
const typedOther = other as Point;
|
|
37
|
-
return this.x === typedOther.x && this.y === typedOther.y;
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
19
|
## How It Works
|
|
42
20
|
|
|
43
21
|
The PartialEq macro performs field-by-field comparison using these strategies:
|
|
@@ -60,22 +38,9 @@ The PartialEq macro performs field-by-field comparison using these strategies:
|
|
|
60
38
|
|
|
61
39
|
Use `@partialEq(skip)` to exclude a field from equality comparison:
|
|
62
40
|
|
|
63
|
-
|
|
64
|
-
/** @derive(PartialEq) */
|
|
65
|
-
class User {
|
|
66
|
-
id: number;
|
|
67
|
-
name: string;
|
|
68
|
-
|
|
69
|
-
/** @partialEq(skip) */
|
|
70
|
-
createdAt: Date; // Not compared
|
|
71
|
-
|
|
72
|
-
constructor(id: number, name: string, createdAt: Date) {
|
|
73
|
-
this.id = id;
|
|
74
|
-
this.name = name;
|
|
75
|
-
this.createdAt = createdAt;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
41
|
+
<MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
|
|
78
42
|
|
|
43
|
+
```typescript
|
|
79
44
|
const user1 = new User(1, "Alice", new Date("2024-01-01"));
|
|
80
45
|
const user2 = new User(1, "Alice", new Date("2024-12-01"));
|
|
81
46
|
|
|
@@ -86,27 +51,18 @@ console.log(user1.equals(user2)); // true (createdAt is skipped)
|
|
|
86
51
|
|
|
87
52
|
The generated `equals()` method accepts `unknown` and performs runtime type checking:
|
|
88
53
|
|
|
89
|
-
|
|
90
|
-
/** @derive(PartialEq) */
|
|
54
|
+
<InteractiveMacro code={`/** @derive(PartialEq) */
|
|
91
55
|
class User {
|
|
92
56
|
name: string;
|
|
93
57
|
constructor(name: string) {
|
|
94
58
|
this.name = name;
|
|
95
59
|
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** @derive(PartialEq) */
|
|
99
|
-
class Admin {
|
|
100
|
-
name: string;
|
|
101
|
-
constructor(name: string) {
|
|
102
|
-
this.name = name;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
60
|
+
}`} />
|
|
105
61
|
|
|
62
|
+
```typescript
|
|
106
63
|
const user = new User("Alice");
|
|
107
|
-
const admin = new Admin("Alice");
|
|
108
64
|
|
|
109
|
-
console.log(user.equals(
|
|
65
|
+
console.log(user.equals(new User("Alice"))); // true
|
|
110
66
|
console.log(user.equals("Alice")); // false (not a User instance)
|
|
111
67
|
```
|
|
112
68
|
|
|
@@ -114,8 +70,7 @@ console.log(user.equals("Alice")); // false (not a User instance)
|
|
|
114
70
|
|
|
115
71
|
For objects with nested fields, PartialEq recursively calls `equals()` if available:
|
|
116
72
|
|
|
117
|
-
|
|
118
|
-
/** @derive(PartialEq) */
|
|
73
|
+
<InteractiveMacro code={`/** @derive(PartialEq) */
|
|
119
74
|
class Address {
|
|
120
75
|
city: string;
|
|
121
76
|
zip: string;
|
|
@@ -135,8 +90,9 @@ class Person {
|
|
|
135
90
|
this.name = name;
|
|
136
91
|
this.address = address;
|
|
137
92
|
}
|
|
138
|
-
}
|
|
93
|
+
}`} />
|
|
139
94
|
|
|
95
|
+
```typescript
|
|
140
96
|
const addr1 = new Address("NYC", "10001");
|
|
141
97
|
const addr2 = new Address("NYC", "10001");
|
|
142
98
|
|
|
@@ -146,47 +102,13 @@ const p2 = new Person("Alice", addr2);
|
|
|
146
102
|
console.log(p1.equals(p2)); // true (deep equality via Address.equals)
|
|
147
103
|
```
|
|
148
104
|
|
|
149
|
-
## With Arrays
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
/** @derive(PartialEq) */
|
|
153
|
-
class Team {
|
|
154
|
-
name: string;
|
|
155
|
-
members: string[];
|
|
156
|
-
|
|
157
|
-
constructor(name: string, members: string[]) {
|
|
158
|
-
this.name = name;
|
|
159
|
-
this.members = members;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const t1 = new Team("Alpha", ["Alice", "Bob"]);
|
|
164
|
-
const t2 = new Team("Alpha", ["Alice", "Bob"]);
|
|
165
|
-
const t3 = new Team("Alpha", ["Alice", "Charlie"]);
|
|
166
|
-
|
|
167
|
-
console.log(t1.equals(t2)); // true
|
|
168
|
-
console.log(t1.equals(t3)); // false
|
|
169
|
-
```
|
|
170
|
-
|
|
171
105
|
## Interface Support
|
|
172
106
|
|
|
173
107
|
PartialEq works with interfaces. For interfaces, a namespace is generated with an `equals` function:
|
|
174
108
|
|
|
175
|
-
|
|
176
|
-
/** @derive(PartialEq) */
|
|
177
|
-
interface Point {
|
|
178
|
-
x: number;
|
|
179
|
-
y: number;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Generated:
|
|
183
|
-
// export namespace Point {
|
|
184
|
-
// export function equals(self: Point, other: Point): boolean {
|
|
185
|
-
// if (self === other) return true;
|
|
186
|
-
// return self.x === other.x && self.y === other.y;
|
|
187
|
-
// }
|
|
188
|
-
// }
|
|
109
|
+
<MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
|
|
189
110
|
|
|
111
|
+
```typescript
|
|
190
112
|
const p1: Point = { x: 10, y: 20 };
|
|
191
113
|
const p2: Point = { x: 10, y: 20 };
|
|
192
114
|
const p3: Point = { x: 5, y: 5 };
|
|
@@ -199,21 +121,9 @@ console.log(Point.equals(p1, p3)); // false
|
|
|
199
121
|
|
|
200
122
|
PartialEq works with enums. For enums, strict equality comparison is used:
|
|
201
123
|
|
|
202
|
-
|
|
203
|
-
/** @derive(PartialEq) */
|
|
204
|
-
enum Status {
|
|
205
|
-
Active = "active",
|
|
206
|
-
Inactive = "inactive",
|
|
207
|
-
Pending = "pending",
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Generated:
|
|
211
|
-
// export namespace Status {
|
|
212
|
-
// export function equals(a: Status, b: Status): boolean {
|
|
213
|
-
// return a === b;
|
|
214
|
-
// }
|
|
215
|
-
// }
|
|
124
|
+
<MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
|
|
216
125
|
|
|
126
|
+
```typescript
|
|
217
127
|
console.log(Status.equals(Status.Active, Status.Active)); // true
|
|
218
128
|
console.log(Status.equals(Status.Active, Status.Inactive)); // false
|
|
219
129
|
```
|
|
@@ -222,21 +132,9 @@ console.log(Status.equals(Status.Active, Status.Inactive)); // false
|
|
|
222
132
|
|
|
223
133
|
PartialEq works with type aliases. For object types, field-by-field comparison is used:
|
|
224
134
|
|
|
225
|
-
|
|
226
|
-
/** @derive(PartialEq) */
|
|
227
|
-
type Point = {
|
|
228
|
-
x: number;
|
|
229
|
-
y: number;
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
// Generated:
|
|
233
|
-
// export namespace Point {
|
|
234
|
-
// export function equals(a: Point, b: Point): boolean {
|
|
235
|
-
// if (a === b) return true;
|
|
236
|
-
// return a.x === b.x && a.y === b.y;
|
|
237
|
-
// }
|
|
238
|
-
// }
|
|
135
|
+
<MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
|
|
239
136
|
|
|
137
|
+
```typescript
|
|
240
138
|
const p1: Point = { x: 10, y: 20 };
|
|
241
139
|
const p2: Point = { x: 10, y: 20 };
|
|
242
140
|
|
|
@@ -245,10 +143,10 @@ console.log(Point.equals(p1, p2)); // true
|
|
|
245
143
|
|
|
246
144
|
For union types, strict equality is used:
|
|
247
145
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
type ApiStatus = "loading" | "success" | "error";
|
|
146
|
+
<InteractiveMacro code={`/** @derive(PartialEq) */
|
|
147
|
+
type ApiStatus = "loading" | "success" | "error";`} />
|
|
251
148
|
|
|
149
|
+
```typescript
|
|
252
150
|
console.log(ApiStatus.equals("success", "success")); // true
|
|
253
151
|
console.log(ApiStatus.equals("success", "error")); // false
|
|
254
152
|
```
|
|
@@ -257,8 +155,7 @@ console.log(ApiStatus.equals("success", "error")); // false
|
|
|
257
155
|
|
|
258
156
|
### Finding Items in Arrays
|
|
259
157
|
|
|
260
|
-
|
|
261
|
-
/** @derive(PartialEq) */
|
|
158
|
+
<InteractiveMacro code={`/** @derive(PartialEq) */
|
|
262
159
|
class Product {
|
|
263
160
|
sku: string;
|
|
264
161
|
name: string;
|
|
@@ -267,8 +164,9 @@ class Product {
|
|
|
267
164
|
this.sku = sku;
|
|
268
165
|
this.name = name;
|
|
269
166
|
}
|
|
270
|
-
}
|
|
167
|
+
}`} />
|
|
271
168
|
|
|
169
|
+
```typescript
|
|
272
170
|
const products = [
|
|
273
171
|
new Product("A1", "Widget"),
|
|
274
172
|
new Product("B2", "Gadget"),
|
|
@@ -285,8 +183,7 @@ console.log(found); // Product { sku: "B2", name: "Gadget" }
|
|
|
285
183
|
|
|
286
184
|
When using objects as keys in Map-like structures, combine PartialEq with Hash:
|
|
287
185
|
|
|
288
|
-
|
|
289
|
-
/** @derive(PartialEq, Hash) */
|
|
186
|
+
<InteractiveMacro code={`/** @derive(PartialEq, Hash) */
|
|
290
187
|
class Key {
|
|
291
188
|
id: number;
|
|
292
189
|
type: string;
|
|
@@ -295,8 +192,9 @@ class Key {
|
|
|
295
192
|
this.id = id;
|
|
296
193
|
this.type = type;
|
|
297
194
|
}
|
|
298
|
-
}
|
|
195
|
+
}`} />
|
|
299
196
|
|
|
197
|
+
```typescript
|
|
300
198
|
const k1 = new Key(1, "user");
|
|
301
199
|
const k2 = new Key(1, "user");
|
|
302
200
|
|
|
@@ -4,16 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Basic Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
/** @derive(PartialOrd) */
|
|
9
|
-
class Temperature {
|
|
10
|
-
celsius: number;
|
|
11
|
-
|
|
12
|
-
constructor(celsius: number) {
|
|
13
|
-
this.celsius = celsius;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
7
|
+
<MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
|
|
16
8
|
|
|
9
|
+
```typescript
|
|
17
10
|
const t1 = new Temperature(20);
|
|
18
11
|
const t2 = new Temperature(30);
|
|
19
12
|
const t3 = new Temperature(20);
|
|
@@ -26,22 +19,6 @@ console.log(t1.compareTo(t3)); // 0 (t1 == t3)
|
|
|
26
19
|
console.log(t1.compareTo("not a Temperature")); // null
|
|
27
20
|
```
|
|
28
21
|
|
|
29
|
-
## Generated Code
|
|
30
|
-
|
|
31
|
-
The PartialOrd macro generates a compareTo method with runtime type checking:
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
compareTo(other: unknown): number | null {
|
|
35
|
-
if (this === other) return 0;
|
|
36
|
-
if (!(other instanceof Temperature)) return null;
|
|
37
|
-
const typedOther = other as Temperature;
|
|
38
|
-
const cmp0 = (this.celsius < typedOther.celsius ? -1 : this.celsius > typedOther.celsius ? 1 : 0);
|
|
39
|
-
if (cmp0 === null) return null;
|
|
40
|
-
if (cmp0 !== 0) return cmp0;
|
|
41
|
-
return 0;
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
22
|
## Return Values
|
|
46
23
|
|
|
47
24
|
The `compareTo()` method returns:
|
|
@@ -78,22 +55,9 @@ The PartialOrd macro compares fields in declaration order with type checking:
|
|
|
78
55
|
|
|
79
56
|
Use `@ord(skip)` to exclude a field from ordering comparison:
|
|
80
57
|
|
|
81
|
-
|
|
82
|
-
/** @derive(PartialOrd) */
|
|
83
|
-
class Item {
|
|
84
|
-
price: number;
|
|
85
|
-
name: string;
|
|
86
|
-
|
|
87
|
-
/** @ord(skip) */
|
|
88
|
-
description: string; // Not used for ordering
|
|
89
|
-
|
|
90
|
-
constructor(price: number, name: string, description: string) {
|
|
91
|
-
this.price = price;
|
|
92
|
-
this.name = name;
|
|
93
|
-
this.description = description;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
58
|
+
<MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
|
|
96
59
|
|
|
60
|
+
```typescript
|
|
97
61
|
const i1 = new Item(10, "Widget", "A useful widget");
|
|
98
62
|
const i2 = new Item(10, "Widget", "Different description");
|
|
99
63
|
|
|
@@ -104,16 +68,16 @@ console.log(i1.compareTo(i2)); // 0 (description is skipped)
|
|
|
104
68
|
|
|
105
69
|
When using PartialOrd, always handle the `null` case:
|
|
106
70
|
|
|
107
|
-
|
|
108
|
-
/** @derive(PartialOrd) */
|
|
71
|
+
<InteractiveMacro code={`/** @derive(PartialOrd) */
|
|
109
72
|
class Value {
|
|
110
73
|
amount: number;
|
|
111
74
|
|
|
112
75
|
constructor(amount: number) {
|
|
113
76
|
this.amount = amount;
|
|
114
77
|
}
|
|
115
|
-
}
|
|
78
|
+
}`} />
|
|
116
79
|
|
|
80
|
+
```typescript
|
|
117
81
|
function safeCompare(a: Value, b: unknown): string {
|
|
118
82
|
const result = a.compareTo(b);
|
|
119
83
|
if (result === null) {
|
|
@@ -136,16 +100,16 @@ console.log(safeCompare(v, "string")); // "incomparable"
|
|
|
136
100
|
|
|
137
101
|
When sorting, handle `null` values appropriately:
|
|
138
102
|
|
|
139
|
-
|
|
140
|
-
/** @derive(PartialOrd) */
|
|
103
|
+
<InteractiveMacro code={`/** @derive(PartialOrd) */
|
|
141
104
|
class Score {
|
|
142
105
|
value: number;
|
|
143
106
|
|
|
144
107
|
constructor(value: number) {
|
|
145
108
|
this.value = value;
|
|
146
109
|
}
|
|
147
|
-
}
|
|
110
|
+
}`} />
|
|
148
111
|
|
|
112
|
+
```typescript
|
|
149
113
|
const scores = [
|
|
150
114
|
new Score(100),
|
|
151
115
|
new Score(50),
|
|
@@ -161,25 +125,9 @@ scores.sort((a, b) => a.compareTo(b) ?? 0);
|
|
|
161
125
|
|
|
162
126
|
PartialOrd works with interfaces. For interfaces, a namespace is generated with a `compareTo` function:
|
|
163
127
|
|
|
164
|
-
|
|
165
|
-
/** @derive(PartialOrd) */
|
|
166
|
-
interface Measurement {
|
|
167
|
-
value: number;
|
|
168
|
-
unit: string;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Generated:
|
|
172
|
-
// export namespace Measurement {
|
|
173
|
-
// export function compareTo(self: Measurement, other: Measurement): number | null {
|
|
174
|
-
// if (self === other) return 0;
|
|
175
|
-
// const cmp0 = (self.value < other.value ? -1 : self.value > other.value ? 1 : 0);
|
|
176
|
-
// if (cmp0 !== 0) return cmp0;
|
|
177
|
-
// const cmp1 = self.unit.localeCompare(other.unit);
|
|
178
|
-
// if (cmp1 !== 0) return cmp1 < 0 ? -1 : 1;
|
|
179
|
-
// return 0;
|
|
180
|
-
// }
|
|
181
|
-
// }
|
|
128
|
+
<MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
|
|
182
129
|
|
|
130
|
+
```typescript
|
|
183
131
|
const m1: Measurement = { value: 10, unit: "kg" };
|
|
184
132
|
const m2: Measurement = { value: 10, unit: "lb" };
|
|
185
133
|
|
|
@@ -190,21 +138,9 @@ console.log(Measurement.compareTo(m1, m2)); // 1 (kg > lb alphabetically)
|
|
|
190
138
|
|
|
191
139
|
PartialOrd works with enums:
|
|
192
140
|
|
|
193
|
-
|
|
194
|
-
/** @derive(PartialOrd) */
|
|
195
|
-
enum Size {
|
|
196
|
-
Small = 1,
|
|
197
|
-
Medium = 2,
|
|
198
|
-
Large = 3
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Generated:
|
|
202
|
-
// export namespace Size {
|
|
203
|
-
// export function compareTo(a: Size, b: Size): number | null {
|
|
204
|
-
// return a < b ? -1 : a > b ? 1 : 0;
|
|
205
|
-
// }
|
|
206
|
-
// }
|
|
141
|
+
<MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
|
|
207
142
|
|
|
143
|
+
```typescript
|
|
208
144
|
console.log(Size.compareTo(Size.Small, Size.Large)); // -1
|
|
209
145
|
console.log(Size.compareTo(Size.Large, Size.Small)); // 1
|
|
210
146
|
```
|
|
@@ -213,25 +149,9 @@ console.log(Size.compareTo(Size.Large, Size.Small)); // 1
|
|
|
213
149
|
|
|
214
150
|
PartialOrd works with type aliases:
|
|
215
151
|
|
|
216
|
-
|
|
217
|
-
/** @derive(PartialOrd) */
|
|
218
|
-
type Interval = {
|
|
219
|
-
start: number;
|
|
220
|
-
end: number;
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
// Generated:
|
|
224
|
-
// export namespace Interval {
|
|
225
|
-
// export function compareTo(a: Interval, b: Interval): number | null {
|
|
226
|
-
// if (a === b) return 0;
|
|
227
|
-
// const cmp0 = (a.start < b.start ? -1 : a.start > b.start ? 1 : 0);
|
|
228
|
-
// if (cmp0 !== 0) return cmp0;
|
|
229
|
-
// const cmp1 = (a.end < b.end ? -1 : a.end > b.end ? 1 : 0);
|
|
230
|
-
// if (cmp1 !== 0) return cmp1;
|
|
231
|
-
// return 0;
|
|
232
|
-
// }
|
|
233
|
-
// }
|
|
152
|
+
<MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
|
|
234
153
|
|
|
154
|
+
```typescript
|
|
235
155
|
const i1: Interval = { start: 0, end: 10 };
|
|
236
156
|
const i2: Interval = { start: 0, end: 20 };
|
|
237
157
|
|
|
@@ -246,8 +166,7 @@ Choose between `Ord` and `PartialOrd` based on your use case:
|
|
|
246
166
|
|
|
247
167
|
- **PartialOrd** → Use when comparing with `unknown` types or when some values might be incomparable
|
|
248
168
|
|
|
249
|
-
|
|
250
|
-
// PartialOrd is safer for public APIs that accept unknown input
|
|
169
|
+
<InteractiveMacro code={`// PartialOrd is safer for public APIs that accept unknown input
|
|
251
170
|
/** @derive(PartialOrd) */
|
|
252
171
|
class SafeValue {
|
|
253
172
|
data: number;
|
|
@@ -260,8 +179,9 @@ class SafeValue {
|
|
|
260
179
|
const result = this.compareTo(other);
|
|
261
180
|
return result !== null && result > 0;
|
|
262
181
|
}
|
|
263
|
-
}
|
|
182
|
+
}`} />
|
|
264
183
|
|
|
184
|
+
```typescript
|
|
265
185
|
const safe = new SafeValue(100);
|
|
266
186
|
console.log(safe.isGreaterThan(new SafeValue(50))); // true
|
|
267
187
|
console.log(safe.isGreaterThan("invalid")); // false
|