Remix.run Logo
embedding-shape 11 hours ago

You're changing the point though, you claimed "I don't find that dynamic typing reduces the number of places I need to update stuff", which just because your editor makes the change, doesn't suddenly make the change not show up in the diff for you and others. A change is a change, regardless of how it's made, unless you don't keep your code in a SCM that is, which I'm assuming most of us do.

I'm not saying it's hard to change types in TypeScript, I understand that your IDE is connected with the language and they're used together, but again my argument was that having types leads to having to change things in more places. Which is true too, and it's a good thing, it's on purpose, and the tools you use help with that, so yay for that! But it's still more changes, and at least for me it's important to be honest about the tradeoffs our choices leads us to.

As I mentioned earlier, I'm fan of static typing in many situations, just not all of them. And I'm not blind to the negatives they can bring too, I guess I just see more nuance in the static typing vs dynamic debate.

skydhash 11 hours ago | parent [-]

Regardless of how dynamic typing is, the contract being enforced stays the same. It's just less enforced by tools. So with dynamic typing, you will have to change the same amount of code if you want your code to stay correct. The only variation in code changes comes from the annotation for the type system.

scotty79 10 hours ago | parent [-]

> So with dynamic typing, you will have to change the same amount of code if you want your code to stay correct.

No, because if a piece of data is pushed through multiple layers you can just change its type at the source and the destination and not in all the layers the data is pushed through. And you can still be correct.

Imagine you have a thing called target which is a description of some endpoint. You can start with just a string, but at one point decide that instead of string you'd prefer object of a class. In dynamic language you just change the place where it originates and the place where it's used. You don't need to change any spot in 3 layers that just forearded target because they were never forced assumed it's a string.

You can achieve that in staticly typed language if you never use primitive types in your parametrs and return types or if you heavily use generics on everything, but it's not how most people write code.

Tools can help you with the changes, but such refactors aren't usually available in free tools. At least they weren't before LLMs. So the best they could do for most people was to take them on a journey through 3 layers to have them make manual change from string to Target at every spot.

skydhash 8 hours ago | parent [-]

In some type systems, you don't need to change it either. Errors will happens only if you've written code that assumes that `target` is a string. If I write a function with the following signature:

  fn split(str: string) => string[]
And you called it with

const first_el = split(target)[0]

If you decide `target` to suddenly be an object, then the code you wrote is incorrect, because semantically, `split` only makes sense when the argument is a string. Which is why, even with dynamic typing, you'll see that the documentation of a function will state what kind of parameters it expects.

If you a call chain like `fn1 | fn2 | fn3 | fn4 | split`, Then yeah you need to ensure what reaches `split` is in fact a string. If you're against updating fn[1-4]'s signature, let's say that it's harder to find which function needs to change in a dynamic typing systems.

Dynamic typing is useful for small programs and scripts because they are easy to iterate upon. But for longer programs, I'll take static typing anytime.