Skip to content

Instantly share code, notes, and snippets.

View WimJongeneel's full-sized avatar
:octocat:

Wim Jongeneel WimJongeneel

:octocat:
View GitHub Profile
const match_pattern = <a>(value: a, pattern: Pattern<a>) => {
if (pattern === String) return typeof(value) == 'string'
if (pattern === Boolean) return typeof(value) == 'boolean'
if (pattern === Number) return typeof(value) == 'number' && Number.isNaN(value) == false
if(typeof (value) != 'object') return value === pattern
return Object.keys(pattern).every(
k => pattern[k] == undefined ? false : match_pattern(value[k], pattern[k])
)
}
type Pattern<a> =
a extends number ? a | NumberConstructor :
a extends string ? a | StringConstructor :
a extends boolean ? a | BooleanConstructor :
{ [k in keyof a]?: Pattern<a[k]> }
match<any, Blog | Error>(httpResult)
.with({Id: Number, Title: String }, r => ({id: r.Id, title: r.Title}))
.with({errorMessage: String}, r => new Error(r.errorMessage))
.otherwise(() => new Error('Client parse error'))
.run()
interface Blog { id: number, title: string }
// Will be { id: number, title: string } | { errorMessage: string }
let httpResult: any = /* API logic. */
let result = httpResult.errorMesage
? new Error(httpResult.errorMessage)
: ({ id: httpResult.Id, title: httpResult.Title })
type LeastUpperBound<a, b> = b extends a ? b : a extends b ? a : never
with: <p extends Pattern<a>>(
pattern: p,
expr: (a: Extract<a, typeof pattern>) => b
) => match(value, otherwise, [...patterns, [pattern, expr]])
type Option<a> = { kind: 'none' } | { kind: 'some', value: a }
let val: Option<string> = { kind: 'some', value: 'hello' }
// Conditinal way of geting the value
if(val.kind == 'some') return val.value
// Pattern matching way of geting the value
match(val)
.with({ kind: 'some' }, o => o.value) // TypeError!
type Pattern<a> = { [ k in keyof a ]?: Pattern<a[k]> }
const match_pattern = <a>(value: a, pattern: Pattern<a>) => typeof(value) != 'object'
? value === pattern
: Object.keys(pattern).every(k => pattern[k] == undefined ? false : match_pattern(value[k], pattern[k]))
match(vector)
.with({ x: 1, y: 1, z: 1 }, () => 'vector3')
.with({ x: 2, y:1 }, () => 'vector2')
.with({ x: 1 }, () => 'vector1')
.otherwise( () => 'no match')
.run()
let vector = { x: 1, y: 1 }
if(vector.z != undefined) return 'vector3'
if(vector.y != undefined) return 'vector2'
return 'vector1'