diff --git a/module8-typescript/README.md b/module8-typescript/README.md index 1003718..ef9ed21 100644 --- a/module8-typescript/README.md +++ b/module8-typescript/README.md @@ -1 +1,30 @@ -# curriculum-backend-readings \ No newline at end of file +# Module 8: TypeScript + +Last revised: 14/06/2022 + +## Summary + +Students learn to use TypeScript, an essential and marketable skill in today’s JavaScript +landscape. This variant of JavaScript provides type safety, allowing developers to write +more scalable and understandable applications. Students apply their learning of +TypeScript concepts using the Nest.js framework in comparison to Express.js. + +## Outline + +- 1 [Introduction to TypeScript [R]](../module8-typescript/r1-introduction-to-typescript/README.md) + +- 1.1 [Everyday Types [R]](../module8-typescript/r1.1-everyday-types/README.md) + +- 1.2 [Advanced Types [R]](../module8-typescript/r1.2-advanced-types/README.md) + +- 1.3 [TypeScript Compiler [R]](../module8-typescript/r1.3-typescript-compiler/README.md) + +- 2 [TypeScript with Node and Express [R]](../module8-typescript/r2-typescript-node-express/README.md) + +- 2.1 [Backend frameworks with TypeScript [R]](../module8-typescript/r2.1-backend-frameworks-typescript/README.md) + +- 2.2 [TypeScript Cart [L]](../module8-typescript/r2.2-typescript-cart/README.md) + +- 2.3 [NestJS Task Management App [L]](../module8-typescript/r2.3-nestjs-task-management/README.md) + +- 3 [Summary [R]](../module8-typescript/r3-summary/README.md) \ No newline at end of file diff --git a/module8-typescript/assets/README.md b/module8-typescript/assets/README.md deleted file mode 100644 index dc48ef7..0000000 --- a/module8-typescript/assets/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# curriculum-backend-readings -Temporary file for git tracking, to be deleted once this assets folder is populated \ No newline at end of file diff --git a/module8-typescript/r1-introduction-to-typescript/README.md b/module8-typescript/r1-introduction-to-typescript/README.md new file mode 100644 index 0000000..6ee6e19 --- /dev/null +++ b/module8-typescript/r1-introduction-to-typescript/README.md @@ -0,0 +1,180 @@ +# Introduction to TypeScript + +Now that you have been working with JavaScript for some time, you must have heard of TypeScript which is described in short as JavaScript with syntax for Types. It is very popularly used in the tech industry these days for both frontend and backend development. Before we learn more about backend, we will familiarize ourselves with TypeScript and how it can be used in backend code through this module. The objectives of this lesson are: + +1. Understanding how and why TypeScript was created +2. Analyzing the pros and cons of using TypeScript in our projects + +## Story of TypeScript + +As per the [2021 Stackoverflow Developer Survey](https://insights.stackoverflow.com/survey/2021#technology-most-popular-technologies), JavaScript completed its ninth year in a row as the most commonly used programming language. However, it is not the [most loved programming language](https://insights.stackoverflow.com/survey/2021#most-popular-technologies-language) because TypeScript ranks 3rd in this list compared to JavaScript at the rank 15th. TypeScript is also the 2nd most wanted language followed by JavaScript. + +TypeScript is a young programming language with its story going back only to 2012. It was launched for public use in October 2012, as of version 0.8 of the language. It was a result of two years of development at Microsoft, with Anders Hejlsberg, the lead architect of C#, as well as the creator of Delphi and Turbo Pascal working on the project too. This team at Microsoft wanted to do something like [Dart](https://dart.dev/) but they took a different approach. Instead of reinventing the language with a completely new syntax, they just amended the JavaScript syntax. Not only that, but they also made this new syntax optional. This is how TypeScript was born. + +That means any JavaScript program is a valid TypeScript program. Due to this reason, TypeScript is also called the **superset of JavaScript**. You might have heard somebody saying TypeScript is just **JavaScript with types**. + +You may be familiar with the basic concept of types from JavaScript or another programming language. In TypeScript, these types are more strongly enforced. For example, you cannot add together a number and a string (`1 + "foo"`) as you would in JavaScript. We'll examine the benefits of this throughout this module. + +For example, in the following TypeScript code, notice that the `user.name` field does not exist (only `user.firstName`, `user.lastName`). + +```TypeScript +const user = { + firstName: "Angela", + lastName: "Davis", + role: "Professor", +} + +console.log(user.name) +``` + +Actually, TypeScript won't even allow you to run this code: you'll get an error. + +``` +Property 'name' does not exist on type '{ firstName: string; lastName: string; role: string; }'. +``` + +We'll learn to understand such error messages and write type-safe code using TypeScript, in addition to understanding why TypeScript has become so popular. While following along in this module, you can play around with some of the code by using the [TypeScript playground](https://www.typescriptlang.org/play). + +## Pros and Cons of TypeScript + +As mentioned previously, TypeScript is a superset of JavaScript. This means that: + +1. It offers additional features to JavaScript such as static typing. +2. Using types is completely optional. +3. It compiles down to regular JavaScript. +4. It can be used for frontend JS as well as backend with Node.js. +5. It includes most features from ES6. +6. Types from third-party libraries can be added with type definitions. + +In case you're wondering, what do we mean by "types"? In programming languages, a type system is a logical system comprising a set of rules that assigns a property called a type to the various constructs of a computer program, such as variables, expressions, functions, or modules. + +Let's imagine a JS program running in the browser (or on Node.js). Being a dynamically typed language, JavaScript will not throw any errors when data type changes for the same variable. At first, the data type of the variable `x` could be a `number`, then a `string` when the value `'hello'` is assigned to it, and then a `boolean` when `true` is assigned to it. So all these types are determined at the runtime. + +What TypeScript did was to provide a compiler that can process a program and throw errors if it detects something odd with the program. This compiler is also called a transpiler since it outputs the cleaner JavaScript program. To use this compiler, we should write the code in a `.ts` file instead of a `.js`, of course after installing TypeScript (using npm). + +What TypeScript expects are the Type Annotations. A Type Annotation is an indication of the data type of a value. For example, the variable `x` can be annotated with `: string`. This annotation provides the data type of variable `x` to the TypeScript compiler. When the TypeScript compiler sees this, it assumes that `x` will be a string during the lifetime of this program. So, if we assign an initial value of `1` which is a number, it is not going to be valid and it will complain about it in the compilation error messages. Once we fix all the issues, TypeScript will generate the output file `sameFileName.js` that is safe to run wherever we want. TypeScript keeps the original filename of the source file and only replaces the extension. The goal of TypeScript is to catch mistakes in a program before it goes to production and causes problems at the runtime. Its goal is not to provide tools to amend or modify the original source code (business logic) such that can it perform well at the runtime in all the situations. + +### Dynamic vs Static Typing + +In dynamically typed languages, the types are associated with run-time values and not named explicitly in your code. For example, JavaScript, Python, Ruby, and PHP. + +JavaScript is a **dynamically typed** and **interpreted** programming language. In general, both of these mean that little preprocessing is done before running JavaScript code. When we say JavaScript is dynamically typed, it means that JavaScript variables have types, such as string, boolean, and number, but these are determined at the time that the code is run -- not beforehand. As an interpreted programming language, the source code is not preprocessed, and code is interpreted, or executed, from human-readable code to things that the machine understands at the time that it runs. You may have noticed that there is an error with types in your JavaScript code -- say you tried to add an array and a number together -- this error will not be caught until the time that the code is run. This is a consequence of being both dynamically typed and interpreted; we are allowed to add together two types that don't make sense (what does it mean to add a list to a number?) and the error only appears if we run the code. + +In statically typed languages like Java, C, C++, Rust, Go, etc., you explicitly assign types to variables, function parameters, return values, etc. + +TypeScript is a **compiled** and **statically typed** language. In a statically typed language, the types of a variable are known at the time that the code is written, not just when the code runs. In a compiled language, code needs to go through another program, called the compiler, before it can be run. While many languages compile, or "translate", from human readable code to machine code, TypeScript actually compiles to JavaScript, though it's not very readable. + +You can read more about some of the tradeoffs between static and dynamic types [in this article](https://instil.co/blog/static-vs-dynamic-types/). + +### Advantages of TypeScript + +1. Makes your code more robust. All your variables can be defined with types. +2. Helps you easily spot bugs. Research says that 15% of commonly occurring bugs can be caught at compile time itself by TypeScript. +3. Improves predictability. If you've defined a variable to a string, it will stay a string. +4. Enhances readability. If you're working with multiple developers, TypeScript makes your code more expressive and self-explanatory and enforces a guideline to be followed by the team. +5. Growing popularity. As we discussed above, TypeScript is growing in popularity in the industry so it is a marketable skill to add to your resume. + +### Disadvantages of TypeScript + +1. More code to write. Sometimes you need the work to be done fast, but TS would involve more code than plain JS for many cases which can add to development time. +2. More to learn. If you've been coding with JS for a while, it would take time to learn TS, and sometimes this is what holds some companies back from refactoring their codebases because they cannot dedicate time for learning. +3. Required compilation. TypeScript needs to be transpiled into JavaScript, in the end, to be understood by browsers and servers. Luckily most popular frameworks today have TS compilation easily configurable. +4. Not true static typing. Because TypeScript is compiled down to regular JavaScript, some developers criticize that it is not a true statically typed language as JavaScript is dynamically typed. So in a way, it gives a false sense of type safety. + +Looking at these advantages and disadvantages, and also if you've been doing some reading online by yourself you will find that there are different opinions about TypeScript. Some developers claim that any JS code should be written in TypeScript and TypeScript only, while some believe it is actually not that beneficial. And then there are some in between who are flexible and open to the ideas of with or without TypeScript. + +Generally speaking, it is best not to form any kind of unshakable opinions about a language or framework in an industry that is ever-evolving and improving. It is always good to learn a new skill, language, or framework. Thus, understand the benefits of TypeScript and be prepared to write TypeScript if the company you work for decides to adopt it in their tech stack. + +## TypeScript in frontend and backend + +We've learned quite a bit about TypeScript and why it makes JavaScript even better. Let's understand this in action with frontend and backend code. TypeScript is compatible with most modern frontend frameworks like React or Next.js. If you're familiar with JSX in React, to use TypeScript you would create a `.tsx` file instead. Let's look at an example of a `Header.tsx` file. + +```tsx +export interface Props { + title: string + color?: string +} + +const Header = (props: Props) => { + return +
+

