I recently had a chance to finish up a major refactor of the codebase for BFDLang (Bureaucratic Form Design Language), a hefty (and now Turing-complete) language for describing, well, bureacratic forms to web documents. I work at an insurance company, and BFDLang gives the administrative staff the power to describe a form in a spreadsheet and immediately see what it would look like as a web document; it's a powerful, in-house no-code solution for them backed by a ton of code, mostly written by myself and two junior developers. The refactor was huge, and complicated, and I couldn't have done it with JavaScript. TypeScript saved me weeks of work.

If you've ever filled out a commercial form, you know it's just a set of questions frequently broken up into sections, often bordered in some way: Your name, your address, perhaps a former address. For home insurance there might be sections on the existing property, inside and out; previous claims against existing insurance; extra coverage for things like pets or jewelery; bonuses for things like fences, alarms, and fire suppression equipment.

Big Forming Language

BFDLang is mostly about asking questions. Those questions will be collected into sections, and maybe those sections will be collected into higher-order sections. Each question has the text of the question, the kind of input (free form or multiple-choice, and if multiple-choice, a list of the choices), and then most importantly, a set of rules for whether or not the question should even be asked.

This last is most important; bureaucratic forms are absolutely no fun at all, so the biggest idea in BFDLang is to not ask questions that confuse the customer. If the customer is insuring a mobile home, questions about the basement would only be confusing; if the customer is insuring a condominium, asking if they have a two or three-car garage is annoying.

Those rules describe a program. We have a compiler that converts all of these into the elements of an Abstract Syntax Tree (AST); a question's ruleset is turned into an object with functions ready to execute, and a section's ruleset contains child sections and questions, and so forth.

Finally, we have the interpreter that, interaction by interaction, validates customer input and runs it against that AST, producing a new tree we call the Policy Object Model.

The Policy Object Model is a static tree that's pretty ideal for handing off to a web-based library or framework, which then, keystroke by keystroke, click by click, sends events and input back into the interpreter to produce a new POM. This may add new questions, or whole new sections; it may make other questions or sections go away.

The Interpreter and the Input History together create the POM, which the user fills out to create new POMs, iteratively, until the POM's top-level object flags as valid, at which point the customer's application is sufficient to be accurate and binding.

The Refactor

Almost ten months ago, we had a demo to put on for VCs, and the number of shortcuts taken inside BFD were terrifying. A big chunk of the compiler actually ended up inside the ruleset; a big chunk of the interpreter intermingled with the compiler and the rules. It was ugly. It was, sadly, what you do for the VC Dog & Pony Show.

I mention all this because there was an article entitled TypeScript Isn't Helping Anyone recently which convinced me I wouldn't trust this guy to program my microwave. He mentions "ten reasons not to" and then never actually states one. His only real complaint is that "TypeScript limits what can be done with JavaScript. Period."

To which I say, YES! And that's a good thing!.

I did the refactor in very progressive steps. We had a God Object that could both change labels on the fly ("How long have you lived at this house?" vs "How long have you lived at this condo?") and the multiple choice answer collection (states have different rules for some questions, so different answer sets were needed); I statically typed the label field and made it standalone, then did the same thing for the choices, then did away entirely with the God Object. I then removed the compiler layer that was embedded in the ruleset, creating very strict rules for how they were to flow through the system, and finally revised the interpreter, giving it a stack to better manage dynamic answer sets (no more "If you have more than one pet, please add them on one or more copies of Form XYZ-11111").

Each and every step of the way, I thought about what I was trying to say, how I wanted to say it, and to describe those expressions in types.

And each and every step of the way, whenever I found TypeScript "limiting" what I was capable of doing with JavaScript, I discovered that TypeScript was right. My thinking was fuzzy or incomplete. I had left cases and issues underdeveloped.

I found over 180 bugs in the course of the refactor, all thanks to TypeScript. It's entirely possible most of them were "theoretically impossible," edge cases so edgy you'd have to do something weird to trigger one (we have a pretty good test suite, too), but this is a library we intend for institutions that sell loans and leases to integrate as part of "insuring the leased or purchased product" process, and I want to make it difficult for their developers to make a mistake with my library.

Was it frustrating? Only if you find your own foolishness frustrating, which I frequently do. That's why I have tools. That's why I use TypeScript.

Use TypeScript, And Save Your Sanity

BFDLang 1.6 is in a much better place than 1.2 was a year ago. The next really big initiatives with it go in two different directions: first, to take the customer input and, wherever possible, avoid changing the POM object, re-using as much of it as possible, returning a reference-on-remain, copy-only-on-write version with every iteration. This will allow web frameworks to use basic object comparison to avoid re-rendering whole parts of the display. The other is to finish the refinements to the BFDLang itself (the "include this question" rulepack is still messy) so that we can write tools to describe the forms, rather than teach administrative people the little bits of estorica and land mines within. And it would not be in a place where either of these initiatives were possible without TypeScript.