6 ms·
Eh it's ok to use `as unknown as X` sometimes If you have complex types, it's sometimes the easiest way to do what you want, and it's perfectly safe as long as
by mpeg 1y ago
Eh it's ok to use `as unknown as X` sometimes
If you have complex types, it's sometimes the easiest way to do what you want, and it's perfectly safe as long as you are 100% sure that the types are compatible.
For example, where you have a fluent-style API where each method modifies the types it's unavoidable to end up using that kind of cast
- aniviacat 1y ago> it's perfectly safe as long as you are 100% sure That was funny to read
- mpeg 1y agoIf you disagree, you're welcome to prove me wrong! To give you an example from a popular open source ts-heavy project: https://github.com/elysiajs/elysia/blob/94abb3c95e53e2a77078bcdd652cd55877b6a697/src/index.ts#L5786-L5826 https://github.com/elysiajs/elysia/blob/94abb3c95e53e2a77078... The `return this as any` there, which effectively casts it to the same type this had, but with the added get route is perfectly safe, it works, and will never be a problem by itself.
- lovich 1y agoIt’s funny because the reason you used a language like typescript is because you want the compiler to be 100% sure that it’s compatible, not relying on human reasoning. If you were going to rely on that anyway, why not just use JavaScript as is and avoid the boilerplate from typescript
- mpeg 1y agoThe code I linked for example results in a web router that is fully type safe. It's not like using js at all, not that I think there's anything wrong with it, if that's your jam.
- horsawlarway 1y agoThis is a great example of "letting perfect be the enemy of good enough". Typescript is "good enough" at it's job. That's a great reason to use it.
- kennywinker 1y agoBecause typescript’s type-checking helps with 99.99%% of the code, and then 0.01% of the time when it doesn’t you use an escape hatch.
- scotty79 1y ago> It’s funny because the reason you used a language like typescript is because you want the compiler to be 100% sure that it’s compatible, not relying on human reasoning. I ever used Typescript because I hoped it would catch some bugs that I didn't (and it did). I never expect it to be 100%. I can't even imagine 100% of what.
- culi 1y agoThe `return this as any` in this codebase was chosen because it was the easiest/quickest route not because it was necessary. Tbh I'm not paid by this company enough to spend time breaking down the correct solution but it would involve validating and discriminating the result of `this.add`. This code is NOT type-safe and will be harder to maintain. Someone will make a change in the future that changes the possible results of `this.add` and TypeScript will not be able to warn you about the consequences of that change.
- matt_kantor 1y agoIt's like how minefields are perfectly safe as long as you know exactly where all the landmines are.
- eyelidlessness 1y agoIt’s not even safe if you’re 100% sure the types are compatible, unless you’re also 100% sure nothing will change that fact. The reason it’s unsafe is because it suppresses the type error permanently, even if whatever factors led to your certainty now change anywhere upstream ever. There are certainly ways to guard against that, but most of them involve some amount of accepting that the type checker produces errors for a reason.
- mpeg 1y agoYes of course the types could change in the future, and the forced cast might cause issues. I wish there was a better way, but this is an acceptable tradeoff. Bear in mind, most changes that could cause issues will still be caught by the type checker in whatever object you're casting to. Obviously it should not be overused where not needed, but it's almost always used in fluent apis because there's no better way (that I know of, at least)
- matt_kantor 1y ago> it's almost always used in fluent apis because there's no better way (that I know of, at least) Got an example?
- mpeg 1y agoYep, I sent one in another comment https://github.com/elysiajs/elysia/blob/94abb3c95e53e2a77078bcdd652cd55877b6a697/src/index.ts#L5786-L5826 https://github.com/elysiajs/elysia/blob/94abb3c95e53e2a77078... This is not the easiest to follow code, but it's very similar to what you'd find in any fluent web router, the idea is that you have say an App class, which has a Routes generic, then on every route you add you compose the return types by returning this as App<Routes & NewRoute>, the thing is in the most simple cases you can probably do this cast directly and it will be fine, but as you add more features (things like extensibility with plugins, ability to merge to other app routes, etc..) you might eventually run into limitations of the type system that require a escape hatch like "as unknown" or "as any" It's not the only case in which you might use it, but I think Elysia is a great example as it does some really interesting things with the type system to provide great DX
- culi 1y ago> For example, where you have a fluent-style API where each method modifies the types it's unavoidable to end up using that kind of cast I think a more concrete example would be necessary but I highly doubt there isn't a more elegant solution using unions and discriminators > it's sometimes the easiest way to do what you want This intention is exactly what leads to unmaintainable typescript codebases imo. Thinking you "know better than TypeScript". TS thinks what it thinks for a reason. Usually that reason is past decisions you made I also don't think it can be perfectly safe. Use a validator if you want it to be perfectly safe