I am regularly up at night in a cold sweat worrying about how if I suddenly find a technically fulfilling job, realizing I forgot everything about computers after a decade on working on meaningless front end JavaScript framework.
What you do as your first job massively influences you career. I did .NET for years by the fluke that is what my first job did. If they did Java, I would be an expert in Java. If I worked somewhere they needed a compiler written in C++ I would have done it and may have a compiler career.
The paradox is as a graduate you generally, unless very exceptional or well connected, or live in the (not "a") tech city, just need to get that first job.
It is hard to get that breaking opportunity, and so that thing that will have echoes throughout your career, you don't have much control over! The reason it is hard to get the first job is because it needs interview experience, and you have very little proof yet. You are asking a company to take that leap of faith.
Later side stepping is possible but very hard as you are competing with people who can be paid the same as a web dev with deep experience.
Also as a young person back then, I had approximately zero confidence, both in myself and even that programming is a good thing to do. Getting into it was very weird, I was probably the only person at my high school of hundreds who geeked out on electronics and programming, for example.
Nowadays with HN and other sites, there is an online community such that even in a country town you can get a sense of community and what is possible. With that any graduate now could hatch a decent plan for their career. They might take any job to pay the bills, but aim to get into a FAANG for example, knowing what it pays and how to go about it. 2020's are amazing.
On the front end, the trends tend to be more extreme; people will not take you seriously unless you give up on whatever tools you use and go straight for React or VueJS... Then when TypeScript comes along, everyone has to switch to that... I couldn't believe it when people started combining JSX with TypeScript... It's essentially a double-transpiled language now... The trends keep adding more complexity and everyone is forced to switch to that regardless.
Introducing a transpiled typing system on top of a dynamically typed language is a recipe for all sorts of insane complexity, which is what I experience whenever I try to use TS. If you consider all the time and effort it took to introduce types for every NPM project out there, all the development of the language itself, the effort expended by individual devs and teams to learn the syntax...
...might it have been the same amount of effort just to introduce some strong types into Javascript itself? It's not like the language can't adapt, and there are already some strong types when you're working with the graphics APIs.
And how would it be different?
I've been using TS since 2016, both for front and back-end, and I can count an amount of times the transpilation abstraction leaked on one hand (and most of these were when I just learning TS and worked on weirdly configured projects). Aside from these, I could just forget about the fact that it's transpiled to JS under the hood.
TypeScript exists as a first step to adding types to JS. Some folks are currently trying to figure out a way to add type annotations that the JS engine will just ignore for now based on what we've learned from TS.
I spent a ridiculous amount of time trying to design types. At some points I couldn't figure it out, or I ran into some limitation of the language to express what I need. So my code has a bunch of exclamation points everywhere to assert that a null ain't coming. It feels dirty.
Just too hard to use for me.
It's not even that there's only happy heads-down programmers off HN who support these mainstream techs. Even in the active userbase here, I'd wager there are tons of people who have an adequate or better experience with typescript or react, and may disagree with the dislikers. But we're not as invested in our liking, don't feel like it's worth engaging in, and none of the banter changes what is or where things are going. These are the de-jure tools that the majority definitely uses widely, which at least the first anti- comment, on front-end frameworks, acknowledged. Whatever the targets-of-the-day happen to be, they will crop up repeatedly, which further dissuades from trying to come back with a positive or even neutral opinion that might represent that silent majority's take. And the silent majority must constantly face Brandolini's Law; what it's doing may be working & have good reason, but it's hard to keep supporting & reasoning through with a pact invested in disbelieving.
I liked the top post talking about disagreeing with the direction. That can be contributive, be value based. So often though the protests amount to gatekeeping "you've done too much." I evaluate where these comments would fall on Steve Yeggie's Software Political axis, from Notes from the Mystery Magic Bus[1], and almost universally the voices are conservative; they object rather than suggest, they refuse rather than support. I'd like to see more progressive protests, that can surface good, that acknowledge value & need but reflow or redirect the energy elsewhere, rather than being unhappy with what is.
I appreciate the high quality HN posts, but sometimes just like at a water cooler a bunch of us just wanna say, "agh I'm so sick of object oriented" and it doesn't mean "all object oriented programming is of no use".
Are you using "?" optional fields in your classes/interfaces a lot? If so, do you need to? Unless it's truly optional, you're basically making the type system less useful if you put that all over the place. If you have a lot of sparse objects, it's probably an indicator of a data type doing too much. You might be much better off splitting it into smaller interfaces and using union types when you need combined objects.
Even if you can't do the above, checking for null at the start of a function/block will "prove" to the compiler that it's not-null for the rest of the block, so an upfront check can save you from a lot of "!" assertions.
Even if you can't do either of the above, you can probably use the elvis operator "?." to safely dereference things that might possibly be undefined.
In my experience with typescript, there's a few good rules of thumb and things to keep in mind:
- Prefer "interface" over "class" for describing most data types. Especially plain old data objects that don't have methods. I'd forget about the definition of "interface" you might know from Java. It can be used that way, but it can also be used like you would use "struct" in C
- Use the "Partial" modifier instead of using "?" in the base structure if you need to do something like sparse updates. For instance a pattern I use a lot is:
interface MyStruct { a: number, b: string }
function update(original: MyStruct, updatedFields: Partial<MyStruct>) {
return {...original, ...updatedFields}
}
- Always prefer readonly fields and non-optionality.- If you're not worried about GC pressure, it's almost always better to return a new object than mutate an old one. The spread operator is great for this.
- Within reason, it's better to prefer smaller data structures and use type unions when you need fields from both in one object.
I think I went into the deep end with some non trivial generic functions. It's been a few months, but I remember ditching interfaces for classes so I could do some run time type checking.
I wouldn't have fallen into these traps with something like Java.
IMO it's not that Typescript is limited at all, it's just that the type system is different, more complex and also more flexible - there are typically more ways to define types compared to Java/C#, so a lot more decision points trying to write something elegant, or even just idiomatic/understandable, so IMO the learning curve is steep. And then you get to the fun stuff with more abstract type definitions, infer keyword...
It screwed with my head way more than I thought it would. Structural typing was really different, I had to spend a long time rewiring my brain. But when I went back to C#, I felt like the type system was crude. I lost all the nice and easy ways of writing dynamic code and had to revert to defining surplus kludgy interfaces, delegates, etc. And in Typescript I'd finally figured out how to write null-safe code and remove almost all ugly coercions, then back in C# null references were a real possibility.
But the frustration left a worse impression than did the benefits. Perhaps if I was being paid to do it and had mentors around to ask for help. But I couldn't find any good advice online.
It took me far longer than a few hours to feel comfortable, probably more like over a month of coding to get to the point where I mostly understood how to express what I wanted with the type system, and had stopped doing C# things in TS and adhering to style guidelines - functional modules, types instead of classes, injecting dependencies etc. And another month or two? to really figure out how everyone has been (ab)using the type system to do more complex stuff.
TS is really flexible and you can do some crazy gymnastics with it - I don't favour that. Just keep it very simple and don't go crazy with the generics.
I've never had a problem at all, I've never had to dig into what was transpiled.
It doesn't make sense; kind of like transpiling lower level assembly code into higher level C code. You could always argue that there is value in forcing arbitrary constraints onto developers but in the end, you need to ask the question "is it worth the complexity?"