menu
/ Florian
3.4k tokens

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++"