I have been reading about Zod which gives runtime type validation.
Is this a good fit to TypeScript and are we likely to see such functionality added to TypeScript?
Now, it's already possible to take certain kinds of objects and narrow their types using plain TypeScript and have all kinds of really solid guarantees about how you're checking the data (and the checks are always going to be as fast as the types will allow, which is great). But Zod is important for being able to take unstructured data and ensure it's compatible with your desired types, in a flexible way, at a cost to runtime speed.
I don't think the Zod stuff is going to find its way into the TypeScript language / standard library. There's very little actual codegen being done in TypeScript (sugar around enums notwithstanding), most of the work to convert it to JS is just checking the types and then stripping them. What you might see instead are improvements to type narrowing.
There are some libraries that provide a cleaner experience (e.g. typescript-is/typia). But they rely either on code generation or extending the TypeScript compiler while Zod just makes do with some clever typing.
TypeScript itself will never integrate something like this as it goes against their design goals[1].
[1] https://github.com/microsoft/TypeScript/wiki/TypeScript-Desi...
But for those who actually want full-stack non-stripped runtime type reflection based on Typescript syntax alone... https://deepkit.io/ - https://deepkit.io/blog/introducing-deepkit-framework - is a really promising and cool project.
It patches the typescript compiler (which pointedly considers runtime type information out of scope) with its own type compiler that emits a bespoke bytecode that is executed in a bespoke VM to communicate runtime type information to both server and client as needed. https://docs.deepkit.io/english/runtime-types.html
And from that baseline, there are very cool things you can do like an ORM entirely based on type annotations https://docs.deepkit.io/english/database.html or strongly-typed RPCs https://docs.deepkit.io/english/rpc.html .
It's very much in the alpha stage, but it's really well thought out - there's a tremendous degree of care the developer is taking towards code cleanliness and developer experience. I'm torn between wishing this project to have a fully funded team and take the world by storm, vs. "letting them cook" so to speak and seeing the developer experience unfold organically. Either way, it's a breath of fresh air into the Typescript ecosystem!
I don't think it's necessary to use Zod/runtime validation everywhere, but it's a nice tool to have on hand.
I haven't heard about Typescript having any plans to generate runtime checks.
No unit testing, no integration testing (as was admitted) and no production sanity test at all. I guess the accountant was asleep at the wheel as well.
You have bigger issues than strong types.
> But how strong and reliable are your test environments to ensure that this all works correctly? How much effort, time, and money does it take to maintain full testing solutions?
Seriously? The entire company revenue depends on counting ad views and you don't have resources to make sure you're counting right? Oh, c'mon!
Strong typing has its place, but this was a bad argument in favor of it...
The resolution of the post mortem was to both add 'an' (they were already set up for it) integration test, and strict typing.
The criticism of the test was that it would only cover that specific path, not others or potential future ones. Which is true.
It could have been one of the many components displaying ads. And this specific component might have accounted for a small percentage of those ads.
And presumably this wasn’t the only feature deployed so any noticeable change in revenues could have been attributed to many other things before a typo in the ID would have been discovered.
It's like the types are one giant unit test for them.
So both of these would have been good, none of them was clearly bad. Notice that you don't necessarily have to choose between these two.
edit: right -> write
Any tool that prevent me from shooting myself in the foot, is appreciated.
Inherent in that is their teammates will not be able to go as fast as them.
For BE code it can take 10 minutes to hours to deploy with debug info, so type errors are a huge PITA and strong types are critical.
Ok, maybe a dev is much faster writing JS because they keep stuff in their head better. But I’m assuming they also use third party libs, or functions that other devs in their team have written that they just need to call.
Typescript makes it easy for the IDE to show you what exactly you need to pass to call the teammate’s function (and this was the originally motivation behind typescript…improving MS dev tooling) without having to dig into the code or read the documentation.
And type inference means you’re rarely actually writing out the types. So I find it hard to believe that anyone writing a relatively complicated piece of code would be faster using JS over TS.
Small scripts and the like, sure. But complete complex applications? I doubt it.
Disagree. `any` is important for incremental adoption, not having it would just make it harder to introduce type-safety to a codebase.
The thing with type safety is that systems like typescript are so easy and cheap to deploy, relative to E2E or even unit tests; it’s a small investment that pays off in multiple ways over time (quality, documentation, developer onboarding).
I really struggle to understand the sometimes vehement arguments against it.
Most developers would need to wait until all browsers support it, and the vast majority of users use it, and you could easily be looking at a decade of lost opportunities while you wait for that.
That said, in a world of impending WASM, I don’t even know if TS on the browser makes sense. It seems like it won’t be long and we won’t need a JavaScript intermediary between TS and the browser at all.
We found that our E2E tests took way too long to write and didn’t really cover the visual defects we often hit.
I think our BE engineers are surprised by the lack of testing while at the same time rare runtime exceptions.
We have enough critical flows tested and with TS to prevent runtime errors, we have a decent degree of confidence.
If only we had a good way to test webauthn…
I absolutely abhor the the trend to accept that this is OK. Your code shouldn't generate warnings and the build system should treat them as errors.
The only difference between a warning and an error is if it's ignorable to still proceed to execution. If it isn't it's an error, if it is, it's a warning.
If all warnings should stop builds then they are no longer warnings. And to be clear you can argue that point - that there shouldn't be such a thing as a warning. And that's a fair argument to make (regardless of if I agree or disagre), but saying "the build system should treat all warnings as errors" isn't really coherent.
Warning is the compiler saying that yes, he understands but you're probably doing it wrong.
Unused variable. Yeah, legal. But why?
Most code that generates warnings can be written in a way so it doesn't. For the rare extreme nonsense warning, deactivate that warning with a comment and justification why to the next reader.
Because if you don't treat warnings like errors they become just a background din.
> ... isn't really coherent.
It's supported by many compilers and isn't a new idea.
They included a tag that included information that was to be passed to that other system, to indicate that this tweet was billable.
Presumably the tag was optional, the tag was just misspelled, so everything appeared to work just fine.
It’s the downstream systems that cared about this tag and they were presumably not even running on the dev machine on which the offending code was written.
The only thing that could have prevented this was some kind of schema that would have rejected an unknown tag at build time. Hence, typescript.
> This property was then used when logging visible Tweets that it was in fact displayed. It was a relational ID that told the backend systems exactly which Tweet from which advertiser was being displayed.
It was supposed to be storing these IDs. Did nobody think to test that the thing was, in fact, storing IDs? Especially for something that puts hundreds of thousands of dollars on the line? Even if you're actually passing that value off to some 3rd party system somewhere, you can verify that this slice of your problem (the React component that receives a prop) is doing its job properly. Even if that means stubbing it to log locally. Something?
I'm not against strong typing. Just saying this is a bad argument in favor of it.
Tests and Types are useful for preventing errors, but the types of errors they can prevent differ. You probably need both!
What's more, though, is that a good type system will help you 'Make Impossible States Impossible'[0]—even more behavior you don't have to test because bad behavior is simply not representable in your program.
Tests are strictly more powerful in the small, because they can be arbitrarily complex, but I would say a (really good) type system is more powerful in the large, because you get way more leverage in terms of overall program correctness.
A lot of my personal projects are in Elm (yeah, yeah, bring on the hate)—the models are really well-defined, but the test suites usually only have a handful of tests of behavior I really want to verify. Haven't even played with the property checker yet, but again, that's something that is strictly more powerful than unit tests, but you can only get it* if you have a type system.
[0] https://www.youtube.com/watch?v=IcgmSRJHu_8
* Okay that's not really true: see clojure.spec in Clojure—but there are so few counterexamples that it's true for most practical purposes
> The `any` type was a mistake and never should have been included in TypeScript in the first place. It is disappointing to see the number of published libraries that embrace `any` types, making it difficult to verify with certainty that code is correct.
`any` is a consequence of TypeScript being JavaScript under the hood. Is `unknown` a better type to use when you're not sure what something might be? Sure, the fact that TypeScript forces you to carefully pick apart what it actually is by guiding you through the appropriate type narrowing is great. But sometimes you actually just want to write some code and sort out the types later, especially when you have a lot of interfaces that came from JS or from an only partially converted TS codebase that would otherwise be full of `as unknown as T`.
I think the only mistake here was allowing the `noImplicitAny` tsconfig option to be off by default. When TypeScript can't figure out what a type is and that setting is off, it just decides that the type is `any`. But when that setting is on, it's an error to not explicitly state the type, even if you explicitly state it's `any`! Then any usage of `any` is explicit, auditable, lintable, etc. and then it's much less of a problem to use effectively.
Because of JavaScript (godblessit), there are many things that were written in a way that makes types difficult to implement. I work on Ember codebases and, while some of my colleagues who happen to work on Ember probably would disagree, there are things about the way it lazily resolves things makes it extremely difficult for everything to be typed properly without lots of recasting and bureaucracy that wouldn't have happened had the whole thing been written in Typescript from the very beginning. Typescript in Ember will always be a shitshow because of this design flaw that was encouraged by the era of JavaScript it was spawned from.
Nevertheless, we shouldn't replace things that are otherwise working just fine, hence it's better to just accept that some things are going to be "any" or "unknown" and deal with them properly.
> Because there was no real error, just a warning, this issue went into production
If you don't at least parse a new warning to figure out what causes it and decide why it's okay to ignore in this case, there's your problem. Types are fine but if this is the lesson you took from that, you learned nothing.
It's nice that the author puts their main reason for using this particular tool up front: they want to make money. But wanting to make money is not necessarily correlated with the use of TypeScript, JavaScript or any other programming language. And it misses that 'wanting to make money' even if it does correlate with the use of TypeScript would still be a preference.
Finally: what's missing from the story about the typo is why there wasn't a system around all of this code that would notice that a particular KPI's relationship to another KPI came in wildly outside of the predicted range. Obviously: typed languages are great, but typos can happen in any language and such a defense-in-depth strategy against silly mistakes will benefit you regardless of the kind of language that you use.
Awaiting the 'we use Rust because we want to make money' blogpost that is sure to follow.
I will put my conclusion first: as an industry, there is so much room for real research and understanding in what does and doesn't work in reducing defects. However, this itself is a pretty difficult problem because of the difficultly in tracking, quantifying, or even defining what a "bug" is.
Until we have that data/research, any conversations about type systems vs testing vs process vs monitoring and saying which is "better" I think very rarely changes opinion and is more likely just to reinforce opinions held by different groups.
That isn't to say this article isn't useful, it is a good real-world perspective of things that do happen. I think the problem is that something about most of our brains (either in the writing or in the reading) causes a huge portion of us to immediately look the issue with such absolutes that most of the learning/discussion that could be had are drowned out through disagreement about the basics.
So in an attempt to try and hopefully start a discussion that goes beyond the argument about the value of types, I would love to learn about any research/products/ideas/success stories of how we as an industry can make software more resilient?
In my (limited) research over the years, it seems like a lot of the research is often limited to a single company (MS did a lot of measurement in the past) or looks more at the people aspect and less at the tools/technology.
I would think that LLMs might make some analysis, like measuring the impact of bugs, more tractable as I think an LLM could probably do an okay job of assessing the real impact of a bug (assuming there is a post mortem doc) better than just having a label like "major" that determines impact. That, combined with some okay understanding of the code that fixed a bug, could maybe help give a more complete understanding of how different tech/process/team structure impacts defect rates?