Hacker News new | past | comments | ask | show | jobs | submit login

11. Going down the rabbit hole spending three whole days getting your typings perfect for some weird use case, instead of writing actual code. Sometimes there's a benefit down the line to having done it, often not, and knowing the difference is where greatness lies.



This is definitely something that typescript constantly lures you into.

I recently switched back to JS for a prototype of a programming language.

I immediately felt more productive.

At times, the TS systems feels like a theorem prover. Until it doesn't. And then you're left with a bunch of types that almost do what you want... but not quite; Always tempted to experiment again for a day or two.

But let's see what happens down the road. Maybe I'll miss the incidental documentation the typings provide.


I used to think this way too, but working over the years with TypeScript has gotten me so accustomed to it that it’s now the other way around. I feel much more productive in TS in general.

With TS its like you’re writing the unit test and your code at the same time, and if your types are expressed well enough you can also skip the compile+run+verify step.

I’ve had cases where I would spend days just writing code, refactoring and iterating, without building the project once, compile it at the end, and have a complex feature work correctly on first try, passing all the functional tests.

It’s like I have a pair working with me constantly compiling my code and pointing out syntax and interface errors while I concentrate on the business logic and big picture stuff.

When I go back to JS it’s as if I now have to do all that manual labour too, as well as constantly write and run unit tests myself to make sure what I write actually works.

Though it definitely took some time to get this comfortable with the TS type system.


Perhaps much like the parent, I want to create without the foundation of TDD or unit tests, so I find the mixture to be expensive in the cases I'm typically working.


One of the things I learned, not from TypeScript but from other languages with type systems that work similarly, is to minimize the use of type decorations and let type inference do most of the heavy lifting.

It took some getting used to because things end up a bit less obvious, but I found that with the IDE's syntax highlighting capabilities, actually inspecting the inferred types isn't as much of an issue. And then you spend less time typing out type names.


Huh. I recently built a language parser in TypeScript and it was a very positive experience. As just one example, discriminated unions for AST nodes worked great.

Always tempted to experiment again for a day or two.

Maybe that's it. I've never felt bad about settling for 95% of the benefits of static typing and slapping any/unknown on the edge cases.


For my company production code I definitely spend way too much trying to implement the correct types, however for side projects and MVPs I do quickly what I have already learned or just sometimes if it's too complicated I'll just go with "any" styled solutions or similar things. I think using TypeScript flexibly for prototypes helps me do that "first compile test" will work out of the box very easily.


This isn't a fault of TypeScript, but any language. Trying to predict the future, trying to predict and eliminate technical debt, in a rapidly developing product.


But it is the fault of TypeScript for having such an obvious path for falling into that trap. Part of what it means to have TypeScript code is to have typing files.

Part of good language design is attempting to minimize bad programming habits. In this case, a language with a HM type system would avoid the issue all together, while affording the same productivity gains from having static types.


This isn’t actually a fault of TS, it’s an explicit goal. They design the type system not to guide usage but to make existing usage explicit and trustworthy.

The places where the type system encourage rabbit holing are almost always where bad types/APIs are already prevalent. Where you’re starting at the type level and don’t have an inclination to allow all manner of dynamic nonsense it’s not that different from types in an ML-family language.


Don't treat types as theorem provers, treat them as formalized docs - getting dirty with dynamic under the hood is perfectly acceptable to me (say you're doing some metaprogramming - typing that out is usually a lot of effort for low gain) - the types just help define intended use.

In code consuming types I relie on inference 80% of the time, sometimes I need to specify generics, if it fails I do dirty casts, if that fails I do dynamic blocks.


Yeah, see how it goes when your system gets past about 20kloc. In my experience working without types starts out great but you soon hit a wall.


Hello, my name is Ari and I'm a type addict.

Thankfully, the impulse to waste time trying to come up with the most precise typing possible for everything hasn't been as strong with TypeScript as it used to be with Haskell for me. In part that's because TS's type system is so ridiculously expressive that I can say what I want to say without spending too long on it anyway, in part it's because the system's proud unsoundness and the ability for typings to simply be wrong means that I know not to stake my life on the types anyway. Besides, in my experience, the more precise I try to make the types at an interface, the more I need to cast in the internals. Better to find a balance that keeps both reasonable.


> the more precise I try to make the types at an interface, the more I need to cast in the internals

Isn't that exactly why you use types to begin with?


Absolutely. One of my strongest opinions about TS is that you should use it pragmatically. It's not worth burning hours of time trying to placate the TS compiler if you know the code works okay - throwing in a `type $FixTypeLater = any` and moving on is an acceptable workaround depending on the situation:

https://blog.isquaredsoftware.com/2019/11/blogged-answers-le...


“as unknown as MyType” usually works almost as well and avoids throwing you out into the cold untyped darkness.

I also try not to let any escape function boundaries.

Recast it to something better when returning something.


> “as unknown as MyType” usually works almost as well and avoids throwing you out into the cold untyped darkness.

No it doesn’t. You’re casting to `any` and hiding that fact. Both top types can be anything at all, `unknown` is only safer if you narrow it to something else by testing it. If you cast it to something else you’re just treating `unknown` as `any`.


