Last active
July 9, 2021 16:22
-
-
Save jaandrle/c76ae19830771270fd5539c91a63b5e3 to your computer and use it in GitHub Desktop.
JavaScript: errors idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const errors= (function(module){ | |
return module(); | |
})(function(){ | |
const proxy_keys= [ "create", "isInstance" ]; | |
const proxy_obj= { get(target, prop){ return prop===Symbol.iterator ? target[Symbol.iterator].bind(target) : target[proxy_keys.indexOf(prop)]; } }; | |
/** | |
* This subclass of Error supports chaining. | |
* If available, it uses the built-in support for property `.cause`. | |
* Otherwise, it sets it up itself. | |
* | |
* @see https://github.com/tc39/proposal-error-cause | |
* @see https://2ality.com/2021/06/error-cause.html | |
*/ | |
class CausedError extends Error { | |
constructor(message, options, skip_stack= 1){ | |
super(message, options); | |
this.stack= this.stack.split("\n").slice(skip_stack).join("\n"); | |
if(!isObject(options)||!hasCause(options)||hasCause(this)) return; | |
const { cause }= options; | |
this.cause= cause; | |
if(!Reflect.has(cause, "stack")) return; | |
const { stack, name, message: message_origin }= cause; | |
const cause_text= `\nCAUSED BY ${name}: ${message_origin}`; | |
Reflect.set(this, "stack", this.stack+cause_text+stack); | |
} | |
} | |
return { create, type, isCausedError, CausedError }; | |
/** | |
* Create new error type based on `name` | |
* @param {string} name Type name of error | |
* @param {function} [messageCreator=i=>i] Message modificator | |
* @returns {[createThis,isInstanceThis]&{create:createThis,isInstance:isInstanceThis}} | |
* @example <caption>Main Usage</caption> | |
* const [ E, isE ]= type("Name"); | |
* const { create, isInstance }= type("Name"); | |
* @example | |
* E= type("Test", ({ name, type })=> `The ${name} is not ${type}`); | |
* E.create({ name: "A", type: "String" }) | |
* //= Test: The A is not String\n… | |
* | |
* E= type("Test2"); | |
* E.create("Message"); | |
* //= Test2: Message\n… | |
*/ | |
function type(name, messageCreator= i=>i){ | |
/** | |
* @callback isInstanceThis | |
* @param {CustomError} _instance | |
* @returns {boolean} | |
*/ | |
/** | |
* @callback createThis | |
* @param {string} message | |
* @param {ErrorOptions} [options] | |
* @returns {CustomError} | |
*/ | |
/** Custom error */ | |
class CustomError extends CausedError{ constructor(m,o){ super(messageCreator(m),o, 3); this.name= name; } } | |
return new Proxy([ (...args)=> new CustomError(...args), isInstance.bind(null, CustomError) ], proxy_obj); | |
} | |
/** | |
* @typedef ErrorOptions | |
* @type {object} | |
* @param {Error} [cause] | |
*/ | |
/** | |
* Initialize Error (in fact `CausedError`) | |
* @param {string} message Error message | |
* @param {ErrorOptions} [options] Error options | |
* @returns {CausedError} | |
*/ | |
function create(message, options){ return new CausedError(message, options, 2); } | |
/** | |
* @param {Error|CausedError} _error | |
* @returns {boolean} | |
*/ | |
function isCausedError(_error){ return _error instanceof CausedError; } | |
function isInstance(_class, _instance){ return _instance instanceof _class; } | |
function isObject(value){ return value !== null && typeof value === "object"; } | |
function hasCause(target){ return Reflect.has(target, "cause"); } | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function createError(name, messageCreator= i=>i, data= null){ | |
class CustomError extends Error{ | |
constructor(...args){ super(messageCreator(...args)); this.name= name; Object.assign(this, data); } | |
static isInstance(_Error){ return _Error instanceof CustomError; } | |
}; | |
const keys= [ "create", "isInstance" ]; | |
return new Proxy( | |
[ (...args)=> new CustomError(...args), CustomError.isInstance ], | |
{ | |
get(target, prop, receiver){ | |
return prop===Symbol.iterator ? target[Symbol.iterator].bind(target) : target[keys.indexOf(prop)]; | |
} | |
} | |
); | |
}; | |
const [ TestError, isTestError ]= createError("TestError"); | |
console.log(TestError, isTestError); | |
const AnotherError= createError("AnotherError"); | |
console.log(AnotherError.create, AnotherError.isInstance); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment