TypeScript Academy: An Expert Crowd-learning Practical Course
We spent over five months sharpening our TypeScript-fu in a crowd-learning program to go above and beyond your regular coding needs. Read more about our journey and what we have learned.
Motivation
I’ve had a whale 🐳 of a time attending our and crowd learning Go and Flutter program and ABCH’s SSoS and so I tried refreshing the concept with a subject dear to me: TypeScript. Let’s see how it went, what we did well, and what could be improved.
Why TypeScript?
When we started adapting TypeScript about 4 years ago, I was actually one of the few who objected. At that time, Flow was still a popular choice and there were many other projects adding typing to JavaScript, like ReasonML, PureScript , etc. At that time it was not obvious that TypeScript would be the one to take off, but luckily I was wrong and people were right not to listen to me and keep on moving our stack to TypeScript.
In a few months, we all were quite happy with the transition and kept our love for all projects ever since. After a while, our frontend team began the adoption as well. So having two developer teams actually working with TypeScript, learning it could prove much more influential than trying out new technologies, like in the previous examples.
The Go and Flutter schools were both “true” crowd-learning experiences: several people without any formal knowledge of the topic and very light management would teach themselves. All of us made a great leap, but being all beginners, we could hardly get to any advanced topics.
With TypeScript Academy I wanted to take an alternative route: Being fairly proficient in TypeScript I felt confident to organize an advanced education project, hence the cocky name Academy. I do not say that lightly: when you say to your colleagues (among which are super capable people you work with on daily basis in the same technology) that they can join the “TypeScript Academy” to learn and improve, you’d better have something that even the best of them can learn, which means, ultimately, to prepare something where even you can learn yourself. Nobody wants to be teased into an advanced course just to read the docs and do basic examples.
Also having (at least) two teams worth of people that know the technology fairly well and could actually use any obtained skills in their daily tasks was a great opportunity to set the bar higher and make the course not about “learning”, but “mastering”.
TypeScript: The course
Mastering TypeScript is not just about writing “your regular useful code” (which mostly anyone attending could do well anyway), but rather about meta-programming in types, which allows you to write generic code. For this purpose, I decided to use even without Type Challenges: an excellent project that provides a list of puzzles, and tasks with increasing difficulty. The puzzles are like code katas, but instead of writing logic for a runtime environment, you implement it in the static type system. It might sound odd, but you can do one-sided equality checks, branching with ternaries, and iteration with recursion, so you can do “algorithms” because the type system is Turing complete even without JavaScript in it.
In the beginning, we usually prepared the puzzles at home and live-coded or explained the existing solution. In the second phase of the course, puzzles were accompanied by short presentations on advanced topics (e.g. DefinitelyTyped, namespaces, decorators, opaque types, …), and in some of the last sessions, we spent mob-coding the hardest puzzles in a group of few people, like Sort and Sum in the type meta language and Generic currying.
We decided to meet once a week and take turns (in full rotations, so everyone periodically has a contribution) in short (5–30 minutes) presentations or live-coding sessions. There were 8 (including myself) brave souls (5 backend, 2 frontend, and one DevOps) attending the vast majority of the lessons with 3 additional visiting representatives of PM, DevOps, and backend, who showed up for a lesson or two to see what it’s like (also it was a bit difficult to drop in as the course went on).
All in all, we had 17 lessons with not-so-shabby attendance, with only 3 people attending 11/17 lessons or less.
Happiness evaluation
During the course I did two feedback forms, one after the fourth lesson, and the second one at the very end. The first one was to see if it was what everyone expected and to see if there are some ways to improve the rest. There were three major standouts:
- The course met the expectations and people were generally content with it (which is really cool, because not only I proposed a reasonable direction of the course, but explained it well enough in the first lesson and also we managed to follow it for a few weeks, so yay!)
- Sticking with only puzzle-solving and coding was too narrow for some people (that’s why we added the “presentations” as mentioned)
- From the different approaches, people were generally most content with live-coding as a form of presentation, as seen in the following chart.
I was really excited about the results from the second form because it was an opportunity for me to get feedback on the project that has been going on for over five months and required my focus for even a little longer than that.
Excitingly, as the charts show, we were able to lift ourselves (by our own anonymous definitions) from average TypeScript level 4 (out of 10) to level 7.625 (non-integer levels don’t have the ring to them, do they?) and the complete beginner climbed up to level 5!
Another goal for me was to grow a team of problem solvers: before the course rarely anyone besides me helped people stuck on complex types, advanced generics, and cryptic transpilation errors. At the end of the course, ⅞ people helped a colleague solve a problem they had with TypeScript, which is lovely.
At the end of the course, we decided to reward ourselves with a memento. We scrambled a t-shirt design at wordclouds.com with authentic words from the markdown file with our shared notes and met at a retrospective.
The retrospective discussion provided the following highlights:
- We lacked a moderator: I didn’t think we’d need one since over 90% of the time someone was live-coding or presenting, but in the end, we figured it would probably make the flow of the lessons swifter and more enjoyable if we had a moderator and take turns on that role.
- We nailed the concept of short presentations (approx 20 minutes), which are preferable to long lessons. Hour-long lessons are sometimes harder to follow or catch up on if you get lost. Of course, this concept was available to us since we did most of the work on the zero-setup TypeScript playground . Everyone could start it instantly in the browser and puzzles had no prerequisites.
- Automation for assigning presentations and puzzles would be better than volunteering. I have considered assigning the puzzles, but I thought if people signed up for the specific ones, it would be better because of the different levels of experience. We agreed that having something assigned externally forces you more to complete the task, compared to the pressure to sign up by yourself for a topic, which people find easier to resist. Welp, we are a lazy bunch, we developers.
- Puzzle repo was great material to follow, but sometimes we lacked a goal. Without a thought-out curriculum, it was easy just to lean on the goal to “finish all puzzles”. We were not sure how many lessons it would take us and we lacked some defined milestones. Spanning over 17 weeks, however, I feel like we kept the dynamics of the course very well.
The taste of the types
Since we spent so much time cracking katas and live-coding, it would be rude to leave you empty-handed. Let’s look at one puzzle more closely: Sort
The goal is to implement a meta-type that receives a tuple of number literal types (all constant) and returns a constant tuple type, containing the same number literals, but sorted.
Sort<[2, 4, 7, 6, 6, 6, 5, 8, 9]> // [2, 4, 5, 6, 6, 6, 7, 8, 9]
Since you cannot do any imperative constructs you are probably used to, you cannot really implement any compare and swap algorithms. Instead, you have to get by with whatever is available, which sometimes tests your creativity. Here are two authentic solutions we have from the course (we mob coded the first one in three people and I’ve written the other one myself)
- Find minimum using accumulator and recursive walk-through tuple
- Append minimum to the resulting tuple
- If the input tuple is empty, return accumulator (from 2), otherwise, remove the first occurrence of the element found in (1) and call recursively with the updated input tuple.
- Enhance each element with an accumulator tuple of length equal to the element (for “3” add a tuple with 3 elements)
- Append all elements with an empty accumulator to the result tuple
- Pop one last element from all remaining accumulators
- If the array is not empty, repeat from (2)
I bet you would not use any of the algorithms in the language of your choice, right?
TypeScript Academy: Summary
The whole academy was an awesome experience for me (though a challenging one!). We all made some sacrifices in our free time to make it work and I feel it was worth it. It was a wonderful journey and I am extremely grateful for all the good people who joined and helped us create this collaborative learning experience together.
Would you be interested in doing a similar project in your team and need help? Let me know. If you have any troubles doing complex types in TypeScript, we now have a squad of people willing to help you out, so feel free to reach out to us.
Originally published at https://www.ackee.agency on August 10, 2022.