Skip to content

Instantly share code, notes, and snippets.

@th3terrorist
Last active August 1, 2023 20:26
Show Gist options
  • Save th3terrorist/72604abe739760246f0562d89e99bcfd to your computer and use it in GitHub Desktop.
Save th3terrorist/72604abe739760246f0562d89e99bcfd to your computer and use it in GitHub Desktop.
Unnecessary js match expression
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