|
|
|
|
|
by weavejester
13 days ago
|
|
I too agree that "until you get better" isn't a good take. To err is human, and even the most experienced developers make mistakes. That said, you don't get static typing for free. As with many things it's a trade-off: you catch some errors at compile time in exchange for working within the confines of the type system. The ultimate hope is that the time you spend fiddling with types is going to be less than the time you spend debugging type errors. > There is nothing you can do with dynamic typing that you cannot do with a sufficiently powerful static type system - and it doesn't have to be something absurd like Haskell's. You basically just need structural typing and type inference and some type-level programming constructs. Haskell doesn't have a complex type system for no reason; it's necessary to encompass everything it wishes to do, and even then it's not as flexible as a dynamically typed language. For instance, how would you statically type Clojure's `assoc` function? It's not at all trivial if you want to retain the type information of the keys and values. |
|
In practice, what you want is something that allows you to do this safely for the concrete type you're working with. If you want an abstraction that covers all of it, there are ways to achieve this in a type-safe manner, such as traits/type classes. Even in clojure, you're not working with everything at once all the time. You are working with a record, or a vector, or whatever. The fact that you can use one function for all of them is mostly just needless cleverness. In Clojure, you have to keep the type of the data you are working with in your head at all times, because even though `assoc` "just works" for many cases, that's not true in all cases. It will happily insert an integer key into a record without issue, which may or may not be waht you want. But you can also try to insert an atom key into a vector, which then crashes loudly. This is clearly an asymmetry in the abstraction.
Moreover, pointing out that Haskell cannot do what you'd want to do in this case doesn't make a lot of sense. I mentioned Haskell precisely because its type system is extremely powerful and complicated to understand for a lot of people, but still doesn't achieve the kind of flexibility we are looking for - it lacks row polymorphism.
To answer your actual question: Typing a function like that for the individual cases is bordering on trivial in a language such as typescript. For the record case, you don't even need it, because in practice, you get the correct type inference for free by just spreading one object into another.