diff --git a/src/utils/customError.test.ts b/src/utils/customError.test.ts new file mode 100644 index 00000000..45a0bd1c --- /dev/null +++ b/src/utils/customError.test.ts @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2022 The Pybricks Authors + +import { CustomError } from './customError'; + +// all subclasses should be declared like this: + +type TestErrorName = 'Test'; + +class TestError extends CustomError {} + +describe('CustomError', () => { + it('should work with instanceof', () => { + expect(new TestError('Test', 'test')).toBeInstanceOf(TestError); + }); + + it('should override name', () => { + expect(new TestError('Test', 'test')).toHaveProperty('name', 'Test'); + }); + + it('should pass cause', () => { + const testCause = new Error('test cause'); + expect(() => { + throw new TestError('Test', 'test', testCause); + }).toThrow({ name: 'Test', message: 'test', cause: testCause }); + }); + + it('should serialize to something useful', () => { + expect(JSON.stringify(new TestError('Test', 'test'))).toBe( + '"[TestError: Test]"', + ); + + expect(`${new TestError('Test', 'test')}`).toBe('[TestError: Test]'); + }); +}); diff --git a/src/utils/customError.ts b/src/utils/customError.ts new file mode 100644 index 00000000..e07515dd --- /dev/null +++ b/src/utils/customError.ts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2022 The Pybricks Authors + +export class CustomError extends Error { + public constructor(name: T, message: string, cause?: Error) { + super(message, { cause }); + this.name = name; + Object.setPrototypeOf(this, new.target.prototype); + } + + public toString(): string { + return `[${this.constructor.name}: ${this.name}]`; + } + + public toJSON(): string { + return this.toString(); + } +}