Now, that said, I probably would want to be friends with that dev. Unless they had an AI generate it, in which case the sin is doubled.
Now, that said, I probably would want to be friends with that dev. Unless they had an AI generate it, in which case the sin is doubled.
RXJS’s pipe function has a pretty complex type for its signature, but as a user of the library it ‘just works’ in exactly the type-safe way I’d expect, without me having to understand the complexity of the type.
As someone who came from a CS background, this kind of attitude is deeply mysterious. That seems like a type expression I'd expect a CS undergrad to be able to write - certainly if an SDE with 1-2 years experience was confused by it, I'd be advocating against their further promotion.
My interpretation of OP's point is that excessive complexity can be a "code smell" on its own. You want to use the solution to match the complexity of the job and both the team that is building it and the one that is likely to maintain it.
As amused as I am by the idea of a dev team being debased by the inelegance of basic bitch programming, the daily reality of the majority of software development in industry is "basic bitch" teams working on "basic bitch" problems. I would argue this is a significant reason why software development roles are so much at risk of being replaced by AI.
To me, it's similar to the choice one has as they improve their vocabulary. Knowing and using more esoteric words might allow adding nuance to ideas, but it also risks excluding others from understanding them or more wastefully can be used as intelligence signalling more than useful communication.
tldr: Complexity is important when it's required, but possibly detrimental when it's not.
Especially when it comes to signatures in Typescript, complex signatures can be used to create simple and ergonomic APIs.
But anyway you shouldn’t be allowed to push anything like this without multiple lines of comments documenting the thing. Unreadable code can be balanced with good documentation but I rarely saw this unfortunately.
If you're writing first-party software, it probably doesn't matter. But if you have consumers, it's important. The compiler will tell you what's wrong all downstream from there unless someone explicitly works around it. That's the one you want to reject.
You're confusing things. It is a maintenance nightmare because it is your job to ensure it is correct and remains correct in spite of changes. You are the one owning that mess and held accountable for it.
> If you're writing first-party software, it probably doesn't matter. But if you have consumers, it's important.
Yes, it is important that you write correct and usable code. That code doesn't fall on your lap though and you need to be the one writing and maintaining it. Whoever feels compelled to write unintelligible character soup that makes even experienced seasoned devs pause and focus is failing their job as a software engineer.
I see it differently. That's the name of the game. Language design is always striving toward making it more intelligible, but it is reasonable to expect pros to have command of the language.
No, that's an extremely naive and clueless opinion to have. Any basic book on software engineering will tell you in many, many ways that the goal of any software engineer is to write simple code that is trivial to parse, understand, and maintain, and writing arcane and overly complex code is the Hallmark of an incompetent developer. The goal of a software engineer is to continuously fight complexity and keep things as simple as they can be. Just because someone can write cryptic, unintelligible code that doesn't make them smart or clever: it only makes them bad at their job.
You say you would reject those correct types, but for what alternative?
It's hugely beneficial to library users to automatically get correctly type return values from functions without having to do error-prone casts. I would always take on the burden of correct types on the library side to improve the dev experience and reduce the risk of bugs on the library-consumption side.
Let's suppose Array.prototype.flat() wasn't in the standard library, which is why I'm reviewing a PR with this gnarly type in it. If I went and asked you why you needed this, I guess you'd say the answer is: "because JavaScript lets me make heterogenous arrays, which lets me freely intermix elements and arrays and arrays of arrays and... in my arrays, and I'm doing that for something tree-like but also need to get an array of each element in the structure". To which I'd say something like "stop doing that, this isn't Lisp, define an actual data type for these things". Suddenly this typing problem goes away, because the type of your "flatten" method is just "MyStructure -> [MyElements]".
I can recognize that most people are going to go for inaccurate types when fancier semantics are necessary to consume things from the network.
But we also have the real world where libraries are used by both JS devs and TS devs, and if we want to offer semantics that idiomatic for JS users (such as Array.prototype.flat()) while also providing a first-class experience to TS consumers, it is often valuable to have this higher-level aptitude with the TS type system.
As mentioned earlier, I believe 90% of TS devs are never in this position, or it's infrequent enough that they're not motivated to learn higher-level type mechanics. But I also disagree with the suggestion that such types should be avoided because you can always refactor your interface to provide structure that allows you to avoid them; You don't always control the shape of objects which permeate software boundaries, and when providing library-level code, the developer experience of the consumer is often prioritized, which often means providing a more flexible API that can only be properly typed with more complex types.
Right, from the structure you get an array with one element which is likely an union type from that naming.
Honestly, you sound more like your arguing from the perspective of a person unwilling to learn new things, considering you couldn't even get that type correct.
To begin with, that flat signature wasn't even hard to understand?
On top of that I fully agree with the poster you’re responding to. In general application code that’s and extremely complicated type, generally done by someone being as clever as can be. And if the code you’ve written when you’re being as clever as possible has a bug in it, you won’t be clever enough to debug it.
I thought it was clear enough that I was being informal and what I meant was clear, but that was admittedly probably a mistake. But to infer an implication from that that I'm "unwilling to learn new things" is a non sequitur and honestly kind of an unnecessarily dickish accusation.
How is that less maintenance burden than a simple Flatten type? Now you have to construct and likely unwrap the types as needed.
And how will you ensure that you're flattening your unneeded type anyways? Sure you can remove the generics for a concrete type but that won't simplify the type.
It's simple. It's just recursive flattening an array in 4 lines. Unlikely to ever change, unlike the 638255 types that you'd have to introduce and maintain for no reason.
There are many reasons not to do that. Say your business logic changes and your type no longer needs one of the alternatives: you are unlikely to notice because it will typecheck even if never constructed and you will have to deal with that unused code path until you realize it's unused (if you ever do).
You made code harder to maintain and more complex for some misguided sense of simplicity.