On the other hand, most of the time I'm willing to put in a little effort to express the desired types, since it dramatically improves the intellisense suggestions, making code edits / refactors much less of a mental burden.

But yeah, sometimes you hit a wall and need to do something unsafe.


It all has to do with refactoring. And new people coming into the project. True fact: One day (or another), it happens.


I was on a project-from-hell once where the project lead cared far more about getting types perfect than allowing the code to be, you know, useful.

If we couldn't do something 100% type-safe then we weren't supposed to do it at all. I kid you not.

I got off of that project as soon as I could manage without burning a bridge. Funny thing was that before that? I thought I was quite the stickler for getting types as correct as possible. Turns out I was off by an order of magnitude of what a real "stickler" for correct types could be...


Same story here, on top of that, the tech lead had the most aggressive linting on the planet (no ES class allowed, limited arrow functions, and so on....) I burned bridge, I don't want to have to deal with people that mind fucked limited in their brain where only good code pass this abusive code lint. TS is really cool, forcing the use of `any` is really dumb.

The only downside of burning bridge is that now, I don't have an overview on how bad shape this project is.


This has been my experience. I've used it on a handful of projects over the last few years and while there have been some benefits it has definitely decreased productivity. I can't say that the TypeScript that I've written has been any more bug-free that the regular JavaScript I've written (or my team mates).


> I can't say that the TypeScript that I've written has been any more bug-free that the regular JavaScript I've written (or my team mates).

Probably just means you are smart and good at testing at some level ;-)

For me the biggest benefit of TypeScript is probably when I debug or extend other peoples code (i.e. all the time) and I don't have to hunt down calling functions to see what gets passed in.

I mostly work on large projects written by other people over the course of years and often this simple thing can save me several minutes several times a day.


Yeah, that's definitely handy, or the ability to right click on something and click "Go to definition" to jump right to it. I'm not saying it's worthless, but all of the legwork to get that to work isn't worth it to me.


Just works out of the box with Angular 2 and above and for React "Create React Application" has you covered. I even thknk there's something for Vue.


preach


I kind of came to the same conclusion at some point. I normally find statically typed languages much more productive. If you’re working with all typescript libraries with great typings it’s probably great but the reality of the javascript ecosystem means you’re often wasting time getting the compiler to understand how a few dependencies should cooperate. That and the fact that I contracted on a few larger projects that were in a transition phase filled with ‘any’ which often meant little type safety but a lot of extra typing.


You don’t really have to type anything you don’t want to type though?


I have software I've personally written that's still running 20 years later. Most of my JavaScript/TypeScript is now many years old. Getting your typings perfect for some weird use case might not be useful but 3 days -- that's nothing.


In the limited TypeScript I've done (only a few months so far), every single time I thought "oh well, let's leave this at any for now" or "ah, crap, ts-ignore until I can think of a better way" or even "let's disable strict-null-checks for now, as fixing all those cases is too much work" has resulted in broken code down the line because assumptions that are not caught by the types have been invalidated. So I tend to err on more or better types for now. Some things can't really be improved of course, but that's where experience comes in over time in recognizing those cases.


I completely agree with you. I once use JSdoc instead of Typescript for a small project. Typing works as good as Typescript on VS Code.


This!

I found it far more productive that going through rabbit hole of TS and its compiler. I write my `definitions.d.ts` for my objects, and use them simply

   /** @type {ns.MyType} identifier */
   const identifier...
and voila, my IDE gives me auto-completes and warns me when I'm doing silly stuff.

It works for functions as well using

   /** @param {type} parameter name */
and is generally a good idea to use.

It gets you 80% of the way there with no compiler/transpiler (although one might argue that the IDE is compiling non-stop on file saves, with its language server).

I embraced Typescript when it was new and the Javascript standard was a total mess. It was leaps and bounds ahead and closer to something like AS3. At the time TS was godsend.

Today, JS + webpack gets you really far using the latest ECMAscript standards.

Same with IDE. The amount of stuff my IDE can deduct based on my few typings and my use of modern strict javascript has strongly reduced the need for another transpiler (on top of webpack).

I found jsDoc to be a perfect 80-20 solution.

Because at the end of the day, TS isn't a compiler, it's a transpiler. You're not compiling to bytecode in a vm, you're still in javascript.

This saves my bacon in the front-end. For the back-end, I most definitely choose a strongly typed language like Go.


I have been working on a frontend project for the past two weeks now. Probably about half my time has been dealing with type errors.


So it’s working? Presumably you are doing something to cause them.


Or their implementation is perfect but are demoralized that they are asked to prove perfection when they'd prefer to move to the next task.


A while ago I spent a week turning a humongous interface with all fields optional into a discriminated union of smaller ones, falling back to an "any" dictionary.

My team was really happy with the result, but I'm afraid that if layoffs happen, I'll be on the shortlist.


I love going down rabbit holes chasing perfect type definitions.

But someone calling themselves startup-cto.net should be a lot more pragmatic about the value of strong types and willing to embrace the possibility of change!


This should be the top comment!

Writing types give me more pleasure than it should... but if something is hard to type and unlikely to be referenced outside the local scope, it often isn't worth the effort.


I think it's important to remember that TypeScripts types are there to deal with the insanity of the JavaScript ecosystem, and are not there to be Haskell.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: