Skip to content

Instantly share code, notes, and snippets.

View WimJongeneel's full-sized avatar
:octocat:

Wim Jongeneel WimJongeneel

:octocat:
View GitHub Profile
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]> }
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 InvertPattern<p> =
p extends NumberConstructor ? number :
p extends StringConstructor ? string :
p extends BooleanConstructor ? boolean :
{ [k in keyof p]: InvertPattern<p[k]> }
with: <p extends Pattern<a>>(
pattern: p,
expr: (a: extract<a, InvertPattern<typeof pattern>>) => b
) => match(value, otherwise, [...patterns, [pattern, expr]]),
type Pattern<a> =
a extends number ? a | NumberConstructor :
a extends string ? a | StringConstructor :
a extends boolean ? a | BooleanConstructor :
a extends Array<infer aa> ? [Pattern<aa>] :
{ [k in keyof a]?: Pattern<a[k]> }
type InvertPattern<p> =
p extends NumberConstructor ? number :
p extends StringConstructor ? string :
const match_pattern = <a>(value: a, pattern: Pattern<a>) => {
/* String, Number, Boolean patterns */
if (Array.isArray(pattern)) {
if (!Array.isArray(value)) return false
return value.every(v => match_pattern(v, pattern[0]))
}
if (typeof (value) != 'object') return value === pattern
return Object.keys(pattern).every(k => pattern[k] == undefined ? false : match_pattern(value[k], pattern[k]))
}
let blogOverviewResponse: any = /* ... */
match<any, Blog[] | Error>(blogOverviewResponse)
.with([{Id: Number, Title: String}], r => r.map(b => ({id: b.Id, title: b.Title})))
.with({ errorMessage: String }, r => new Error(r.errorMessage))
.otherwise( () => new Error('client parse error'))
.run()
match value with
| { Id: int, Title: string } v -> Result (Blog v.Id, v.Title)
| { errorMessage: string } v -> Error v.errorMessage
| _ -> Error "client parse error"
b => b.Id == 1 && b.Title.contains("Hello")
type Expr =
| { kind: '==', left: Expr, right: Expr }
| { kind: 'includes', left: Expr, right: Expr }
| { kind: '&&', left: Expr, right: Expr }
| { kind: 'value', value: any }
| { kind: 'index', id: string }
const createValExpression = (value: any): Expr => ({
kind: 'value', value
})
const createBinaryExpression = (kind: '==' | 'includes' | '&&', left: Expr, right: Expr): Expr => ({
kind, left, right
})
const = createIndexExpression(id: string): Expr => ({
kind: 'index', id