Hoi hoi!
YAY! is-kit just reached 100 GitHub stars⭐ 🎉🎉🎉
When it reached 50 stars, I wrote about how we use it in a production TypeScript applicat...
For further actions, you may consider blocking this person and/or reporting abuse
100 stars is crazy. Well done and love the gif article cover lol. XD
Thank you!! 😹⭐
Honestly, making the GIF probably took me the longest out of the whole article 😹
The Effect catchIf story is the part I'll remember. A refinement quietly widening the error channel to unknown is exactly the failure mode guards are supposed to prevent — and it only surfaced when two libraries met in real code, not in either one's own test suite. The NoInfer fix is elegant, too: the refinement's input shouldn't get a vote on a type that's already been decided upstream.
The discriminatedUnion compile-time checks hit the same nerve from the other side. The type evolves, the hand-written guard doesn't, and the compiler normally says nothing. That drift has bitten me before, so a builder that rejects missing or extra branches feels like the right kind of strict.
Congrats on 100 — the stage where people start filing real edge cases is the fun one.
Thank you so much!! 😸
I really liked that the issue only appeared when the two libraries met in real code, it’s exactly the kind of thing I could never have found by testing
is-kitalone. 😹And yes, the drift problem with hand-written guards is one of the main reasons I wanted
discriminatedUnionto be strict at compile time. If the type changes, I really want the compiler to force me to look at the guard again.Now that people are actually finding these kinds of edge cases, the project is becoming much more interesting for me too. Thank you for reading it so carefully! 😺⭐
Glad the careful reading landed! One more thought on the drift angle: hand-written guards don't just rot when the type changes — they rot when the domain vocabulary changes too, like a new variant getting a runtime branch before anyone remembers to update the guard. Compile-time strictness turns that into a to-do list, which is a much friendlier failure mode. Rooting for 200 ⭐
Exactly 😸 I really like the way you put it as “domain vocabulary” changing.
A new runtime variant can appear before the TypeScript model catches up, or the other way around.
Making that mismatch a compile-time error turns it into something you have to consciously deal with instead of something that quietly drifts.
200 still feels far away, but I’ll keep going. 😹⭐
Yes — that two-way drift is exactly why the compile-time error matters so much. A runtime variant sneaking in ahead of the model is just as easy to miss as the model racing ahead, and in both cases a quiet mismatch is worse than a loud one. Congrats again on 100 — if the edge cases people keep finding are what push it toward 200, that strictness is doing its job.
Exactly 😸 A quiet mismatch is the scary part.
What I want from
discriminatedUnionis basically to turn that drift into a loud failure while you’re still writing code, instead of discovering it later at runtime.And thank you again! If the edge cases people find are what take is-kit toward 200, I’ll be very happy with that path. ⭐
Unfortunately, I can only give one star. 🌟
I hope you reach 1,000 stars soon.
Haha, one star is already enough! 😸🌟 Thank you so much!
1,000 still feels very far away, but I’ll keep going. 🚀
Congratulations 🎉
Thx! 😸
The union changing while its guard stays incomplete is the example I'd keep in the docs. I'd show one added variant and the resulting compiler error right beside it. I'd also pair a coding exercise with that kind of change request: finish the first version, then change the input contract and see what the types actually protect.
Yeah, I think that’s a great docs example 😸
Adding one new variant and showing the compiler error right next to it would make the drift problem very concrete. 👍
I also like the exercise idea, changing the contract after the first implementation is probably the easiest way to see what the types actually protect.
the exhaustive discriminatedUnion builder is the bit that earns its place for me. runtime guards that compile but quietly miss a variant are how we got burned when someone added a third ok state and nothing complained until prod.
refineKey on a guard you already trust beats a hand rolled predicate too. does refineDefinedKey keep narrowing right when the optional key comes through a generic wrapper, or does inference fall back to unknown there?
Yes 😸
refineDefinedKeyis generic over the parent object, so it keeps the caller’s object type and intersects the optional key with the refined type instead of replacing the whole thing withunknown.So through a generic wrapper, narrowing still works as long as the wrapper preserves the property constraint.
We also have
tsdcoverage for generic refinement composition. The main case where you’d lose it is if the wrapper itself erases that property type tounknownbeforerefineDefinedKeysees it.onwards and upwards !!!! Congratulations
And you are becoming a celebrity on Devtv !!!
Haha, I'm happy to be celebrity 😹⭐
Thank you!! 😸⭐ Onwards and upwards! 🚀
congrats GitHub master @nyaomaru ....
Thx! 😸
Congratulations 🎉🔥🔥❤️❤️ My Friend!!!!!
Thx, my friend!!!!! 😸❤️🔥🎉
Next target: 200 stars! Nyaomaru, good luck! 😼
Congratulations @nyaomaru ! 😃🎉
Thx! 😸🤝
Congrats bro!🤩
Thx! 😸
Congratulations 😃🎉
Thx!! 😸