+ {props.title} +

+
+} +``` + +Here we have created a Header component that takes in two props `title` and `color`. We have defined the prop types using TypeScript and indicated that the `title` should have a string type and the `color` is an optional prop but should also have a string type. + +So now when we want to have a Header component on a page: + +```tsx +
+
+
+``` + +The first case will give us an error within our IDE stating that the prop title is missing. The second case will be compiled and executed to display a header with the words 'Hello World' in blue since we provided blue color as the default when prop color is not provided. And you can predict what happens in the third case too. + +TypeScript is also very compatible on the backend, you can have `.ts` files in your Node Express projects or use a backend framework like NestJS which has TypeScript incorporated. We will learn more about this framework in an upcoming lesson, let's take a look at another TypeScript example useful for backend. + +```ts +type User = { + name: string; + age: number; +}; + +function isAdult(user: User): boolean { + return user.age >= 18; +} + +const justine: User = { + name: "Justine", + age: 23, +}; + +const isJustineAnAdult: boolean = isAdult(justine); +``` + +The first part with `type` keyword is responsible for declaring our custom type of objects representing users. Later we utilize this newly created type to create the function `isAdult` that accepts one argument of type `User` and returns `boolean`. After this, we create `justine`, our example data that can be used for calling the previously defined function. Finally, we create a new variable with information on whether `justine` is an adult or not. So now if by mistake we had set the `age` on `justine` to something other than a `number`, TypeScript would flag the issue and prevent us from shipping code that could work unexpectedly. + +There are additional things about this example that you should know. Firstly, if we would not comply with declared types, TypeScript would alarm us that something is wrong and prevent misuse. Secondly, not everything must be typed explicitly - TypeScript is very smart and can deduce types for us. For example, variable `isJustineAnAdult` would be of type `boolean` even if we didn't type it explicitly or `justine` would be a valid argument for our function even if we didn't declare this variable as of `User` type. + +So looking at these above code examples, here are some strong advantages of TypeScript in both frontend and backend. + +### Reducing bugs + +Have you ever made any of these mistakes in JavaScript and had to spend a nontrivial amount of time fixing them? + +- Called a function with the wrong number of arguments: `twoArgFunction(x)` +- Called a function with too many arguments: `oneArgFunction(x, y)` +- Tried to get the index of a non-array type: `someString[5]` +- Indexed an array with the wrong type, rather than a number: `someArray["foo"]` +- Had a variable be `null` or `undefined` when you thought that it wasn't +- `undefined is not a function` + +With TypeScript, these bugs (and many more) are easily caught at compile time with a useful error message. Static typing is often considered advantageous for scaling codebases. When working on a large product (or even a small one), it saves everyone time and development effort if as many mistakes can be caught _before_ the code is run, not afterward. Compiled and typed languages certainly are not guaranteed to be bug-free, but in general, by the time you run the code, you will have fewer bugs than interpreted languages. In a post-mortem analysis by Airbnb from their attempt to migrate their whole codebase to TypeScript, they estimated that [38% of their bugs were preventable by TypeScript](https://youtu.be/P-J9Eg7hJwE?t=711). + +### Autocomplete + +In addition to the benefits of using types to help reduce the number of bugs, static types also allow for stronger auto-complete in editors, since, for example, the allowable function calls and variable names that can be typed in a certain place will be known even before the code will run. + +### Refactoring + +Having types makes refactoring code much easier. For example, if you are renaming a function, editors can use statically known information about types to rename all instances of that function in a single click. This is not possible with JavaScript; in the absence of type information, the editor cannot know ahead of time whether two function calls named `myFunction()` are really the exact same function, or whether they are two different functions in different files that happen to have the same name. This is only one example, but in general, TypeScript allows you to refactor code with less risk of breaking things. + +## Conclusion + +TypeScript is growing in popularity every day in the industry. It brings some significant benefits and improvements to the development process, but also comes with a few concerns that need to be considered before deciding to use the language. In any case, it makes JavaScript even more powerful through static typing and is a marketable skill to add to any developer's resume. It is used both on frontend and backend and helps developers write cleaner and less error-prone code as it detects issues much before runtime. We shared some syntax examples in this lesson, but now let's take a deeper dive into the different Type Annotations of TypeScript and their uses in the next lesson. + +--- + +## References + +- https://www.cleverism.com/skills-and-tools/typescript +- https://medium.com/jspoint/typescript-a-beginners-guide-6956fe8bcf9e +- https://tsh.io/blog/why-use-typescript +- https://nodejs.dev/learn/nodejs-with-typescript +- https://dev.to/hiro9108/javascript-vs-typescript-why-we-should-learn-typescript-4d5o +- https://www.youtube.com/watch?v=BCg4U1FzODs&ab_channel=TraversyMedia diff --git a/module8-typescript/r1.1-everyday-types/README.md b/module8-typescript/r1.1-everyday-types/README.md new file mode 100644 index 0000000..2957953 --- /dev/null +++ b/module8-typescript/r1.1-everyday-types/README.md @@ -0,0 +1,409 @@ +# Everyday Types + +Without any further ado, let us now dive into the different Types that we can use in our codebases. The objectives of this lesson are: + +1. Viewing practical usage examples of Types +2. Understanding when to use Types + +We'll start by reviewing the most basic and common types you might encounter when writing JavaScript or TypeScript code. These will later form the core building blocks of more complex types. + +## Type Annotations on Variables + +When you declare a variable using `const`, `var`, or `let`, you can optionally add a type annotation to explicitly specify the type of the variable: + +```ts +let myName: string = "Alice"; +``` + +TypeScript doesn't use "types on the left"-style declarations like `int x = 0`; Type annotations will always go after the thing being typed. + +In most cases, though, this isn’t needed. Wherever possible, TypeScript tries to automatically infer the types in your code. For example, the type of a variable is inferred based on the type of its initializer: + +```ts +// No type annotation needed -- 'myName' inferred as type 'string' +let myName = "Alice"; +``` + +## Primitives + +JavaScript has three primitive types -- `string`, `number`, `boolean` -- and they are present in TypeScript as well. You can declare them just as you would in JavaScript. However, in TypeScript, you may _optionally_ add a type. As mentioned previously, in most cases TypeScript can infer the type correctly. + +```ts +// TypeScript infers the type. +const name = "Foo Bar"; +const age = 36; +const isInBootcamp = true; + +// However, if you would like, you can explicitly write the types +// after the variable names. In most cases, this is not necessary, +// but it may be helpful if you are getting an error message. +const name: string = "Foo Bar"; +const age: number = 36; +const isInBootcamp: boolean = true; +``` + +What does it mean when TypeScript is type-safe? Let's try adding together a number and a string in both JavaScript and TypeScript: + +```ts +// JavaScript: prints "1foo" +console.log(1 + "foo"); + +// TypeScript: gives an error +console.log(1 + "foo"); +``` + +## Arrays + +The syntax for arrays in TypeScript is again no different than JavaScript. However, typing becomes more important here. To declare an array of some type, we use the notation `string[]`, `number[]`, and so on. You can also use the syntax `Array`, `Array`, and so on. There is no difference. Note that this is the syntax for referring to the **type** of the variable, + +We'll go through a few examples. + +### Inferred array types + +TypeScript will infer the type of an array if it is declared with some value initially. For example, we have an array of numbers below; TypeScript is smart enough to figure out that `ids` has the type `number[]`. + +```ts +const ids = [1, 2, 3]; +ids.push("somestring"); +``` + +This gives an error, which tells us that we can't push a string to the parameter (of the `push` function) that expects the type `number`. TypeScript has inferred that this is an array of numbers. + +``` +Argument of type 'string' is not assignable to parameter of type 'number'. +``` + +### Limits of inference + +If there is no initial value, TypeScript is, unfortunately, not smart enough to figure out the type of an array. For example: + +```ts +// No type is declared on the array. TypeScript doesn't know +// what type the members are. This code passes, and anything +// can be pushed into the array (not very helpful for type safety). +const ids = []; +ids.push("somestring"); +ids.push(5); +ids.push({}); +``` + +TypeScript believes that the members of the array can be any type (formally: type `any`, which will be discussed later). + +If you plan on declaring an empty array, this is an instance where you would want to explicitly specify the type in order to receive type-safety: + +```ts +// This will give an error if you try to push a string to the array this time. +const ids: number[] = []; +ids.push(5); +``` + +The `number[]` indicates that this will be an array of numbers. Similarly, you could have `string[]` or `boolean[]`. + +## Any + +TypeScript also has a special type, `any`, that you can use whenever you don't want a particular value to cause type-checking errors. It is useful when you don't want to write out a long type just to convince TypeScript that a particular line of code is okay. + +```ts +let x: any = "Hello"; +let arr: any[] = [1, true, "Hello"]; +``` + +When a value is of type `any`, you can access any properties of it (which will, in turn, be of type `any`), call it like a function, assign it to (or from) a value of any type, or pretty much anything else that’s syntactically legal. + +```ts +let obj: any = { x: 0 }; +// None of the following lines of code will throw compiler errors. +// Using `any` disables all further type checking, and it is assumed +// you know the environment better than TypeScript. +obj.foo(); +obj(); +obj.bar = 100; +obj = "hello"; +const n: number = obj; +``` + +Beginners of TypeScript are often tempted to use `any` type, but it is highly discouraged. It is possible in almost all cases to write code without `any`. Do not use `any` as a crutch to skip past type errors: doing so is often a sign that something else is wrong with the code (and `any` is simply being used to ignore the fundamental issue). + +When the keyword `any` is used, TypeScript no longer performs type checking, since it has no information about the type. This means that we no longer have the benefits of the type-checker. + +Here is an example of typing something as `any`, demonstrating how we can start introducing errors in our code that were previously prevented: + +```ts +const a: any = [1, 2, 3, 4, 5]; +const invalidAddition = a + 5; // Adding a list to a number? +const functionDoesntExist = a.someInvalidFunction(); // This also compiles! +``` + +Some valid usages of `any` might be: facilitating code migration from JavaScript to TypeScript, leveraging third-party code without types, and working with input of completely unknown structure. + +## Tuples + +Sometimes you may have an array whose elements are of different types. This is usually not encouraged, but it is possible. TypeScript allows type definitions for mixed arrays or tuples. You could even have an array of tuples. + +```ts +// Tuple +let person: [number, string, boolean] = [1, "Alice", true]; +// Tuple Array +let employees: [number, string][]; +employees = [ + [1, "Alice"], + [2, "Johnny"], + [3, "Davis"], +]; +``` + +If you're wondering how is a tuple different from an `any[]`, tuples have a fixed type for each element even if not the same type for all elements. But when you state an array of `any` there could be as many different elements of different types. + +```ts +// This tuple would give an error because the third element +//is expected to be a boolean but is assigned a string +let employee: [number, string, boolean] = [1, "Alice", "Developer"]; +// These cases are all acceptable because +// the elements be of any type +let manager: any[]; +manager = [3, "Hello", true, "Angela"]; +manager = [1, 2, 3]; +manager = [false, "Hello"]; +``` + +## Functions + +Functions are the primary means of passing data around in JavaScript. TypeScript allows you to specify the types of both the input and output values of functions. In TypeScript, you can also use both the `function` keyword or arrow functions, but you must add types to the parameters. And where required you can add return type annotations too. + +```ts +// Function keyword +function add(x: number, y: number): number { + return x + y; +} + +// Arrow function +const add = (x: number, y: number): number => { + return x + y; +}; +``` + +Note the addition of three number types: the two parameters `x`, `y`, and the return type `number`. You may omit the return type sometimes if TypeScript can infer it, but it's also good practice to keep it in so that readers of your functions, such as your teammates, can immediately know at a glance what type should be returned from the function. + +It should be noted that in TypeScript every parameter is required unless specified by adding a `?` after the parameter. In JavaScript, if a function has three declared parameters, you can choose not to provide them, and they will take the value of `undefined`. This is not the case in TypeScript. + +```ts +// Return both the first name and last name if the last name is provided, +// otherwise return only the first name. +function makeName(firstName: string, lastName?: string) { + if (lastName) { + return firstName + " " + lastName; + } else { + return firstName; + } +} +``` + +In the example above, the second parameter, `lastName`, is optional. This is because it is written as `lastName?: string`. Note that this is equivalent to declaring it as `lastName: string | undefined` (the question mark is equivalent syntax). + +### Anonymous functions + +Anonymous functions are a little bit different from function declarations. When a function appears in a place where TypeScript can determine how it's going to be called, the parameters of that function are automatically given types. + +```ts +// No type annotations here, but TypeScript can spot the bug +const names = ["Alice", "Bob", "Eve"]; + +// Contextual typing for function +names.forEach(function (s) { + console.log(s.toUppercase()); +}); + +// Contextual typing also applies to arrow functions +names.forEach((s) => { + console.log(s.toUppercase()); +}); +``` + +TypeScript would flag an error `Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?` in the above example. Even though the parameter `s` didn't have a type annotation, TypeScript used the types of the `forEach` function, along with the inferred type of the array, to determine the type `s` will have. This process is called contextual typing because the context that the function occurred within informs what type it should have. + +We learned how to write types on a function, but it's very common in JavaScript to pass functions as values. For example, using `map`, `reduce`, or any type of callback, a function accepts another function as a parameter. Let's look at how to write the type of such a function. + +Consider a function that takes another function that operates on numbers (consider this a version of `map`, that, for the sake of example, only works on numbers). + +```ts +// Takes a list of numbers and applies a processor function to each number +function mapNumbers(nums: number[], fn: (x: number): number) { + return nums.map(fn); +} +``` + +Note the syntax here to declare a function type. You must add the parameter names, even in the types. The parameter `fn` has the type `(x: number): number`. It takes one parameter `x` of type `number`, and it returns a `number` as a result. + +## Unions + +A union type is a type formed from two or more other types, representing values that may be any one of those types. We refer to each of these types as the union's members. + +```ts +let id: string | number; +// This is valid +id = 22; +// This is also valid +id = "22"; +``` + +It's easy to provide a value matching a union type - simply provide a type matching any of the union's members. If you have a value of a union type, how do you work with it? TypeScript will only allow an operation if it is valid for every member of the union. For example, if you have the union `string | number`, you can't use methods that are only available on `string`: + +```ts +function printId(id: number | string) { + console.log(id.toUpperCase()); +Property 'toUpperCase' does not exist on type 'string | number'. + Property 'toUpperCase' does not exist on type 'number'. +} +``` + +The solution is to narrow the union with code, the same as you would in JavaScript without type annotations. Narrowing occurs when TypeScript can deduce a more specific type for a value based on the structure of the code. For example, TypeScript knows that only a `string` value will have a `typeof` value `"string"`: + +```ts +function printId(id: number | string) { + if (typeof id === "string") { + // In this branch, id is of type 'string' + console.log(id.toUpperCase()); + } else { + // Here, id is of type 'number' + console.log(id); + } +} +``` + +## Objects + +Apart from primitives, the most common sort of type you'll encounter is an object type. This refers to any JavaScript value with properties, which is almost all of them! To define an object type, we simply list its properties and their types. + +For example, here's a function that takes a point-like object: + +```ts +// The parameter's type annotation is an object type +function printCoord(pt: { x: number; y: number }) { + console.log("The coordinate's x value is " + pt.x); + console.log("The coordinate's y value is " + pt.y); +} +printCoord({ x: 3, y: 7 }); +``` + +Here, we annotated the parameter with a type with two properties - `x` and `y` - which are both of type `number`. You can use `,` or `;` to separate the properties, and the last separator is optional either way. The type part of each property is also optional. If you don't specify a type, it will be assumed to be `any`. + +Object types can also specify that some or all of their properties are optional. To do this, add a `?` after the property name: + +```ts +function printName(obj: { first: string; last?: string }) { + // ... +} +// Both OK +printName({ first: "Bob" }); +printName({ first: "Alice", last: "Alisson" }); +``` + +In JavaScript, if you access a property that doesn't exist, you'll get the value undefined rather than a runtime error. Because of this, when you read from an optional property, you'll have to check for undefined before using it. + +```ts +function printName(obj: { first: string; last?: string }) { + // Error - might crash if 'obj.last' wasn't provided! + console.log(obj.last.toUpperCase()); + + if (obj.last !== undefined) { + // OK + console.log(obj.last.toUpperCase()); + } + + // A safe alternative using modern JavaScript syntax: + console.log(obj.last?.toUpperCase()); +} +``` + +## Type Aliases + +We've been using object types and union types by writing them directly in type annotations. This is convenient, but it's common to want to use the same type more than once and refer to it by a single name. A type alias is exactly that - a name for any type. The syntax for a type alias is: + +```ts +type Point = { + x: number; + y: number; +}; + +function printCoord(pt: Point) { + console.log("The coordinate's x value is " + pt.x); + console.log("The coordinate's y value is " + pt.y); +} + +printCoord({ x: 100, y: 100 }); +``` + +## Null and Undefined + +JavaScript has two primitive values used to signal absent or uninitialized values: `null` and `undefined`. TypeScript has two corresponding types by the same names. How these types behave depends on whether you have the `strictNullChecks` option on or off. We'll learn more about how to configure this setting in a later section of this module. + +With `strictNullChecks` off, values that might be `null` or `undefined` can still be accessed normally, and the values `null` and `undefined` can be assigned to a property of any type. This is similar to how languages without null checks (e.g. C#, Java) behave. The lack of checking for these values tends to be a major source of bugs; it is always recommended to turn `strictNullChecks` on if it's practical to do so in their codebase. + +With `strictNullChecks` on, when a value is `null` or `undefined`, you will need to test for those values before using methods or properties on that value. Just like checking for `undefined` before using an optional property, we can use narrowing to check for values that might be null: + +```ts +function doSomething(x: string | null) { + if (x === null) { + // do nothing + } else { + console.log("Hello, " + x.toUpperCase()); + } +} +``` + +TypeScript also has a special syntax for removing `null` and `undefined` from a type without doing any explicit checking. Writing `!` after any expression is effectively a type assertion that the value isn't `null` or `undefined`: + +```ts +function liveDangerously(x?: number | null) { + // No error + console.log(x!.toFixed()); +} +``` + +## Enums + +Enums are a feature added to JavaScript by TypeScript which allows for describing a value that could be one of a set of possible named constants. Unlike most TypeScript features, this is not a type-level addition to JavaScript but something added to the language and runtime. Because of this, it's a feature that you should know exists, but maybe hold off on using it unless you are sure. + +```ts +// Up is initialized with 1 +// All of the following members are auto-incremented from that point on +// Up = 1 Down = 2 Left = 3 Right = 4 +enum Direction1 { + Up = 1, + Down, + Left, + Right, +} + +// String enum with all string values defined +enum Direction2 { + Up = "Up", + Down = "Down", + Left = "Left", + Right = "Right", +} + +// Number enum +enum UserResponse { + No = 0, + Yes = 1, +} + +// heterogeneous enum +enum BooleanLikeHeterogeneousEnum { + No = 0, + Yes = "YES", +} +``` + +## Conclusion + +You would mostly find yourself using primitive types, arrays, objects, and functions in your everyday code. TypeScript powers all of these elements with static typing and type checking. You have now learned the syntax for type annotations and assertions. You have also learned about how TypeScript infers types and applies contextual typing. You can get creative and use Tuples, Unions, Enums, and Any types but of course, these require a lot more thought and consideration put in first. You can also create your own type aliases and reuse them wherever required across the codebase. With that, let's prepare ourselves to look at more complex and advanced types in the next lesson. + +--- + +## References + +- https://www.typescriptlang.org/docs/handbook/2/everyday-types.html +- https://www.youtube.com/watch?v=BCg4U1FzODs&ab_channel=TraversyMedia +- https://dev.to/hiro9108/javascript-vs-typescript-why-we-should-learn-typescript-4d5o diff --git a/module8-typescript/r1.2-advanced-types/README.md b/module8-typescript/r1.2-advanced-types/README.md new file mode 100644 index 0000000..fbc0f50 --- /dev/null +++ b/module8-typescript/r1.2-advanced-types/README.md @@ -0,0 +1,191 @@ +# Advanced Types + +We have learned quite a bit about Types so far, but when it comes to large-scale projects there are more advanced types that help us write more robust code which will dive into now. The objectives of this lesson are: + +1. Viewing practical usage examples of advanced Types +2. Understanding when to use advanced Types + +## Interfaces + +An interface declaration is another way to name an object type. Interfaces can be used interchangeably with type aliases and simple object types. + +```ts +interface Point { + x: number; + y: number; +} + +function printCoord(pt: Point) { + console.log("The coordinate's x value is " + pt.x); + console.log("The coordinate's y value is " + pt.y); +} + +printCoord({ x: 100, y: 100 }); +``` + +Like when we used a type alias above, the example works just as if we had used an anonymous object type. TypeScript is only concerned with the structure of the value we passed to `printCoord` - it only cares that it has the expected properties. + +You can also define properties in an interface to be optional using `?` or non-editable by specifying `readonly`. + +```ts +interface UserInterface { + readonly id: number; + name: string; + age?: number; +} + +const user1: UserInterface = { + id: 1, + name: "John", +}; +``` + +Interfaces can be used with functions as well. + +```ts +interface MathFunc { + (x: number, y: number): number; +} + +const add: MathFunc = (x: number, y: number): number => x + y; +const sub: MathFunc = (x: number, y: number): number => x - y; +``` + +## Classes + +TypeScript offers full support for the class keyword introduced in ES2015. As with other JavaScript language features, TypeScript adds type annotations and other syntax features to allow you to express relationships between classes and other types. Just like any other OOP language, classes have members or fields and a constructor function is used to instantiate the objects of this class with initial field values. Classes can also have member functions. + +```ts +// Class with constructor +class Person { + id: number; + name: string; + + constructor(id: number, name: string) { + this.id = id; + this.name = name; + } + + greet(message: string) { + console.log(message + this.name); + } +} + +const alice = new Person(1, "Alice Green"); +alice.greet("Hello"); +``` + +You can use an `implements` clause to check that a class satisfies a particular interface. + +```ts +interface PersonInterface { + id: number; + name: string; + register(): string; +} + +class Person implements PersonInterface { + id: number; + name: string; + + constructor(id: number, name: string) { + this.id = id; + this.name = name; + } + + register() { + console.log(`${this.name} is now registered`); + } +} + +const alice = new Person(1, "Alice Green"); +const mike = new Person(2, "Mike Jordan"); + +alice.register(); +mike.register(); +``` + +Classes may extend from a base class. A derived class has all the properties and methods of its base class, and also defines additional members. + +```ts +class Employee extends Person { + position: string; // additional member of this subclass + + constructor(id: number, name: string, position: string) { + super(id, name); + this.position = position; + } +} + +const emp = new Employee(3, "Shawn", "Developer"); +emp.register(); +``` + +A field of a class can be one of the following: `public`, `private`, `protected`, or +`readonly`. + +- `public`: This field can be read to and written as normal. +- `private`: Only accessible by the instance of the class. For example, this variable cannot be accessed by any code other than the functions in the class. +- `protected`: Similar to `private`, but subclasses can access the field. +- `readonly`: This field can only be read, but it can never be assigned or have its value changed (similar to `const`). + +By default, all class members are `public` but you can apply other data modifiers like `private` and `protected` to control member visibility. Protected members are only visible to subclasses of the class they're declared in. Private is like Protected but doesn't allow access to the member even from subclasses. + +In general, it is considered good practice in coding to use the minimal visibility required. For example, if you never plan to write to the field, you should start with `readonly`. If you find that you need to write to the field, but only in the code in the class, you should use `private`. Usage of `protected` is rare. In most cases, well-structured code will have most instance variables of a class as `private`. + +We've tried to cover the basics of Classes here. You can read a lot more in detail [on the TypeScript handbook](https://www.typescriptlang.org/docs/handbook/2/classes.html). + +## Generics + +Generics allow us to create reusable and flexible components which can work over a variety of types rather than a single one. This allows users to consume these components and use their types. + +```ts +// Without generics +function getArray(items: any[]): any[] { + return new Array().concat(items); +} + +let numArray = getArray([1, 2, 3, 4]); +let strArray = getArray(["alice", "dave", "mike"]); + +// With generics +function getArray(items: T[]): T[] { + return new Array().concat(items); +} + +let numArray = getArray([1, 2, 3, 4]); +let strArray = getArray(["alice", "dave", "mike"]); +``` + +The drawback of using `any[]` is that something like `numArray.push('hello')` would not throw an error, but when you use generics it acts as a placeholder with types defined and applied when creating variables from the generic. + +You can read more about generics and considerations for using this feature of TypeScript on [The TypeScript handbook](https://www.typescriptlang.org/docs/handbook/2/generics.html). + +## Decorators + +With the introduction of Classes in TypeScript and ES6, there now exist certain scenarios that require additional features to support annotating or modifying classes and class members. Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. Decorators are a stage 2 proposal for JavaScript and are available as an experimental feature of TypeScript. + +A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use the form `@expression`, where `expression` must be a function that will be called at runtime with information about the decorated declaration. For example, given the decorator `@sealed` we might write the `sealed` function as follows: + +```ts +function sealed(target) { + // do something with 'target' ... +} +``` + +You can read more about Decorators in detail [on the TypeScript handbook](https://www.typescriptlang.org/docs/handbook/decorators.html). You will most likely not use this in everyday projects as it is a very experimental feature, so we have only paraphrased the basics from the handbook and made you aware of the existence of this advanced type. + +## Conclusion + +Now we have taken a look at basic everyday types as well as complex advanced types. Were you able to visualize how these types being applied could help in reducing bugs in our code? Slowly you will start to get the hang of TypeScript with more practice. Let us now explore how the TypeScript compiler works in the next lesson. + +--- + +## References + +- https://www.youtube.com/watch?v=BCg4U1FzODs&ab_channel=TraversyMedia +- https://www.typescriptlang.org/docs/handbook/2/classes.html +- https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces +- https://www.typescriptlang.org/docs/handbook/2/generics.html +- https://www.typescriptlang.org/docs/handbook/decorators.html +- https://gist.github.com/bradtraversy/f80a4cd87e7034bea5264f7d8c431b4e diff --git a/module8-typescript/r1.3-typescript-compiler/README.md b/module8-typescript/r1.3-typescript-compiler/README.md new file mode 100644 index 0000000..f5cc6c2 --- /dev/null +++ b/module8-typescript/r1.3-typescript-compiler/README.md @@ -0,0 +1,86 @@ +# TypeScript Compiler + +Now that we know so much about what TypeScript syntax looks like, we will learn about the TypeScript compiler. The objectives of this lesson are: + +1. Installing and using the TypeScript compiler +2. Viewing compiled JS output for TS code +3. Understanding the configuration and use of the compiler config file + +## What is a compiler? + +In case you haven't heard about "compilers" before or are unsure about the term, A compiler is a special program that translates a programming language's source code into machine code, bytecode, or another programming language. The source code is typically written in a high-level, human-readable language such as Java or C++. A programmer writes the source code in a code editor or an integrated development environment (IDE) that includes an editor, saving the source code to one or more text files. A compiler that supports the source programming language reads the files, analyzes the code, and translates it into a format suitable for the target platform. + +Sometimes the term "transpiler" is used interchangeably with compiler, but they are not exactly the same. Transpilers, or source-to-source compilers, are tools that read the sourcecode written in one programming language and produce the equivalent code in another programming language with a similar level of abstraction. And TypeScript is a good example of a transpiler as it converts TypeScript code to JavaScript. Similarly, Babel transpiler can also be used for converting the ES6 JS code to ES5 JS sourcecode. Compilers also convert the code from one language to another language but both languages are very different in abstraction level. For example, Java compiler converts the `.java` file to `.class` file. + +Strictly speaking, TypeScript is _transpiled_ to JavaScript. However, most developers and Microsoft itself refer to the tool that does this as "TypeScript Compiler". That said, don't fret too much about the loose usage of the terms compiler and compilation. As long as what's actually happening is clear from the context, it doesn't really matter which term is used — the message still gets through. Transpilers are also called source-to-source compilers, so "TypeScript Compiler" could also be considered short for "TypeScript to JavaScript Compiler". + +## Installing and using the compiler + +To install and start using the TypeScript Compiler or `tsc` on your machine, you can do a global npm package installation. + +```bash +npm i -g typescript +``` + +Then you can verify the installation by checking for the compiler version. + +```bash +tsc -v +``` + +Now you can start writing TypeScript code in any `.ts` file. Let's say you wrote some code in a file called `index.ts`. All you need to do to compile to JavaScript is: + +```bash +tsc index +``` + +You will see that TypeScript creates a JS file of the same name `index.js` with the transpiled JS code. If there were any errors found during compilation, they would get flagged in the terminal. But if you're using a modern editor like VSCode, you can find errors being flagged by the IDE itself and even auto-complete recommendations showing up to prevent you from making type errors. + +You can open up the transpiled JS file and read through the code. Depending on how complex your TS file was or how many lines of code it had, the transpiled JS file may or may not be easily readable. But just a skim through the generated JS files still gives an idea of how the TypeScript Compiler works. + +You can also simply run the command `tsc` if you have more than one target TS file to be compiled and it will automatically search for TS files in the project folder and transpile them. You can also run TypeScript Compiler in watch mode using `tsc --watch` and it will watch for file changes, re-compile and hot reload. + +## TypeScript Compiler Configuration + +TypeScript uses a configuration file in the project folder to follow any custom rules or options you would like to set. To generate this file, just run: + +```bash +tsc --init +``` + +This will immediately create a `tsconfig.json` file in your project folder. You'll see that this file contains a property called `compilerOptions` with lots and lots of options mostly commented out. You can read through the comments or visit the TypeScript docs to learn about these options, but no need to worry about memorizing these. In most of your projects, you might have to adjust just a few properties here and there. + +```json +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "target": "es6", + "noImplicitAny": true, + "moduleResolution": "node", + "sourceMap": true, + "outDir": "dist", + "baseUrl": ".", + "paths": { + "*": ["node_modules/*"] + } + }, + "include": ["src/**/*"] +} +``` + +For example, you might see the `target` property is set by default to `"es5"`. This results in `var` being used in the output JS files. You may change this to `"es6"` to enable use of `let` and `const` and other ES6 syntax features. + +You can configure the `outDir` and `rootDir` properties and provide paths to your desired output directory and input directory. So then you could have a `src` directory and a `dist` directory in your project structure to separate source code and production code. + +## Conclusion + +You can read more about the `tsconfig.json` file [here](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) but it is really not that complicated. This lesson intends to give you an idea about how the TypeScript compiler works and you can possibly visualize a little bit of what is happening under the hood. You can also find many online TypeScript IDEs, playgrounds, and compilers that let you try out TS code and view the compiled JS output, [here](https://www.codingrooms.com/compiler/typescript) is one. We will now move into looking at TypeScript in practice with Node and Express. + +--- + +## References + +- https://www.techtarget.com/whatis/definition/compiler +- https://howtodoinjava.com/typescript/transpiler-vs-compiler/ +- https://www.youtube.com/watch?v=BCg4U1FzODs&t=669s&ab_channel=TraversyMedia diff --git a/module8-typescript/r2-typescript-node-express/README.md b/module8-typescript/r2-typescript-node-express/README.md new file mode 100644 index 0000000..56d0318 --- /dev/null +++ b/module8-typescript/r2-typescript-node-express/README.md @@ -0,0 +1,130 @@ +# TypeScript with Node and Express + +We took some time to understand the TypeScript syntax and how it makes our code better, so let us come back to the backend and how TypeScript can be used in backend code. We have been learning to build backend servers using Node.js and Express.js where we've used JavaScript syntax thus far. So how can we use TypeScript code in an Express server and how do we ensure it is getting compiled correctly? That is what we will learn now. The objectives of this lesson are: + +1. Setting up TypeScript with Node and Express +2. Viewing practical usage of TypeScript in backend codebases +3. Understanding extended types in Express + +## Setting up + +We'll be walking through a workflow for setting up TypeScript with Node and Express. Firstly, make sure TypeScript is installed globally on your machine. + +```bash +npm i -g typescript +``` + +Then we create a new project folder and initialize the `package.json` file just like we do for our regular Node Express projects. + +```bash +mkdir node-express-typescript +cd node-express-typescript/ +npm init --yes +``` + +We will also set up the `tsconfig.json` file. + +``` +tsc --init +``` + +On this file the main configurations required are: + +```json +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "outDir": "./dist", + "srcDir": "./src", + "strict": true, + "moduleResolution": "node" + } +} +``` + +Now we'll create our source folder with an `app.ts` file. + +```bash +mkdir src +cd src +touch app.ts +``` + +Next, we install Express and a few dev dependencies for TypeScript. + +```bash +npm i express +npm i -D nodemon typescript ts-node @types/node @types/express +``` + +We will add a few scripts to our `package.json` file. + +```json +{ + "scripts": { + "start": "node dist/app.js", + "dev": "nodemon src/app.ts", + "build": "tsc -p ." + } +} +``` + +And now we are ready to build an Express application with TypeScript and incorporate custom types for Node and Express. + +## Building Express application with TypeScript + +Let's start out by building a simple Express server, which has been the first step in all our projects so far. We add these lines to the `app.ts` file. + +```js +import express from "express"; + +const app = express(); + +app.get("/", (req, res) => { + res.send("Express TypeScript Server"); +}); + +app.listen(5000, () => console.log("Server running")); +``` + +Now if we run `npm run dev` we should see our Express server running in watch mode. + +Now let's add in some meaningful types in our Express server code. We'll use the custom Express types - Application, Request, Response, and NextFunction. + +```ts +import express, { Application, Request, Response, NextFunction } from "express"; + +const app: Application = express(); + +app.get("/", (req: Request, res: Response, next: NextFunction) => { + res.send("Express TypeScript Server"); +}); + +app.listen(5000, () => console.log("Server running")); +``` + +And then we can also have any functions with types that can be called in the handler functions for our endpoints. + +```ts +const add = (x: number, y: number): number => x + y; +``` + +You can use Interfaces, Object types, Classes, or any other Types from TypeScript. + +You can anytime look at the compiled JS files in the dist folder and see what your TypeScript code gets compiled to. + +And when you're ready to deploy the JS code to the server, you can run `npm start` on the server. + +## Conclusion + +TypeScript can make work on your backend code a little bit easier by helping you easily spot type errors and avoid running into unexpected code execution at runtime. If you're working with a team, it also makes the codebase very readable and enforces guidelines for defining types on all variables and functions. We hope you'll try to use TypeScript in some of your Express projects and share your experience of working with static typing. We are now approaching the end of this module, so in the next lesson, we'll be looking a bit beyond Express.js at other frameworks which already incorporate TypeScript. + +--- + +## References + +- https://blog.logrocket.com/how-to-set-up-node-typescript-express/ +- https://www.valentinog.com/blog/typescript/#dipping-our-toes-into-typescript-types +- https://dev.to/macmacky/get-better-with-typescript-using-express-3ik6 +- https://www.youtube.com/watch?v=zRo2tvQpus8&t=623s&ab_channel=TraversyMedia diff --git a/module8-typescript/r2.1-backend-frameworks-typescript/README.md b/module8-typescript/r2.1-backend-frameworks-typescript/README.md new file mode 100644 index 0000000..5ac5fe3 --- /dev/null +++ b/module8-typescript/r2.1-backend-frameworks-typescript/README.md @@ -0,0 +1,115 @@ +# Backend frameworks with TypeScript + +We have been working with the Express framework and have understood the use of TypeScript syntax in it. However, there are open-source frameworks that are built directly using TypeScript even though Express is still one of the most popular frameworks and is actually even the foundation of newly built frameworks. The objectives of this lesson are: + +1. Looking at other frameworks that use TypeScript inherently +2. Understanding Nest.js and TypeORM frameworks + +## Backend frameworks using TypeScript + +In a previous lesson, we had mentioned [frameworks built on top of Express.js](https://expressjs.com/en/resources/frameworks.html). Some of these frameworks are powered exclusively by TypeScript. + +1. [FoalTS](https://foalts.org/): Considered to be the elegant NodeJS framework, it provides a set of ready-to-use components so you don't have to reinvent the wheel every time. In one single place, you have a complete environment to build web applications. This includes a CLI, testing tools, frontend utilities, scripts, advanced authentication, ORM, deployment environments, GraphQL and Swagger API, AWS utilities, and more. The framework is entirely written in TypeScript. The language brings you optional static type-checking along with the latest ECMAScript features. This allows you to detect the silliest errors during compilation and improve the quality of your code. It also offers you autocompletion and a well-documented API. + +2. [NestJS](https://nestjs.com/): Described as a progressive Node.js framework, uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript), and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming) all of which helps for building efficient, scalable Node.js server-side applications. Nest aims to provide an application architecture out of the box which allows for the effortless creation of highly testable, scalable, loosely coupled, and easily maintainable applications. The architecture is heavily inspired by AngularJS. + +3. [Expressive Tea](https://expressive-tea.io/): For building module-oriented, clean, fast, and descriptive server-side applications with TypeScript and Express out of the box. It is a flexible framework but also gives freedom to the developer to build their own architectures by providing descriptive decorators, a plugin engine, shareable modules, and modern Javascript. + +4. [Prisma](https://www.prisma.io/): Described as a next-generation Node.js and TypeScript ORM, it helps app developers build faster and make fewer errors with an open source database toolkit for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB, and CockroachDB. + +5. [TypeORM](https://typeorm.io/): Can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript and JavaScript (ES5, ES6, ES7, ES8). Its goal is to always support the latest JavaScript features and provide additional features that help you to develop any kind of application that uses databases - from small applications with a few tables to large-scale enterprise applications with multiple databases. + +6. [RxJS](https://rxjs.dev/): A Reactive Extensions Library for JavaScript, useful for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code. + +7. [AdonisJS](https://adonisjs.com/): A fully featured web framework for Node.js, it includes everything you need to create a fully functional web app or an API server and does not require wasting hours downloading and assembling hundreds of packages. + +## NestJS + +[Here](https://www.youtube.com/watch?v=0M8AYU_hPas&ab_channel=TraversyMedia) is a 100-second video on NestJS by Fireship for a quick overview. + +NestJS is a Node.js framework that's intended for use with TypeScript to build efficient and scalable server-side applications. This is a web application that mainly relies on strong HTTP server frameworks like Express or Fastify. Nest is a new Node.js framework that not only imitates but also corrects the flaws of previous Node.js frameworks. + +### Few of the great features of NestJS + +1. Nest.js was created to help developers create Monoliths and Microservices. +2. It's simple to use, quick to learn, and easy to apply. +3. It leverages TypeScript. +4. Powerful Command Line Interface (CLI) to boost productivity and ease of development. +5. Support for dozens of nest-specific modules that help you easily integrate with common technologies and concepts like TypeORM, Mongoose, GraphQL, Logging, Validation, Caching, WebSockets, and much more. +6. Easy unit-testing applications. +7. Great documentation. +8. Built for large-scale enterprise applications. + +### Core Components of NestJS + +1. **Controllers** are responsible for handling incoming requests and responding to the application's client-side. +2. **Modules** are used to structure code and separate functionality into logical, reusable chunks. +3. **Providers or services** which abstract complexity and logic away from the user. It's possible to inject the service into controllers or other services. + +[Here](https://www.freecodecamp.org/news/build-web-apis-with-nestjs-beginners-guide/) is a freeCodeCamp tutorial on how to build APIs with NestJS, Postgres, and Sequelize. + +## TypeORM + +[Here](https://javascript.plainenglish.io/creating-a-rest-api-with-jwt-authentication-and-role-based-authorization-using-typescript-fbfa3cab22a4#:~:text=Why%20TypeORM%3F,model%20class%20to%20make%20validations.) is an article mentioning a strong reason why you should learn and use TypeORM. + +TypeORM leverages TypeScript to write database integration code and is compatible with MySQL / MariaDB / Postgres / SQLite / Microsoft SQL Server / Oracle / sql.js / MongoDB. You can switch between those databases without having to rewrite your code. + +### Few of the great features of TypeORM + +1. Supports DataMapper and ActiveRecord patterns +2. Entities and columns and Entity manager +3. Database-specific column types +4. Repositories and custom repositories. +5. Clean object-relational model and Associations (relations) +6. Eager and lazy relations. Uni-directional, bi-directional and self-referenced relations. +7. Supports multiple inheritance patterns. +8. Cascades, Indices, and Transactions. +9. Migrations and automatic migrations generation. +10. Connection pooling and Replication. +11. Using multiple database instances. +12. Working with multiple database types and Cross-database and cross-schema queries. +13. Elegant syntax, flexible and powerful QueryBuilder. +14. Left and inner joins. +15. Proper pagination for queries using joins. +16. Query caching. +17. Streaming raw results and Logging. +18. Listeners and subscribers (hooks). +19. Supports closure table pattern. +20. Schema declaration in models or separate configuration files. +21. Connection configuration in json / xml / yml / env formats. +22. Produced code is performant, flexible, clean, and maintainable. +23. Follows all possible best practices. + +With TypeORM your models look like this: + +```ts +import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"; + +@Entity() +export class User { + @PrimaryGeneratedColumn() + id: number; + + @Column() + firstName: string; + + @Column() + lastName: string; + + @Column() + age: number; +} +``` + +[Here](https://orkhan.gitbook.io/typeorm/docs/example-with-express) is a tutorial on using TypeORM with Express. + +## Conclusion + +When it comes to Node.js with TypeScript, there is much more beyond Express. While Express is still very popular and widely used in the industry, it is great to be flexible and adapt to working with a new framework if you're asked to in your career as a developer. It is also interesting to study how these frameworks were built and what is the problem they are trying to solve. Although sometimes it can feel like there is a JS framework for literally everything under the sun, take it one step at a time and identify just one or two frameworks to invest your time in learning. We recommend NestJS after you've mastered ExpressJS. + +--- + +## References + +- https://nodejs.dev/learn/nodejs-with-typescript +- https://enlear.academy/why-you-should-use-nestjs-as-your-backend-framework-bd1ff1acce5d diff --git a/module8-typescript/r2.2-typescript-cart/README.md b/module8-typescript/r2.2-typescript-cart/README.md new file mode 100644 index 0000000..7522d6f --- /dev/null +++ b/module8-typescript/r2.2-typescript-cart/README.md @@ -0,0 +1,3 @@ +# TypeScript Cart + +[Assignment repo link](https://github.com/ReCoded-Org/curriculum-backend-typescript-cart) \ No newline at end of file diff --git a/module8-typescript/r2.3-nestjs-task-management/README.md b/module8-typescript/r2.3-nestjs-task-management/README.md new file mode 100644 index 0000000..d173c2e --- /dev/null +++ b/module8-typescript/r2.3-nestjs-task-management/README.md @@ -0,0 +1,3 @@ +# NestJS Task Management App + +[Assignment repo link](https://github.com/ReCoded-Org/curriculum-backend-nestjs-task-managmentt) \ No newline at end of file diff --git a/module8-typescript/r3-summary/README.md b/module8-typescript/r3-summary/README.md new file mode 100644 index 0000000..b9d8cb3 --- /dev/null +++ b/module8-typescript/r3-summary/README.md @@ -0,0 +1,5 @@ +# Summary + +We hope you enjoyed learning TypeScript with us and now when you see a codebase full of `.ts` files you will not feel confused. You can also market yourself as a junior developer familiar with TypeScript which would be very valuable for companies looking to hire. + +To further enhance your learning, you can explore GitHub for open source TypeScript projects so that you can skim through a rich codebase and look at Types in action. Sometimes for small projects and assignments as a beginner it may feel like TypeScript is too overwhelming or completely unnecessary. To see it in a larger and more complex codebase puts things into perspective. And not only TypeScript, but for any new concept that you learn you can always search for open source repositories and use them as a learning resource. There is a lot to learn from the open source community. And continuous learning helps keep the mind flexible and not get too attached to a single language or framework.