Skip to content

Commit 9f6b74b

Browse files
committed
Simplify annotation internals a bit
1 parent f796e00 commit 9f6b74b

File tree

3 files changed

+27
-46
lines changed

3 files changed

+27
-46
lines changed

src/core/annotate.ts

+11-33
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,17 @@ export interface ScalarAnnotation {
2020
readonly text?: string;
2121
}
2222

23-
export interface FunctionAnnotation {
24-
readonly type: 'function';
25-
readonly text?: string;
26-
}
27-
28-
export interface CircularRefAnnotation {
29-
readonly type: 'circular-ref';
30-
readonly text?: string;
31-
}
32-
33-
export interface UnknownAnnotation {
34-
readonly type: 'unknown';
35-
readonly value: unknown;
23+
export interface OpaqueAnnotation {
24+
readonly type: 'opaque';
25+
readonly value: string; // e.g. '???' | '<function>' | '<circular ref>'
3626
readonly text?: string;
3727
}
3828

3929
export type Annotation =
4030
| ObjectAnnotation
4131
| ArrayAnnotation
4232
| ScalarAnnotation
43-
| FunctionAnnotation
44-
| CircularRefAnnotation
45-
| UnknownAnnotation;
33+
| OpaqueAnnotation;
4634

4735
/** @internal */
4836
function brand<A extends Annotation>(ann: A): A {
@@ -67,25 +55,15 @@ export function makeArrayAnn(
6755
}
6856

6957
/** @internal */
70-
export function makeFunctionAnn(text?: string): FunctionAnnotation {
71-
return brand({ type: 'function', text });
72-
}
73-
74-
/** @internal */
75-
export function makeUnknownAnn(value: unknown, text?: string): UnknownAnnotation {
76-
return brand({ type: 'unknown', value, text });
58+
export function makeOpaqueAnn(value: string, text?: string): OpaqueAnnotation {
59+
return brand({ type: 'opaque', value, text });
7760
}
7861

7962
/** @internal */
8063
export function makeScalarAnn(value: unknown, text?: string): ScalarAnnotation {
8164
return brand({ type: 'scalar', value, text });
8265
}
8366

84-
/** @internal */
85-
export function makeCircularRefAnn(text?: string): CircularRefAnnotation {
86-
return brand({ type: 'circular-ref', text });
87-
}
88-
8967
/**
9068
* @internal
9169
* Given an existing Annotation, set the annotation's text to a new value.
@@ -122,7 +100,7 @@ function annotateArray(
122100
arr: readonly unknown[],
123101
text: string | undefined,
124102
seen: RefSet,
125-
): ArrayAnnotation | CircularRefAnnotation {
103+
): ArrayAnnotation | OpaqueAnnotation {
126104
seen.add(arr);
127105

128106
// Cannot use .map() here because it won't work correctly if `arr` is
@@ -171,7 +149,7 @@ function annotate(value: unknown, text: string | undefined, seen: RefSet): Annot
171149
if (Array.isArray(value)) {
172150
// "Circular references" can only exist in objects or arrays
173151
if (seen.has(value)) {
174-
return makeCircularRefAnn(text);
152+
return makeOpaqueAnn('<circular ref>', text);
175153
} else {
176154
return annotateArray(value, text, seen);
177155
}
@@ -180,17 +158,17 @@ function annotate(value: unknown, text: string | undefined, seen: RefSet): Annot
180158
if (isPojo(value)) {
181159
// "Circular references" can only exist in objects or arrays
182160
if (seen.has(value)) {
183-
return makeCircularRefAnn(text);
161+
return makeOpaqueAnn('<circular ref>', text);
184162
} else {
185163
return annotateObject(value, text, seen);
186164
}
187165
}
188166

189167
if (typeof value === 'function') {
190-
return makeFunctionAnn(text);
168+
return makeOpaqueAnn('<function>', text);
191169
}
192170

193-
return makeUnknownAnn(value, text);
171+
return makeOpaqueAnn('???', text);
194172
}
195173

196174
function public_annotate(value: unknown, text?: string): Annotation {

src/core/format.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { INDENT, indent, isMultiline, quote } from '~/lib/text';
22
import { isDate } from '~/lib/utils';
33

4-
import type { Annotation, ArrayAnnotation, ObjectAnnotation } from './annotate';
4+
import type {
5+
Annotation,
6+
ArrayAnnotation,
7+
ObjectAnnotation,
8+
OpaqueAnnotation,
9+
} from './annotate';
510

611
export type Formatter = (err: Annotation) => string | Error;
712

@@ -138,19 +143,17 @@ export function serializeAnnotation(
138143
prefix: string = '',
139144
): [string, string | undefined] {
140145
// The serialized data (the input object echoed back)
141-
let serialized;
146+
let serialized: string;
147+
142148
if (ann.type === 'array') {
143149
serialized = serializeArray(ann, prefix);
144150
} else if (ann.type === 'object') {
145151
serialized = serializeObject(ann, prefix);
146-
} else if (ann.type === 'function') {
147-
serialized = '<function>';
148-
} else if (ann.type === 'circular-ref') {
149-
serialized = '<circular ref>';
150-
} else if (ann.type === 'unknown') {
151-
serialized = '???';
152-
} else {
152+
} else if (ann.type === 'scalar') {
153153
serialized = serializeValue(ann.value);
154+
} else {
155+
((_: OpaqueAnnotation) => {})(ann); // Serves as an exhaustiveness check
156+
serialized = ann.value;
154157
}
155158

156159
const text = ann.text;

test/core/annotate.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { Annotation, ObjectAnnotation } from '~/core/annotate';
44
import {
55
annotate,
66
makeArrayAnn,
7-
makeCircularRefAnn,
7+
makeOpaqueAnn,
88
makeObjectAnn as makeObjectAnnOriginal,
99
makeScalarAnn,
1010
merge as mergeOriginal,
@@ -153,7 +153,7 @@ describe('annotating circular objects', () => {
153153

154154
const expected = makeArrayAnn([
155155
makeScalarAnn('foo'),
156-
makeArrayAnn([makeScalarAnn(42), makeCircularRefAnn()]),
156+
makeArrayAnn([makeScalarAnn(42), makeOpaqueAnn('<circular ref>')]),
157157
]);
158158

159159
expect(annotate(circularArray)).toEqual(expected);
@@ -174,9 +174,9 @@ describe('annotating circular objects', () => {
174174
foo: makeScalarAnn(42),
175175
bar: makeObjectAnn({
176176
qux: makeScalarAnn('hello'),
177-
self: makeCircularRefAnn(),
177+
self: makeOpaqueAnn('<circular ref>'),
178178
}),
179-
self: makeCircularRefAnn(),
179+
self: makeOpaqueAnn('<circular ref>'),
180180
});
181181

182182
expect(annotate(circularObject)).toEqual(expected);

0 commit comments

Comments
 (0)