menu
Introducing TypeScript++
Evolving TypeScript into the Last Programming Language
- there is a lot of software, and there is about to be a whole lot more
- most of it is not very good
- slow, buggy, clunky
- dependency sprawl
- supply chain attacks
and now we're asking even more from our software than ever before
not really hackable
not really visible / homoiconic
unfortunately, merely regurgutitating the software we already have isn't going to be great
produce much more software than any one could ever meaningfully review
so, how does one build correct, optimal, integrated software?
if software is so cheap, why can't we make it really good?
if we can quickly and cheaply rewrite software from and to any language, where do we end up
switching costs near zero, incremental adoption eventually becomes less important
where do we want to end up?
what characteristics would the last language have?
would it look like an existing one, or something totally different?
Higher Order Programming
the history of programming is one of monotonically increasing levels of abstraction: from handcrafting gears, to wiring up vacuum tubes, to punching cards, to coding assembly, to writing C, to programming Java, to scripting Python, to asking an LLM to script Python.
climbing the ladder of abstraction yields more output for every bit of effort
so we gradually remove ourselves from the cumbersome burden of having to actually spell out exactly what we want the machine to be doing: which electrons? which bits? which registers? what memory? what computer? where computer? when computer?
it follows then that we might want to go all the way, that the ultimate sophistication of programming is not programming at all, but more like "talking to a colleague"?
oh, how great software could be, how magnificient, how accessible, if only we could make programming as simple and unconstrained as natural language?
if we didn't have to write code at all, nor trouble ourselves with any of the nuances and rigor imposed by formal languages!
one can only imagine the splendidness of an ecosystem of unconstrained creation!
fortunately, magnificiently, we already have precedent to understand what that low-code, high volume engineering evolves into: game development!
- as many nerds will know, early on, game development - even more so than software development - was a complete dredge, and only a self-selected guild of turbonerds could pull it off successfully.
then, eventually, the nerds figured out how to package the hard bits into reusable components and evolve more complete, higher level packages of reusable software components we call a "game engine".
initially, when using an engine, maybe you didn't always get exactly the same level of control, or even hit quite the same highs as the best hardcore engineers.
but it was a lot more productive, and it enabled a scale of project
better tools also enabled more people like game designers, writers, and artists, .. to more directly contribute to the game (visual scripting, material editors, ..)
so:
lot of the time is just iterating in some more interactive editor
sometimes you "play" the game, sometimes you edit the game, sometimes you build new tools to help you edit the game
continuous granularity
reusable parts, "asset stores" (ShadCN), ..
it's all part of the game
Long Live Code
"coding is solved" ("bugs not solved yet")
well, define "coding", define "solved"?
if we increasingly work through other tools, why invest in a language?
it's a fair question though: why should we even think about code at all if it can all be written by AI anyway
in some sense, this is like asking we care about numbers when calculators exist
what even is the point of code? why did we ever write code in the first place?
code, in itself, is inert and useless
nobody really wants code much like nobody wants software or computers in and of themselves
the code is not the product, and usually the software is not the product, either
- as long as there are humans involved at the edges and on the sign off, we need some common ground
- programming is about problem solving, about iterating on a solution and then formalising it in a repeatable form.
- in the olden days, we used to solve problems with artisinal human-directed next-character-prediction, now we can often work at a higher level.
- I want to know, what is the space of all possible software programs to solve my program, and how do I most efficiently get there, where do I go when I'm there, how do I stay in the right place, and so on
- abstraction, yes, but not purely abstraction of specification, also abstraction of exploration, with full specificity available on demand
- I've tried that, it doesn't work, I don't want to do that
but we must still understand, or the software sits in some weird disconnected castle in the sky that serves nobody
(well over a year of "vibe coding" has shown this pretty concolusively)
if programming is really just about problem solving, and code is just one medium for formalising solutions, we should expect to see some other evolved forms at varying levels of abstraction
indeed, spreadsheets have worked for decades, game dev people have been doing this for a while, we have now figured out a new way to prompt simple software into existence
historically, when some more "accessible" programming-ish becomes too common, the "real" programmers no longer consider it programming. thus, excel is not "programming", just like image classification is not "AI"
and of course, there is the trivial but important point that we're already not writing most code ourselves - the OS, standard libraries, dependency ecosystems, some compiler/transpiler is writing the actual low level code for us, ..
old adage that a complex system that works starts from a simple system that works
in any non-trivial systems I have seen, there is no useful separation of the system and its "specification"
sometimes the exact sequence of steps matters, sometimes it does not
the granularity of the specification to care about depends strongly on how standardized the solution is.
- every attempt to put something purely "above" code and then have it define the behavior of the software with sufficient specificity ends up reinventing code in a worse way (config languages, Gherkin tests, drag and drop coding tools, "APIs will replace everything", etc.)
System Scaffolding
- a new kind of user is coming online, and there is a lot of excitement about "agent first design"
- a myriad of developer-adjacent tools are being rebuilt to become "agent native".
- It's not entirely clear what "agent native" means, beyond good APIs, high performance, open standards, which all just sounds like building software in the way we should have done anyway.
- most things that are "good for agents" - fast iteration, clean boundaries, programmable software - are good for humans too, we just haven't had the opportunity to the big rewrite until now
- like with every technological shift, what are the new abstractions, what is the new shape of software and how do we get there?
our tools for building, interacting with, understanding software are pretty primitive
if everything is code, how do we make sure it's the right code?
"oh just have the AI tell you if the code is right" but again what is right?
(in this sense, the "alignment problem" feels much more like a product and legibility problem, and certainly not merely an intelligence problem, which is short term bearish but long term very bullish)
this does not magically go away with more abstractions or "smarter AI"
understand the shape of software and the space of all possible software
make a map
much better static and dynamic analysis
"software in motion"
code is going to run everything, even more so than it already does (literally)
fundamentally, there is not a single test, suite of tests, mathematical proof, or any other final gate that you can run to convince me that some non-trivial general program is correct
(mathematical proofs are ofc very useful for rigid and fully formalizable systems)
doesn't matter whether it's human written or not, software is just very complex
and the only way to assess "correct" for any interesting software is to see it in motion under many different angles, over time
- I don't know what I want until I see it, and I also don't know what I don't want until I see that too
- correctness is an iterative process, alignment is continuous, the shape is changing
- "correctness" must be specified acrosss many layers to systematically exclude all the things we do not want
- incremental, iterative, multi-level precision
- alignment requires visibility, we cannot align what we cannot see
- need a common vocabulary
- correctness is much more iterative, squishy, and multimodal than some cold mathematical proof
- (especially as we get into squishy computation!)
- visibility and precision must be built on a solid foundation, incrementally
- precision requires looking systems..
- .. from many angles, in detail, high low, statically and dynamically, in motion, statically, all sorts of dynamics, ...
- you can't engineer precision and alignment (i.e. understanding) into a system post-hoc (or at least, only with great difficulty that far exceeds the cost of doing it properly from the start)
Boring Software
- there is something beautiful about doing the most with the fewest possible parts
- in programming, a minimal, simple language like C or even Go is elegant, the least parts to get the most done, with deliberate "no" to the last 20%.
- even "multi-paradigm" languages like Java or C# that have organically accumulated more systems-y features over time do not (attempt to) cover the complete spectrum
- (though very few people would have called either "minimal" at the time they were introduced)
- boring software must mean complete software, an integrated stack, since that has fewer parts.
- tremendous advantage to using a single language for everything, as shown by the popularity of e.g. TypeScript monorepos (suboptimal though they are in various respects)
- if software is going to become even more ubiquotous, how do we fill thos elast 20%
- TypeScript is a great foundation
- there is already wide range of prior art in the realm of "TS ergonomics with systems performance", but that is just one aspect of what we'Re trying to do here
- static hermes, assembly script, ...
- all in - not incrementally adoptable.
- (though we do have C ABI ofc)
what is the ideal final system?
it is very tempting to get a blank piece of paper and dream up the "perfect system"
but it probably does not matter per se
pragmatic perfection
I don't want to learn a new and totally different language, I already know the ones that exist
I like imperative programming
I want to use the Web, basically TypeScript, and build with stuff I'm familiar with
I want to use what I already know, with minimal new learning
Predictable, known behavior - even if imperfect - is better than something totally new, theoretically perfect thing
(besides, we usually figure out that the grass isn't quite greener anyway..)
the current set of modern programming languages is pretty good
colored functions are fine, Promises are fine actually. microtasks a little weird but whatever
number is okay as a type actually, it's convenient
bigint and string as lowercase primitives are fine, not ideal, but fine
all in all, it's fine, and most importantly: it's familiar
(... and it's how the web works!)
no intention of "fixing" anything that is sound but clumsy and can be trivially linted for
more importantly, want a complete language that can represent all the things we need, and then constrain by package / library (but it all has to go togetheraaa)
so let's just get on with it
what is the minimum edit distance from TypeScript to a universal language that keeps TypeScript's ergonomics and familiarity, is strict and sound and analysable, and also runs reliably at machine speed?
basically, what is "TypeScript++"? TS that runs predictably like JVM/CLR/Go with som Rust-y bits
the question is explicitly not what is the "best theortical version if we did TypeScript all over again".
instead: "what is the most typescript we can make it, removing only what is absolutely necessary" (default decision = keep)
what's the most boring thing we could build?
don't try to be cute or clever or fancy
no "improvements", only corrections
don't "fix" what's not actually broken
only use boring ideas already proven by other languages / libraries / ..
safe, sound, predictable, and above all: familiar
TypeScript++
- TypeScript is already tantalizingly close to being a serious, native, universal programming language
- the dichotomy between "scripting languages" and "systems languages" no longer makes much sense if it's not humans doing the typing (assuming "compile times" are fast)
TS++ fashions itself as a "superset of a strict subset of TS", which is vaguely reminiscient of the relationship between C and C++
mechnically, what is the ergonomic ladder of TS++ between TS -> Rust, what are the minimal things to remove for unsoundness, and the minimum features to add to cover the whole universal language spectrum
there are a lot of interesting details details in making "TS++"