TypeScript's type system is very powerful because it allows us to express types in terms of other types, including generics
I was looking at the implementation of the TS utilities & learned lots about how to implement generics, so I wanted to share my learnings
/thread 🧵👇🏾
1️⃣ Basic generics
Generic types are like implicit return funcs. They take 1+ params & return a new type
`Partial<>`, `Required<>` & `Readonly<>` take any obj type & return a new obj type w/ property modifiers
We can use them as an example for our own `Mutable<>` util!
🧵👇🏾
2️⃣ Generic constraints
Using `extends` we can restrict what types of params are allowed. It's kinda like providing types of our generic params
`Record<>` limits the `Keys` param to only `string`, `number` or `symbol` cuz JS objects only allow those types as keys
🧵👇🏾
3️⃣ Conditional generics
We can use a ternary operator to return the type based on a type condition
`NonNullable<>`, `Exclude<>` & `Extract<>` remove/select the types of the target param if the source param type matches
We can build `NonNullable<>` using `Exclude<>`!
🧵👇🏾
4️⃣ Generic references
Instead of restricting a param by predefined types, we can limit based on types of other params for relational validation! 🤯
`Pick<>` enforces that the strings listed are valid keys of the obj
And `Omit<>` is composed from `Pick<>` & `Exclude<>`
🧵👇🏾
We're really just scratching the surface on how TS generics work by rebuilding the utils, but it gives us insights into how we can build our own generic types
Check out my latest post w/ more explanations on how the code snippets work
📣 If you're interested in learning more about TypeScript I'm giving a workshop as a part of @cascadiajs on Nov 11 called "TypeScript for React Developers"
Workshop tickets are $50 off w/ purchase of conference ticket
That's a wrap for this week! Feel free to subscribe to the BenMVP Newsletter for more of my posts on TypeScript/JavaScript, React, DivOps & other frontend goodies
I recently created a TypeScript generic utility type that recursively converted `Date` types into Firestore `Timestamp` types
The type was fun to come up w/ cuz I learned a lot but it's also a bit complex. Lemme break down all the TS features line by line...
/thread 🧵👇🏾
`ToFirestore<>` takes a single generic type param, `MaybeDate`. If it is a `Date` type, then the "true" branch of the type conditional returns a `Timestamp` type instead. This base case of the recursive type serves as the crux of the mapping of `Date` ➡️ `Timestamp` type
🧵👇🏾
The "false" branch of the outer conditional begins a nested one that converts `Date` ➡️ `Timestamp` types of an array type by recursively calling `ToFirestore<>` on the array item type
(the `infer` keyword auto-creates a new generic type that's the array items type)
What are some situations for when we can use the `useCallback()` & `useMemo()` Hooks in React components?
Well, one case where we need `useCallback()` is when we call a helper function w/in `useEffect()`, so we need "referential equality" to include it in deps
/thread 🧵👇🏾
I also use `useCallback()` by default when returning a function from a custom Hook cuz I dunno how that function will be used w/in host components
`useCallback()` gives a stable function reference similar to the updater func from `useState()` (the 2nd array element)
🧵👇🏾
The `useMemo()` Hook is similar to `useCallback()` except that it memoizes any value not just functions
So I use `useMemo()` in the same situations: when I have a derived object/array that's used in the deps of `useEffect()`
The .reduce() method is maybe the most powerful, yet least understood array method. It basically allows us to transform an array into... nearly anything else
Let's re-implement 1️⃣0️⃣ lodash functions to learn more about how for examples on how .reduce works
/thread 👇🏾🧵
1️⃣ sum()
ℹ️ Computes the sum of the values in an array
The function is called a "reducer" & the 2nd param is our initial value
The 1st arg of the reducer is the "accumulator" (the value we're building up). The 2nd is the current array element in the iteration
/thread 👇🏾🧵
2️⃣ countBy()
ℹ️ Creates an object w/ keys that are the array elements and values that are their counts
Here we're turning an array into an object
(can't forget to return the object we're accumulating!)