My avatar
Blog post cover image

Zihan Weekly 2: HOTScript - Higher-Order TypeScript

TypeScript is amazing. The flexibility its type system is providing is just so powerful and I just noticed a project callHOTScript(Higher-Order TypeScript) which allows us to make type-level functions. What does this mean? Let’s see how we can use it.

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 Fns 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 Zihan Lib

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

Dependency cruiser: Validate and visualise dependencies.

Articles

So, what’s next?: The creator of Core-js shares a complicated story about the challenges he’s faced while maintaining one of the most ubiquitous OSS projects in the world. This topic requires more nuance than we can give it here, but it highlights some of the challenges of funding OSS — especially for lower-level packages.

Roll your own JavaScript runtime: Deno shows us how we can build our own toy JavaScript runtime with Rust and the crate deno_core. It looks pretty cool and I am thinking that maybe I should try it out.

Try out CSS Nesting today: CSS Nesting is now available in WebKit.

Web Push for Web Apps on iOS and iPadOS

Well-known Symbols: JavaScript’s 14 Symbols and where they can be useful.

Rethinking the Modern Web: To be honest it’s quite long so I don’t think you should read through it all.

Videos

Others

Vue Amsterdam 2023: This time it’s more about Vue’s ecosystem.