Last active
August 1, 2023 20:26
-
-
Save th3terrorist/72604abe739760246f0562d89e99bcfd to your computer and use it in GitHub Desktop.
Unnecessary js match expression
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 ofClass = (classDef, instance) => { | |
if (typeof classDef === 'function' | |
&& typeof instance === 'object') { | |
return new classDef().constructor === instance.constructor | |
} | |
if (classDef === Number) | |
return typeof instance === 'number' | |
if (classDef === String) | |
return typeof instance === 'string' | |
if (classDef === Boolean) | |
return typeof instance === 'boolean' | |
return false | |
} | |
const hasMatchingStructure = (testStruct, againstStruct) => { | |
if (ofClass(testStruct, againstStruct)) | |
return true | |
if (typeof testStruct === 'object' | |
&& typeof againstStruct === 'object') | |
return includesAllFields(testStruct, againstStruct) | |
return againstStruct === testStruct | |
} | |
const includesField = (key, value, against) => { | |
if (value === true) | |
return Object.keys(against).includes(key) | |
return hasMatchingStructure(value, against[key]) | |
} | |
const includesAllFields = (testObject, againstObject) => | |
Object.entries(testObject) | |
.every(([k, v]) => includesField(k, v, againstObject)) | |
const destructureMatchParams = (...args) => { | |
let defaultExpr = null | |
const pairs = [] | |
for (let i=0; | |
i<args.length; | |
i+=2) { | |
const pattern = args[i] | |
const expr = args[i+1] | |
if (pattern === null) { | |
if (defaultExpr !== null) | |
throw new Error('[match]: duplicate default case detected (null pattern)') | |
defaultExpr = expr | |
continue | |
} | |
pairs.push([pattern, expr]) | |
} | |
return [pairs, defaultExpr] | |
} | |
const match = value => (...args) => { | |
if (value === undefined || value === null) | |
return null | |
if (args.length % 2 !== 0) | |
throw new Error('[match]: number of arguments must be even') | |
const [ | |
pairs, | |
defaultExpr, | |
] = destructureMatchParams(...args) | |
for (const [pattern, expression] of pairs) { | |
if (ofClass(pattern, value)) { | |
return typeof expression === 'function' | |
? expression(value) | |
: expression | |
} | |
if (typeof value !== typeof pattern) | |
continue | |
if (hasMatchingStructure(pattern, value)) { | |
if (typeof expression === 'function') { | |
if (value instanceof Object) { | |
const argObject = Object.keys(pattern) | |
.reduce((acc, k) => ({...acc, [k]: value[k]}), {}) | |
return expression(argObject, ...Object.values(value)) | |
} else { | |
return expression(value) | |
} | |
} | |
return expression | |
} | |
if (value === pattern) { | |
return typeof expression === 'function' | |
? expression(value) | |
: expression | |
} | |
} | |
return typeof defaultExpr === 'function' | |
? defaultExpr(value) | |
: defaultExpr | |
} | |
module.exports = match |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment