Skip to content

Commit f32e019

Browse files
authored
improvement: change validate from an assertion function to a type guard (#13)
Usage of parser.validate is unclear because you need to assign an output type, which defeats the purpose of this whole library (see microsoft/TypeScript#34596 and related issues.) This changes .validate (which throws on invalid input) to .validates, which is a type guard that returns false on invalid input. .parse still throws on invalid input. BREAKING CHANGE: TsjsonParser.validate renamed to TsjsonParser.validates and functionality changed from assertion function to type guard.
1 parent bad212a commit f32e019

File tree

2 files changed

+14
-10
lines changed

2 files changed

+14
-10
lines changed

src/tsjson-parser.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,25 @@ export class TsjsonParser<T extends SchemaLike> {
2525
this.validator = ajv.compile(schema);
2626
}
2727

28-
public validate(data: unknown): asserts data is Validated<T> {
28+
// call this to get the errors from the most recent validation call.
29+
public getErrors = () => this.validator.errors;
30+
31+
public validates(data: unknown): data is Validated<T> {
2932
const valid = this.validator(data);
3033
if (!valid) {
31-
throw new Error(JSON.stringify(this.validator.errors));
34+
return false;
3235
}
36+
return true;
3337
}
3438

3539
public parse = (text: string, skipValidation = false): Validated<T> => {
3640
const data: unknown = JSON.parse(text);
3741
if (skipValidation) {
3842
return data;
3943
}
40-
this.validate(data);
41-
return data;
44+
if (this.validates(data)) {
45+
return data;
46+
}
47+
throw new Error(JSON.stringify(this.validator.errors));
4248
};
4349
}

src/tsjson.test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,25 +163,23 @@ describe("Sanity-checks:", () => {
163163
});
164164

165165
test("Ensure validate is not called if skipValidation is true", () => {
166-
/* eslint-disable @typescript-eslint/unbound-method */
167166
const parser = new TsjsonParser(S({ type: "null" }));
168-
parser.validate = jest.fn();
167+
const spy = jest.spyOn(parser, "validates");
169168
const parsed = parser.parse(JSON.stringify(null));
170169
expectType<null>(parsed);
171170
expect(parsed).toBe(null);
172-
expect(parser.validate).toBeCalledTimes(1);
171+
expect(spy).toBeCalledTimes(1);
173172
parser.parse(JSON.stringify(null), true);
174-
expect(parser.validate).toBeCalledTimes(1);
173+
expect(spy).toBeCalledTimes(1);
175174
expect(ajv.validateSchema(parser.schema)).toBe(true);
176-
/* eslint-enable @typescript-eslint/unbound-method */
177175
});
178176

179177
test("SkipValidation is dangerous", () => {
180178
const parser = new TsjsonParser(S({ type: "null" }));
181179
const parsed = parser.parse(JSON.stringify(SAMPLE_STRING_1), true);
182180
expectType<null>(parsed); // typeof parsed === null, which is wrong!
183181
expect(parsed).toBe(SAMPLE_STRING_1);
184-
expect(() => parser.validate(parsed)).toThrow();
182+
expect(parser.validates(parsed)).toBe(false);
185183
expect(ajv.validateSchema(parser.schema)).toBe(true);
186184
});
187185

0 commit comments

Comments
 (0)