Arrows are the only function form. No function keyword means no hoisting surprises and no dynamic this.
let clamp = (n: number, lo = 0, hi = 1) => Math.min(hi, Math.max(lo, n))
let map = <A, B>(xs: A[], f: (a: A) => B): B[] => xs.map(f)
let fetchJson = async (url: string) => await (await fetch(url)).json()Functions are uncurried TypeScript functions, without automatic currying or labelled arguments. Use an options object, the TS idiom. Recursion, async/await, and top-level await are supported directly in the core language.
Type guards and assertions use checked inference or typed imports. Let the checker infer a predicate from a checked condition: let isString = (x: unknown) => typeof x == "string". Explicit Hem-authored x is T, asserts x is T, and asserts cond signatures are refused with HEM2029 because their annotation does not verify their implementation. Imported assertion functions remain usable foreign contracts. For example, Effect’s Schema module can validate an unknown input:
import * as Schema from "effect/Schema"
let uppercase = (value: unknown): string => {
Schema.asserts(Schema.String, value)
value.toUpperCase()
}After Schema.asserts(Schema.String, value), the imported assertion contract narrows value to string. The validator accepts an empty string and throws for non-string inputs. For authored validation, prefer checked narrowing and result values rather than promising an unchecked assertion signature.
This ordinary typed import does not require Hem’s Effect extension.
Use an explicit trailing options object for named options. Hem does not add labels to positional parameters.