6 ms·
Using TypeScript for the entire stack feels like a superpower. The type system is incredible. V8 is fast. The frameworks are phenomenal (Next.js, Material UI, e
by a_wild_dandan 2y ago
Using TypeScript for the entire stack feels like a superpower. The type system is incredible. V8 is fast. The frameworks are phenomenal (Next.js, Material UI, etc). The ecosystem is enormous, with packages for everything. The unified codebases save gobs of duplicate code (e.g. ferrying data betwixt client/server). I'm not surprised that such an expressive system can play Sudoku!
- sva_ 2y ago> with packages for everything Which can quickly turn into a crutch if you're not wise about it
- brigadier132 2y agoOne thing I do when I see a dependency I want to use is get its github and paste it in this site: https://codetabs.com/count-loc/count-loc-online.html https://codetabs.com/count-loc/count-loc-online.html Depending on the # of lines of code and how many people use it actively I decide between just * forking it and using the fork as a dependency * copying the parts i need from it * or just using it as a dependency Either way, the dependencies existing is just a boon. Even if you don't want to depend on it directly you can use the existing work as a guide and implement something yourself.
- leononame 2y agoFor me, it's the opposite. The type system is decent, but it's generics can get extremely out of hand, it's not sound, and I run into weird type errors with libraries more often than not. Having no integer types (ok, this isn't something typescript could just implement) other than BigInt is another big one for me. That you can just do `as unknown as T` is an endless source of pain and sometimes it doesn't help that JS just does whatever it wants with type coercion. I've seen React libraries with number inputs that actually returned string values in their callbacks, but you wouldn't notice this until you tried doing addition and ended up with concatenation. Have fun finding out where your number turned into a string. The number of times I've read `... does not exist on type undefined` reaches trauma-inducing levels. TypeScript is as good as it can get for being a superset of JS. But it's not a language I have fun writing stuff in (and I even fear it on the backend). It has its place, and it's definitely a decent language, but I would choose something else for frontend if I could, and wouldn't use it on the backend at all. I somehow don't trust it. I know people write amazing software with it, but YMMV I guess.
- carderne 2y agoI tend to agree with you but for problem like this one: > That you can just do `as unknown as T` is an endless source of pain You should be using strict typingcheck/linting rules somewhere in your pipeline to make these illegal (or at least carefully scrutinised and documented).
- ridiculous_leke 2y agoThose rules should be enabled by default.
- moritzwarhier 2y agoESLint rules that require type information (not just stripping types) are prohibitively expensive for larger code bases. As far as I know, there isn't any kind of tsconfig rule to disallow this (please correct me if I'm missing something here!). So unless you're using tools I don't know about, this is kind of a mandatory last bastion of "any". You can disallow any, enable the strictest possible null/undefined checks (including noUncheckedIndexedAccess). And there's also the assertion TS check that normally prevents erroneous type assertions. But "as unknown as MyType" is not preventable by means of tsc, as far as I know. Unless there's an option I don't know do disable this kind of assertion (or even all assertions).
- lolinder 2y agoHow large is too large and what counts as prohibitive? We're using lints with types on over a million lines of TypeScript and the lints are instant inside of the editors. They take a good 10 minutes to run in CI across the whole project, but that's shorter than the tests which are running in parallel.
- moritzwarhier 2y agoGood point, I was talking about similarly sized code bases, yes. Because of the hefty CI runtime increase, myself I opposed to adding it. We have lots of parallel branches that people work on and many code reviews every day, where the CI just needs to run from a clean slate so to speak. But most of the current long CI run penalty in the frontend of that comes from tsc, not ESLint, in my case. I might look into it again. In the project there already are all kinds of optimizations (caching to speed up full Ci runs with common isolated parts of a monorepo). And for TS, project references + incremental builds for development are used, tsc in a monorepo would be miserable without them.
- harha_ 2y agoTypeScript is overly complicated and for what? Compile-time "safety". It's better than plain JavaScript, though whatever library I pull as a dependency and peek inside the TypeScript<>JavaScript interface glue, I always find horrors beyond my comprehension.
- mynameisvlad 2y ago> the TypeScript<>JavaScript interface glue … the typing file? That’s literally the only thing that’s different and if the original codebase was written in TS then is literally the types they defined.
- harha_ 2y agoWell either the typing glue or the library itself if it's written in TypeScript. My point was: the types are too damn complicated. Way too complicated for what they achieve. Almost always.
- xamuel 2y agoCompile error messages in a classical typed language: "Error: Object of type 'StructA' cannot be assigned to variable of type 'StructB'" Compile error messages in TypeScript when you use a library like React: "Error: Cannot reconcile <5 pages of arcane gibberish> with <5 pages of different arcane gibberish>"
- SonOfLilit 2y agoWhile TypeScript seems to be a nice language, it's ecosystem is the JS ecosystem and it is madness. Major versions of some common library breaking backwards compatibility released every week mean you need to run as fast as you can just to stay in place. Public opinion can't be relied upon. The most popular ORM library just recently added support for native JOINs, and this wasn't common knowledge (I almost used it before at had them!). The most decent ORM as chosen by some coworkers very experienced with the ecosystem still doesn't support subqueries (well, there's an escape hatch for writing them in raw SQL...). Some marketer-turned-programmer created hundreds of useless packages (like, a separate package per ansi color) that all require each other, and they are popular enough that if you'll run npm ls in your real world project you will find that you depend on them. Having professionally used cargo, pip, even cabal, npm feels like the eternal september of open source packages.
- yieldcrv 2y agoyeah this part is pretty bad you can get lucky and reach a nirvana state where all your dependencies function well in a new project, but 6 months later its a disaster like ah you need to upgrade node, but ah your transpiler requires the older version of node, but ah the semantic versioning was not followed by your type definition addendum library and now there were autoupdated breaking changes, ah your project only worked with a locked package file and if you re-install any package the wrong way everything breaks in incomprehensible ways! I know my way around it though, so yay big bucks and quick deployment of greenfield projects
- space_crab 2y agoI know this isn’t realistic for many many scenarios, but if you can help it there is a sweet spot where you dedicate ~30 minutes to merge weekly dependabot updates and you don’t run into this problem.
- lolinder 2y agoMost of the madness that you're describing there isn't inherent in the JavaScript ecosystem, it's more to do with undisciplined development practices that might be more likely to be enabled by JavaScript's flexibility but are by no means required in order to participate. Don't use libraries that aren't stable. Aggressively trim dependencies. Lock versions and upgrade intentionally. Ideally, use a company registry to cache what you actually want to be using. Every ecosystem has its problems, and JS+NPM's are largely that it's too good at making everything too easy, leading to an abundance of naive developers building in a naive way. On the whole I'll take that over the unnecessary barriers in other ecosystems (don't get me started on pip...), but it definitely requires some discipline to navigate safely.
- __jonas 2y agoI had this thought with a personal project but I got lost in a nightmare of configuration between typescript, node, the browser, my bundler etc. Maybe it’s a better time with a framework like Next, which I assume comes with the client / server code sharing part preconfigured, bun looked promising as well to simplify the development setup. But I ended up switching to another language for my backend and I feel pretty good about it.
- beezlewax 2y agoBetwixt? Hello thePrimagen
- rpmisms 2y agoI would have agreed with you once upon a time, but I'm building a project in Laravel right now. You want superpowers? Do a week's worth of fullstack JS in an afternoon with Laravel.
- pjmlp 2y agoOnly when those types actually could be used by runtimes, to catch up the the various JVM and CLR implementations. There is no more juice left to squeeze in JavaScript, as it stands, beyond heroic efforts. I rather stay with JVM and CLR languages, and only reach out to the node ecosystem, when SaaS products leave me no choice in regards to SDK support. If Typescript is to never leave the role of being a linter, and a down version translator, eventually we have to ask ourselves when is Typescript done, instead of being an intellectual exercise for the sake of it.
- saagarjha 2y ago> Only when those types actually could be used by runtimes 'pjmlp you do know how Java does generics right?
- pjmlp 2y agoAt least those have Valhala on the horizon. And lets not pretend Java is like JavaScript if that is your point.
- drewhk 2y agoThe problem with generics type erasure is less of an issue though in practice because the ecosystem is generally compiled from typed code and hence the compile-time guarantees reduce the dangers of erasure. This is unfortunately not true in TypeScript where you encounter plain JS all the time (sometimes TypeScript wrappers of dubious quality) causing more havoc. So while _theoretically_ type erasure could be considered having similar problems, in _practice_ it is much more manageable in Java. I guess if the whole JS ecosystem would be TypeScript only it would be less of an issue there as well, but right now it can be messy.
- drewhk 2y agoOne more addition, there is a subtle but very important difference between how TypeScript's "erasure" works compared to Java's. In the case of Java, an explicit cast is emitted in the bytecode, which upon execution checks the compatibility of the actual runtime type with the target type during runtime. Yes, this makes it a runtime error compared to a static bytecode verifier/compiler error, but the behavior is well defined and the error does not propagate further from the original mistake. In comparison, Typescript does not emit "verification code" at the casting site ensuring for example that all asserted fields exist on the runtime object at that point. The result of this is that the type mismatch will be only evident at the point where for example a missing field is accessed - which can be very far from the original mistake. If you wish, you can consider type issues caused by Java's erasure as runtime, but _defined behavior_, while in TypeScript it is kind-of undefined behavior that can lead to various error symptoms not known in advance.
- afavour 2y agoI agree about TypeScript as a language but I’m very burnt out on the various JS frameworks. They’re all so bulky and heavy. I like feeling as though I’m close to the end product and the average React codebase is a pile of abstractions trying to push you away from the underlying APIs.
- sureglymop 2y agoI agree with you. If I develop for the browser, I'd like to use browser APIs. If those browser APIs are too complex for me to use without abstractions, that's another problem in itself that has to be addressed separately.