Zihan Weekly 2: HOTScript - Higher-Order TypeScript
19 Feb, 2023TypeScript is amazing. The flexibility its type system is providing is just so powerful and I just noticed a project call
const str = "10"
type n = Call<Strings.ToNumber, typeof str>
// ^ = 10
Too simple? Let’s look at another more complex one:
type shouldBeNinetyFive = Pipe<
// ^ = 95
[1, 2, 3, 4, 3, 4],
[
Tuples.Map<Numbers.Add<3>>,
Strings.Join<".">,
Strings.Split<".">,
Tuples.Map<Strings.ToNumber>,
Tuples.Map<Numbers.Add<10>>,
Tuples.Sum
]
>
Yes, we are using functions in TypeScript! This looks so cool. But how does it works under the hood?
We have a interface Fn
which has some args and an output type, plus a Call
type:
interface Fn {
_args: unknown[]
output: unknown
args: this["_args"] extends unknown[] & infer args extends any[]
? args
: never
}
type Call<fn extends Fn, args> = (fn & {
_args: args
})["output"]
Just try to understand the code. The _args
and args
are just a trick that makes sure the args are what we are passing into it, without unknown[]
.
And here are two Fn
s implemented:
interface Join extends Fn {
output: [...this["args"][0], ...this["args"][1]]
}
interface StringToNumber extends Fn {
output: this["args"][0] extends `${infer n extends number}` ? n : never
}
Each of the functions takes the args
provided and gives an output type. Now we can use these two type-level functions like this:
const a = ["Hello"] as const
const b = ["world"] as const
type joined = Call<Join, [typeof a, typeof b]>
// ^ = ["Hello", "world"]
const str = "35"
type n = Call<StringToNumber, [typeof str]>
// ^ = 35
It’s working! HOTScript looks so great and I think it’s absolutely going to be a big deal in the future.
Projects
Create libraries without pain! Just use one of these commands according to your favourite package manager with amazing experiences!
Trust me it’s really nice!
pnpm create zihan-lib
npm create zihan-lib
yarn create zihan-lib
Articles
deno_core
. It looks pretty cool and I am thinking that maybe I should try it out.