HQL provides TypeScript type annotations and type declarations with two approaches:
|, &, keyof, mapped, etc.)Type annotations use colon syntax with no space after the colon (whitespace is a token delimiter in S-expressions).
(fn add [a:number b:number] :number
(+ a b))
(fn get-count [] :number
42)
(let x:number 42)
(const name:string "hello")
(fn greet [name:string times]
(print name times))
The type tokenizer supports these inline forms:
x:number, x:string, x:booleanarr:Array<number>, m:Map<string,number>x:number|stringx:?number (becomes (number) | null | undefined)x:string[] (becomes Array<string>)x:{name:string, age:number}x:[string, number]x:(a: number) => stringtype keyword (primary)(type MyString string)
(type ID number)
(type Container<T> T)
deftype (backward compatible, also supports string passthrough)(deftype MyNumber number)
(deftype Complex "Record<string, number>")
(deftype EventName "`on${string}`")
(deftype "KeyValue<K extends string, V>" "{ key: K; value: V }")
These compile from S-expression syntax directly to TypeScript:
| HQL Syntax | TypeScript Output |
|---|---|
(| A B C) | A | B | C |
(& A B) | A & B |
(keyof T) | keyof T |
(indexed T K) | T[K] |
(if-extends T U X Y) | T extends U ? X : Y |
(mapped K Keys V) | { [K in Keys]: V } |
(tuple A B C) | [A, B, C] |
(array T) | T[] |
(readonly T) | readonly T |
(typeof x) | typeof x |
(infer T) | infer T |
(rest T) | ...T |
Utility types (any capitalized name) are treated as generic type application:
| HQL Syntax | TypeScript Output |
|---|---|
(Partial T) | Partial<T> |
(Required T) | Required<T> |
(Pick T K) | Pick<T, K> |
(Omit T K) | Omit<T, K> |
(Record K V) | Record<K, V> |
(NonNullable T) | NonNullable<T> |
Intersection inside union and union/intersection inside array get parentheses automatically:
(type T (| (& A B) C)) ;; => (A & B) | C
(type T (array (| A B))) ;; => (A | B)[]
(interface User "{ id: string; name: string }")
(interface Box<T> "{ value: T; getValue(): T }")
(interface Employee extends Person "{ salary: number }")
(interface Manager extends Person Serializable "{ department: string }")
(abstract-class Animal [
(abstract-method speak [] :string)
])
(abstract-class Container<T> [
(abstract-method getValue [] :T)
(abstract-method setValue "value: T" :void)
])
(fn-overload process "x: string" :string)
(fn-overload process "x: number" :number)
(fn-overload "identity<T>" "x: T" :T)
(namespace Utils [
(deftype ID "string")
])
(const-enum Direction [North South East West])
(const-enum Status [(OK 200) (NotFound 404) (Error 500)])
(const-enum Color [(Red "red") (Green "green") (Blue "blue")])
(declare function "greet(name: string): string")
(declare var "globalCounter: number")
(declare const "PI: 3.14159")
(declare module "my-module")
src/hql/transpiler/tokenizer/type-tokenizer.tssrc/hql/transpiler/pipeline/hql-ast-to-hql-ir.tssrc/hql/transpiler/type/hql_ir.tssrc/hql/transpiler/pipeline/ir-to-typescript.tstests/unit/native-type-expressions.test.ts -- 36 tests for native S-expression type operatorstests/unit/type-declarations.test.ts -- type alias and interface declarationstests/unit/typescript-advanced.test.ts -- abstract classes, function overloads, namespaces, const enums, declare statementstests/unit/type-annotations.test.ts -- parameter and return type annotation parsing and executiontests/unit/type-tokenizer.test.ts -- type tokenizer unit tests (bracket depth, normalization, extraction)tests/unit/type-checking.test.ts -- type checking behavior testsSee also: TYPE-SYSTEM.md for additional examples.