@macroforge/mcp-server 0.1.17 → 0.1.20
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(Hash) */
|
|
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(p2.hashCode()); // Same hash (equal values = equal hash)
|
|
|
25
16
|
console.log(p3.hashCode()); // Different hash
|
|
26
17
|
```
|
|
27
18
|
|
|
28
|
-
## Generated Code
|
|
29
|
-
|
|
30
|
-
The Hash macro generates a method that combines field hashes using the FNV-1a style algorithm:
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
hashCode(): number {
|
|
34
|
-
let hash = 17;
|
|
35
|
-
hash = (hash * 31 + (Number.isInteger(this.x) ? this.x | 0 : this.x.toString().split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) | 0;
|
|
36
|
-
hash = (hash * 31 + (Number.isInteger(this.y) ? this.y | 0 : this.y.toString().split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 0))) | 0;
|
|
37
|
-
return hash;
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
19
|
## Hash Algorithm
|
|
42
20
|
|
|
43
21
|
The generated hash function uses the following algorithm for different types:
|
|
@@ -68,22 +46,9 @@ The generated hash function uses the following algorithm for different types:
|
|
|
68
46
|
|
|
69
47
|
Use `@hash(skip)` to exclude a field from hash computation:
|
|
70
48
|
|
|
71
|
-
|
|
72
|
-
/** @derive(Hash) */
|
|
73
|
-
class User {
|
|
74
|
-
id: number;
|
|
75
|
-
name: string;
|
|
76
|
-
|
|
77
|
-
/** @hash(skip) */
|
|
78
|
-
lastLogin: Date; // Not included in hash
|
|
79
|
-
|
|
80
|
-
constructor(id: number, name: string, lastLogin: Date) {
|
|
81
|
-
this.id = id;
|
|
82
|
-
this.name = name;
|
|
83
|
-
this.lastLogin = lastLogin;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
49
|
+
<MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
|
|
86
50
|
|
|
51
|
+
```typescript
|
|
87
52
|
const user1 = new User(1, "Alice", new Date("2024-01-01"));
|
|
88
53
|
const user2 = new User(1, "Alice", new Date("2024-12-01"));
|
|
89
54
|
|
|
@@ -94,8 +59,7 @@ console.log(user1.hashCode() === user2.hashCode()); // true (lastLogin is skippe
|
|
|
94
59
|
|
|
95
60
|
Hash is often used together with PartialEq. Objects that are equal should have the same hash code:
|
|
96
61
|
|
|
97
|
-
|
|
98
|
-
/** @derive(Hash, PartialEq) */
|
|
62
|
+
<InteractiveMacro code={`/** @derive(Hash, PartialEq) */
|
|
99
63
|
class Product {
|
|
100
64
|
sku: string;
|
|
101
65
|
name: string;
|
|
@@ -104,8 +68,9 @@ class Product {
|
|
|
104
68
|
this.sku = sku;
|
|
105
69
|
this.name = name;
|
|
106
70
|
}
|
|
107
|
-
}
|
|
71
|
+
}`} />
|
|
108
72
|
|
|
73
|
+
```typescript
|
|
109
74
|
const p1 = new Product("ABC123", "Widget");
|
|
110
75
|
const p2 = new Product("ABC123", "Widget");
|
|
111
76
|
|
|
@@ -118,23 +83,9 @@ console.log(p1.hashCode() === p2.hashCode()); // true
|
|
|
118
83
|
|
|
119
84
|
Hash also works with interfaces. For interfaces, a namespace is generated with a `hashCode` function:
|
|
120
85
|
|
|
121
|
-
|
|
122
|
-
/** @derive(Hash) */
|
|
123
|
-
interface Point {
|
|
124
|
-
x: number;
|
|
125
|
-
y: number;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Generated:
|
|
129
|
-
// export namespace Point {
|
|
130
|
-
// export function hashCode(self: Point): number {
|
|
131
|
-
// let hash = 17;
|
|
132
|
-
// hash = (hash * 31 + (self.x | 0)) | 0;
|
|
133
|
-
// hash = (hash * 31 + (self.y | 0)) | 0;
|
|
134
|
-
// return hash;
|
|
135
|
-
// }
|
|
136
|
-
// }
|
|
86
|
+
<MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
|
|
137
87
|
|
|
88
|
+
```typescript
|
|
138
89
|
const p: Point = { x: 10, y: 20 };
|
|
139
90
|
console.log(Point.hashCode(p)); // numeric hash value
|
|
140
91
|
```
|
|
@@ -143,28 +94,9 @@ console.log(Point.hashCode(p)); // numeric hash value
|
|
|
143
94
|
|
|
144
95
|
Hash works with enums. For string enums, it hashes the string value; for numeric enums, it uses the numeric value directly:
|
|
145
96
|
|
|
146
|
-
|
|
147
|
-
/** @derive(Hash) */
|
|
148
|
-
enum Status {
|
|
149
|
-
Active = "active",
|
|
150
|
-
Inactive = "inactive",
|
|
151
|
-
Pending = "pending",
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Generated:
|
|
155
|
-
// export namespace Status {
|
|
156
|
-
// export function hashCode(value: Status): number {
|
|
157
|
-
// if (typeof value === "string") {
|
|
158
|
-
// let hash = 0;
|
|
159
|
-
// for (let i = 0; i < value.length; i++) {
|
|
160
|
-
// hash = (hash * 31 + value.charCodeAt(i)) | 0;
|
|
161
|
-
// }
|
|
162
|
-
// return hash;
|
|
163
|
-
// }
|
|
164
|
-
// return value | 0;
|
|
165
|
-
// }
|
|
166
|
-
// }
|
|
97
|
+
<MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
|
|
167
98
|
|
|
99
|
+
```typescript
|
|
168
100
|
console.log(Status.hashCode(Status.Active)); // consistent hash
|
|
169
101
|
console.log(Status.hashCode(Status.Inactive)); // different hash
|
|
170
102
|
```
|
|
@@ -173,33 +105,19 @@ console.log(Status.hashCode(Status.Inactive)); // different hash
|
|
|
173
105
|
|
|
174
106
|
Hash works with type aliases. For object types, it hashes each field:
|
|
175
107
|
|
|
176
|
-
|
|
177
|
-
/** @derive(Hash) */
|
|
178
|
-
type Coordinates = {
|
|
179
|
-
lat: number;
|
|
180
|
-
lng: number;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
// Generated:
|
|
184
|
-
// export namespace Coordinates {
|
|
185
|
-
// export function hashCode(value: Coordinates): number {
|
|
186
|
-
// let hash = 17;
|
|
187
|
-
// hash = (hash * 31 + (value.lat | 0)) | 0;
|
|
188
|
-
// hash = (hash * 31 + (value.lng | 0)) | 0;
|
|
189
|
-
// return hash;
|
|
190
|
-
// }
|
|
191
|
-
// }
|
|
108
|
+
<MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
|
|
192
109
|
|
|
110
|
+
```typescript
|
|
193
111
|
const loc: Coordinates = { lat: 40.7128, lng: -74.0060 };
|
|
194
112
|
console.log(Coordinates.hashCode(loc));
|
|
195
113
|
```
|
|
196
114
|
|
|
197
115
|
For union types, it uses JSON stringification as a fallback:
|
|
198
116
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
type Result = "success" | "error" | "pending";
|
|
117
|
+
<InteractiveMacro code={`/** @derive(Hash) */
|
|
118
|
+
type Result = "success" | "error" | "pending";`} />
|
|
202
119
|
|
|
120
|
+
```typescript
|
|
203
121
|
console.log(Result.hashCode("success")); // hash of "success" string
|
|
204
122
|
console.log(Result.hashCode("error")); // hash of "error" string
|
|
205
123
|
```
|
|
@@ -1,27 +1,43 @@
|
|
|
1
1
|
# Built-in Macros
|
|
2
2
|
|
|
3
|
-
*Macroforge comes with
|
|
3
|
+
*Macroforge comes with built-in derive macros that cover the most common code generation needs. All macros work with classes, interfaces, enums, and type aliases.*
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
| `Debug`
|
|
7
|
+
| [`Debug`]({base}/docs/builtin-macros/debug)
|
|
8
8
|
| `toString(): string`
|
|
9
9
|
| Human-readable string representation
|
|
10
10
|
|
|
11
|
-
| `Clone`
|
|
11
|
+
| [`Clone`]({base}/docs/builtin-macros/clone)
|
|
12
12
|
| `clone(): T`
|
|
13
|
-
| Creates a copy of the object
|
|
13
|
+
| Creates a deep copy of the object
|
|
14
14
|
|
|
15
|
-
| `
|
|
15
|
+
| [`Default`]({base}/docs/builtin-macros/default)
|
|
16
|
+
| `static default(): T`
|
|
17
|
+
| Creates an instance with default values
|
|
18
|
+
|
|
19
|
+
| [`Hash`]({base}/docs/builtin-macros/hash)
|
|
20
|
+
| `hashCode(): number`
|
|
21
|
+
| Generates a hash code for the object
|
|
22
|
+
|
|
23
|
+
| [`PartialEq`]({base}/docs/builtin-macros/partial-eq)
|
|
16
24
|
| `equals(other: T): boolean`
|
|
17
25
|
| Value equality comparison
|
|
18
26
|
|
|
19
|
-
| `
|
|
27
|
+
| [`Ord`]({base}/docs/builtin-macros/ord)
|
|
28
|
+
| `compare(other: T): number`
|
|
29
|
+
| Total ordering comparison (-1, 0, 1)
|
|
30
|
+
|
|
31
|
+
| [`PartialOrd`]({base}/docs/builtin-macros/partial-ord)
|
|
32
|
+
| `partialCompare(other: T): number | null`
|
|
33
|
+
| Partial ordering comparison
|
|
34
|
+
|
|
35
|
+
| [`Serialize`]({base}/docs/builtin-macros/serialize)
|
|
20
36
|
| `toJSON(): Record<string, unknown>`
|
|
21
37
|
| JSON serialization with type handling
|
|
22
38
|
|
|
23
|
-
| `Deserialize`
|
|
24
|
-
| `fromJSON(data: unknown): T`
|
|
39
|
+
| [`Deserialize`]({base}/docs/builtin-macros/deserialize)
|
|
40
|
+
| `static fromJSON(data: unknown): T`
|
|
25
41
|
| JSON deserialization with validation
|
|
26
42
|
|
|
27
43
|
## Using Built-in Macros
|
|
@@ -160,10 +176,18 @@ Each macro has its own options and behaviors:
|
|
|
160
176
|
|
|
161
177
|
- [**Debug**]({base}/docs/builtin-macros/debug) - Customizable field renaming and skipping
|
|
162
178
|
|
|
163
|
-
- [**Clone**]({base}/docs/builtin-macros/clone) -
|
|
179
|
+
- [**Clone**]({base}/docs/builtin-macros/clone) - Deep copying for all field types
|
|
180
|
+
|
|
181
|
+
- [**Default**]({base}/docs/builtin-macros/default) - Default value generation with field attributes
|
|
182
|
+
|
|
183
|
+
- [**Hash**]({base}/docs/builtin-macros/hash) - Hash code generation for use in maps and sets
|
|
164
184
|
|
|
165
185
|
- [**PartialEq**]({base}/docs/builtin-macros/partial-eq) - Value-based equality comparison
|
|
166
186
|
|
|
187
|
+
- [**Ord**]({base}/docs/builtin-macros/ord) - Total ordering for sorting
|
|
188
|
+
|
|
189
|
+
- [**PartialOrd**]({base}/docs/builtin-macros/partial-ord) - Partial ordering comparison
|
|
190
|
+
|
|
167
191
|
- [**Serialize**]({base}/docs/builtin-macros/serialize) - JSON serialization with serde-style options
|
|
168
192
|
|
|
169
193
|
- [**Deserialize**]({base}/docs/builtin-macros/deserialize) - JSON deserialization with validation
|
|
@@ -4,20 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Basic Usage
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
/** @derive(Ord) */
|
|
9
|
-
class Version {
|
|
10
|
-
major: number;
|
|
11
|
-
minor: number;
|
|
12
|
-
patch: number;
|
|
13
|
-
|
|
14
|
-
constructor(major: number, minor: number, patch: number) {
|
|
15
|
-
this.major = major;
|
|
16
|
-
this.minor = minor;
|
|
17
|
-
this.patch = patch;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
7
|
+
<MacroExample before={data.examples.basic.before} after={data.examples.basic.after} />
|
|
20
8
|
|
|
9
|
+
```typescript
|
|
21
10
|
const v1 = new Version(1, 0, 0);
|
|
22
11
|
const v2 = new Version(1, 2, 0);
|
|
23
12
|
const v3 = new Version(1, 2, 0);
|
|
@@ -27,24 +16,6 @@ console.log(v2.compareTo(v1)); // 1 (v2 > v1)
|
|
|
27
16
|
console.log(v2.compareTo(v3)); // 0 (v2 == v3)
|
|
28
17
|
```
|
|
29
18
|
|
|
30
|
-
## Generated Code
|
|
31
|
-
|
|
32
|
-
The Ord macro generates a compareTo method using lexicographic field comparison:
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
compareTo(other: Version): number {
|
|
36
|
-
if (this === other) return 0;
|
|
37
|
-
const typedOther = other;
|
|
38
|
-
const cmp0 = (this.major < typedOther.major ? -1 : this.major > typedOther.major ? 1 : 0);
|
|
39
|
-
if (cmp0 !== 0) return cmp0;
|
|
40
|
-
const cmp1 = (this.minor < typedOther.minor ? -1 : this.minor > typedOther.minor ? 1 : 0);
|
|
41
|
-
if (cmp1 !== 0) return cmp1;
|
|
42
|
-
const cmp2 = (this.patch < typedOther.patch ? -1 : this.patch > typedOther.patch ? 1 : 0);
|
|
43
|
-
if (cmp2 !== 0) return cmp2;
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
19
|
## Comparison Logic
|
|
49
20
|
|
|
50
21
|
The Ord macro compares fields in declaration order (lexicographic ordering). For each type:
|
|
@@ -83,22 +54,9 @@ Unlike `PartialOrd`, the `Ord` macro never returns `null` - it provides total or
|
|
|
83
54
|
|
|
84
55
|
Use `@ord(skip)` to exclude a field from ordering comparison:
|
|
85
56
|
|
|
86
|
-
|
|
87
|
-
/** @derive(Ord) */
|
|
88
|
-
class Task {
|
|
89
|
-
priority: number;
|
|
90
|
-
name: string;
|
|
91
|
-
|
|
92
|
-
/** @ord(skip) */
|
|
93
|
-
createdAt: Date; // Not used for ordering
|
|
94
|
-
|
|
95
|
-
constructor(priority: number, name: string, createdAt: Date) {
|
|
96
|
-
this.priority = priority;
|
|
97
|
-
this.name = name;
|
|
98
|
-
this.createdAt = createdAt;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
57
|
+
<MacroExample before={data.examples.skip.before} after={data.examples.skip.after} />
|
|
101
58
|
|
|
59
|
+
```typescript
|
|
102
60
|
const t1 = new Task(1, "Bug fix", new Date("2024-01-01"));
|
|
103
61
|
const t2 = new Task(1, "Bug fix", new Date("2024-12-01"));
|
|
104
62
|
|
|
@@ -109,8 +67,7 @@ console.log(t1.compareTo(t2)); // 0 (createdAt is skipped)
|
|
|
109
67
|
|
|
110
68
|
The generated `compareTo()` method works directly with `Array.sort()`:
|
|
111
69
|
|
|
112
|
-
|
|
113
|
-
/** @derive(Ord) */
|
|
70
|
+
<InteractiveMacro code={`/** @derive(Ord) */
|
|
114
71
|
class Score {
|
|
115
72
|
points: number;
|
|
116
73
|
name: string;
|
|
@@ -119,8 +76,9 @@ class Score {
|
|
|
119
76
|
this.points = points;
|
|
120
77
|
this.name = name;
|
|
121
78
|
}
|
|
122
|
-
}
|
|
79
|
+
}`} />
|
|
123
80
|
|
|
81
|
+
```typescript
|
|
124
82
|
const scores = [
|
|
125
83
|
new Score(100, "Alice"),
|
|
126
84
|
new Score(50, "Bob"),
|
|
@@ -141,25 +99,9 @@ scores.sort((a, b) => b.compareTo(a));
|
|
|
141
99
|
|
|
142
100
|
Ord works with interfaces. For interfaces, a namespace is generated with a `compareTo` function:
|
|
143
101
|
|
|
144
|
-
|
|
145
|
-
/** @derive(Ord) */
|
|
146
|
-
interface Point {
|
|
147
|
-
x: number;
|
|
148
|
-
y: number;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Generated:
|
|
152
|
-
// export namespace Point {
|
|
153
|
-
// export function compareTo(self: Point, other: Point): number {
|
|
154
|
-
// if (self === other) return 0;
|
|
155
|
-
// const cmp0 = (self.x < other.x ? -1 : self.x > other.x ? 1 : 0);
|
|
156
|
-
// if (cmp0 !== 0) return cmp0;
|
|
157
|
-
// const cmp1 = (self.y < other.y ? -1 : self.y > other.y ? 1 : 0);
|
|
158
|
-
// if (cmp1 !== 0) return cmp1;
|
|
159
|
-
// return 0;
|
|
160
|
-
// }
|
|
161
|
-
// }
|
|
102
|
+
<MacroExample before={data.examples.interface.before} after={data.examples.interface.after} />
|
|
162
103
|
|
|
104
|
+
```typescript
|
|
163
105
|
const points: Point[] = [
|
|
164
106
|
{ x: 5, y: 10 },
|
|
165
107
|
{ x: 1, y: 20 },
|
|
@@ -174,22 +116,9 @@ points.sort((a, b) => Point.compareTo(a, b));
|
|
|
174
116
|
|
|
175
117
|
Ord works with enums. For numeric enums, it compares the numeric values; for string enums, it uses string comparison:
|
|
176
118
|
|
|
177
|
-
|
|
178
|
-
/** @derive(Ord) */
|
|
179
|
-
enum Priority {
|
|
180
|
-
Low = 0,
|
|
181
|
-
Medium = 1,
|
|
182
|
-
High = 2,
|
|
183
|
-
Critical = 3
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Generated:
|
|
187
|
-
// export namespace Priority {
|
|
188
|
-
// export function compareTo(a: Priority, b: Priority): number {
|
|
189
|
-
// return a < b ? -1 : a > b ? 1 : 0;
|
|
190
|
-
// }
|
|
191
|
-
// }
|
|
119
|
+
<MacroExample before={data.examples.enum.before} after={data.examples.enum.after} />
|
|
192
120
|
|
|
121
|
+
```typescript
|
|
193
122
|
console.log(Priority.compareTo(Priority.Low, Priority.High)); // -1
|
|
194
123
|
console.log(Priority.compareTo(Priority.Critical, Priority.Low)); // 1
|
|
195
124
|
console.log(Priority.compareTo(Priority.Medium, Priority.Medium)); // 0
|
|
@@ -199,25 +128,9 @@ console.log(Priority.compareTo(Priority.Medium, Priority.Medium)); // 0
|
|
|
199
128
|
|
|
200
129
|
Ord works with type aliases. For object types, it uses lexicographic field comparison:
|
|
201
130
|
|
|
202
|
-
|
|
203
|
-
/** @derive(Ord) */
|
|
204
|
-
type Coordinate = {
|
|
205
|
-
x: number;
|
|
206
|
-
y: number;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
// Generated:
|
|
210
|
-
// export namespace Coordinate {
|
|
211
|
-
// export function compareTo(a: Coordinate, b: Coordinate): number {
|
|
212
|
-
// if (a === b) return 0;
|
|
213
|
-
// const cmp0 = (a.x < b.x ? -1 : a.x > b.x ? 1 : 0);
|
|
214
|
-
// if (cmp0 !== 0) return cmp0;
|
|
215
|
-
// const cmp1 = (a.y < b.y ? -1 : a.y > b.y ? 1 : 0);
|
|
216
|
-
// if (cmp1 !== 0) return cmp1;
|
|
217
|
-
// return 0;
|
|
218
|
-
// }
|
|
219
|
-
// }
|
|
131
|
+
<MacroExample before={data.examples.typeAlias.before} after={data.examples.typeAlias.after} />
|
|
220
132
|
|
|
133
|
+
```typescript
|
|
221
134
|
const c1: Coordinate = { x: 10, y: 20 };
|
|
222
135
|
const c2: Coordinate = { x: 10, y: 30 };
|
|
223
136
|
|
|
@@ -228,8 +141,7 @@ console.log(Coordinate.compareTo(c1, c2)); // -1 (c1 < c2)
|
|
|
228
141
|
|
|
229
142
|
Use `Ord` when all values of a type are comparable. Use `PartialOrd` when some values might be incomparable (e.g., different types at runtime).
|
|
230
143
|
|
|
231
|
-
|
|
232
|
-
// Ord: Total ordering - never returns null
|
|
144
|
+
<InteractiveMacro code={`// Ord: Total ordering - never returns null
|
|
233
145
|
/** @derive(Ord) */
|
|
234
146
|
class Version {
|
|
235
147
|
major: number;
|
|
@@ -238,21 +150,10 @@ class Version {
|
|
|
238
150
|
this.major = major;
|
|
239
151
|
this.minor = minor;
|
|
240
152
|
}
|
|
241
|
-
}
|
|
153
|
+
}`} />
|
|
242
154
|
|
|
155
|
+
```typescript
|
|
243
156
|
const v1 = new Version(1, 0);
|
|
244
157
|
const v2 = new Version(2, 0);
|
|
245
158
|
console.log(v1.compareTo(v2)); // Always -1, 0, or 1
|
|
246
|
-
|
|
247
|
-
// PartialOrd: Partial ordering - can return null
|
|
248
|
-
/** @derive(PartialOrd) */
|
|
249
|
-
class Value {
|
|
250
|
-
data: number;
|
|
251
|
-
constructor(data: number) {
|
|
252
|
-
this.data = data;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const val = new Value(10);
|
|
257
|
-
console.log(val.compareTo("not a Value")); // null (incomparable)
|
|
258
159
|
```
|