Rust for TypeScript Developers
Table of Contents
IntroductionThePrimeagen begins the course by comparing Rust to TypeScript. The developer ergonomics of Rust make it easier to write maintainable code without a lot of unexpected behavior. Proficiency in TypeScript and an understanding of Unions, Generics, and functional programming are recommended before viewing this course.
Rust BasicsThePrimeagen compares common programming constructs in TypeScript to the equivalent implementation in Rust. The examples include variables, functions, loops, classes, and interfaces.
Numbers & StringsThePrimeagen explains how Rust handles Number and String types. Rather than a single Number type, Rust has types representing integers, unsigned integers, and floating point numbers. Strings can be represented by a mutable String type or an immutable &str, a pointer to a sequence of utf-8 characters.
Vector, Tuple, & StructThePrimeagen explains Vectors, Tuples, & Structs. Vectors closely resemble Arrays in TypeScript. By default, they are not mutable unless declared with the mut keyword. Structs are similar to Objects or Classes. Pattern matching is also introduced in this lesson.
todo, unreachable, & unwrapThePrimeagen introduces three convenience methods in Rust. The todo method flags unfinished code. The unreachable method indicates code should not be reached and will panic, and unwrap will return the contained value.
Install RustThePrimeagen sets up a new project with TypeScript and Rust. Strict type-checking rules are enabled. Cargo, Rust's package manager, initializes the Rust project and a Git repository.
Value, Mutable, ImmutableThePrimeagen explains the difference between values, references, and mutability. Values can be accessed by their owner or through a reference. By default, references are read-only (immutable). To mutate a value through a reference, the reference must be defined using &mut.
Coding an IteratorThePrimeagen introduces iterators and creates programs in TypeScript and Rust that define a list of numbers, map through them, and increment their value by one. The result is printed to the console.
Understanding CollectThePrimeagen demonstrates the functionality of the collect method by implementing a custom version of it. Values from the original vector are pushed into a new vector as they are iterated. The new vector becomes available after the iterateration is complete.
Iterating Through a Text FileThePrimeagen reads from a text file and presents two exercises for working with the contents. First, the contents are iterated through and printed to the console. Afterward, a filter is applied, and every even line is printed.
Enums in TypeScript vs RustThePrimeagen creates enums in both TypeScript and Rust. One advantage of Rust enums is adding utility methods rather than relying on a separate module. The match operator also provides additional type safety with Rust enums.
Enums & SubtypesThePrimeagen demonstrates more capabilities of enums in Rust. Subtypes can be added to enums to enable pattern matching and eliminate the need to check the types of properties on an object or struct. Additional pattern-matching techniques are also demonstrated in this lesson.
Options in TypeScript vs RustThePrimeagen explains Option types are a useful way to handle null and undefined values. The Some and None variants explicitly define the type and whether or not the option handles null or undefined values.
Options in RustThePrimeagen uses Options to eliminate type-checking against undefined variables. The ? operator can be used to unwrap a value by using pattern-matching under the hood.
Options ExerciseStudents are instructed to write a function that takes in a Vec<usize> nums and a usize index and returns either the value multiplied by 5 at the index (if it exists) or the index multiplied by 5. The solution should be written in TypeScript first, followed by Rust.
Error HandlingThePrimeagen introduces error handling and different strategies for addressing errors in an application. If a function throws an error, default values can be returned instead of the error with unwrap_or. The and_then method can also layer on scenarios for handling an error.
Results & Error Handling ExerciseStudents are instructed to write a program that reads an argument from the command line that specifies the name and path of a file. The file should be loaded, and each line should be printed.
Q&AThePrimeagen answers questions about the differences between Option and Result enums.
Stack vs HeapThePrimeagen explains how function calls are added to the stack. Recursive function calls without a return can cause a stack overflow. For property types like vectors that grow dynamically, their contents are stored in heap and a reference to the heap is placed on the stack.
Borrow CheckerThePrimeagen introduces the borrow checker and explains a few rules about how Rust handles values. A value can only have one owner. There can be unlimited immutable references (borrows) and only one mutable reference (if there are no immutable references).
Borrow Checker PracticeThePrimeagen walks through examples that lead to borrow checker errors and identifies the problematic code in each example.
Borrow Checker Q&AThePrimeagen answers questions about the borrow checker and scenarios around how long Rust keeps values in memory.
Traits vs InterfacesThePrimeagen compares interfaces in TypeScript with traits in Rust. Both interfaces and traits specify methods that should be found on the objects implementing them. Rust adds an extra level of abstraction by using the impl keyword to define the specific method implementation of the trait for a given struct.
Creating ModulesThePrimeagen demonstrates how traits can behave like a prototypical inheritance because they can add a method to types not owned by the program. The code is then refactored, and a Rust module is created by importing the necessary traits.
Default & Display TraitsThePrimeagen implements two built-in Rust traits. The Default trait behaves like a static method and returns a new struct instance with default values. The Display trait behaves like a toString method and allows for a custom print implementation. A TypeScript-equivalent implementation is also created in this lesson.
Creating an IteratorThePrimeagen creates a custom iterator for the rectangle struct. An associated type is defined to tell Rust what to expect out of the iterator. The resulting items contain a vector of points along with the index.
IntoIterator & From TraitsThePrimeagen further explains the functionality of the IntoIterator trait. Because this trait is implemented on the Rect struct, any instance of Rect can be used in a for loop or any other iterative statement. However, reference implementations are necessary to satisfy the borrow checker. The From trait is also introduced in this lesson.
Custom TraitsThePrimeagen creates a collision module. The Collidable trait is created and implemented for all collision scenarios. For example, rectangles colliding with rectangles, circles with circles, and rectangles with circles.
Generic Trait ImplementationThePrimeagen creates a generic implementation of Collidable by creating a PointIter trait. This trait generically maps over a vector of points. Points and Contains traits are also made. The Contains trait with one method, contains_point, returns a bool if the point is contained within the geometry.
Refactor Rectangle and CircleThePrimeagen refactors the rectangle and circle shapes to implement the Point and Contains traits. In order for rectangles and circles to be able to detect each other, the Collidable trait is refactored to include two generics.
Reading Shapes from a FileThePrimeagen reads shape data from a file and codes a new Shape enum. The Points and Contains traits are implemented, and adjacent lines in the data file are checked for collisions.