https://github.com/sk-azraf-sami/learn-typescript
I made this note by following the tutorial of 'Dave Gray' on YouTube and also took help from chatgpt to make it more organize and readable.
https://github.com/sk-azraf-sami/learn-typescript
documentation javascript note notes type-safe type-safety typescript
Last synced: about 2 months ago
JSON representation
I made this note by following the tutorial of 'Dave Gray' on YouTube and also took help from chatgpt to make it more organize and readable.
- Host: GitHub
- URL: https://github.com/sk-azraf-sami/learn-typescript
- Owner: Sk-Azraf-Sami
- Created: 2025-05-11T11:04:44.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-20T11:08:14.000Z (about 1 year ago)
- Last Synced: 2025-06-24T18:48:24.637Z (about 1 year ago)
- Topics: documentation, javascript, note, notes, type-safe, type-safety, typescript
- Language: TypeScript
- Homepage:
- Size: 259 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
## Table of Contents
- [Basic Concepts & Types](#basic-concepts--types)
- [Arrays, Tuples, and Type Safety](#arrays-tuples-and-type-safety)
- [Object](#object)
- [Advanced Types & Functions](#advanced-types--functions)
- [Type Assertions, Unknown, and DOM Handling](#type-assertions-unknown-and-dom-handling)
- [OOP, Interfaces, Index Signatures, and Records](#oop-interfaces-index-signatures-and-records)
- [Generics](#generics)
- [Utility Types](#utility-types)
---
## [Basic Concepts & Types](#basic-concepts--types)
### β
1. Variable Declaration with Type Inference
```ts
let username = 'Sami';
console.log(username);
```
* TypeScript automatically infers the type of `username` as `string` because it's initialized with a string.
* This is called **type inference** β TypeScript assigns a type based on the value provided.
---
### π’ 2. Explicit Type Annotation
```ts
let a: number = 12;
// let b: string = "6";
let b: number = 6;
let c: number = 10;
console.log(a / b);
```
* You can explicitly define the type of a variable using `: type`.
* Here, `a`, `b`, and `c` are explicitly set to type `number`.
* TypeScript will throw an error if you try to assign a value of a different type (e.g., uncommenting `b: string = "6"`).
---
### π€ 3. Type Safety
```ts
let myname = 'azraf';
// myname = 83;
```
* TypeScript infers `myname` as `string`.
* If you try to assign a number to `myname`, it results in a **type error**.
* This enforces **type safety** β helps prevent bugs caused by unexpected types.
---
### β 4. Function with Type Annotations
```ts
const sum = (a: number, b: number) => {
return a + b;
};
```
* Function parameters and return values can have types.
* This ensures correct usage and avoids type-related issues in function calls.
---
### π 5. The `any` Type
```ts
let album: any;
```
* The `any` type disables type checking for that variable.
* It can hold **any value**, such as string, number, object, etc.
* Use with caution β it sacrifices TypeScriptβs benefits.
---
### π 6. Union Types
```ts
let postId: string | number;
```
* A **union type** allows a variable to be one of multiple types.
* `postId` can be either a `string` or a `number`.
---
### π€ 7. Regular Expressions
```ts
let re: RegExp = /\w+/g;
```
* `RegExp` is a built-in type in TypeScript for regular expressions.
* `\w+` matches one or more word characters.
* The `g` flag stands for "global" (matches all occurrences).
---
## [Arrays, Tuples, and Type Safety](#arrays-tuples-and-type-safety)
### π 1. String Array
```ts
let stringArr = ['Dhaka', 'Bangladesh', 'Khulna'];
```
* TypeScript infers `stringArr` as `string[]`.
* All elements must be of type `string`.
```ts
// stringArr[0] = 115; β Error
```
* You cannot assign a `number` to an index of a `string[]` array.
---
### π 2. Mixed Type Array (Union Inference)
```ts
let mixArr = ['ntm', 83, 'sas', 115];
```
* TypeScript infers this as `(string | number)[]` β a union of `string` and `number`.
```ts
mixArr[0] = 1907; // β
OK
// mixArr.unshift(true); β Error
```
* You can reassign elements with either `string` or `number`.
* Adding a `boolean` (`true`) causes a type error, as `boolean` isnβt in the union.
---
### β οΈ 3. Array Type Compatibility
```ts
// stringArr = mixArr; β Error
mixArr = stringArr; // β
OK
```
* You **cannot assign** a union-typed array (with more types) to a strictly typed one (`string[]`).
* But assigning a `string[]` to a `(string | number)[]` is allowed β it's compatible because `string[]` is a subset of the union.
---
### π·οΈ 4. Explicit Array Typing
```ts
let stuName: string[] = [];
stuName.push('ntm');
```
* You can explicitly declare an arrayβs type using `type[]`.
* Here, only strings can be added to `stuName`.
---
### π¦ 5. Tuples β Fixed-Length & Fixed-Type Arrays
```ts
let myTuples: [string, number, boolean] = ['ntm', 83, true];
```
* A **tuple** defines:
* A fixed number of elements.
* Each element must be of a specific type **and position matters**.
```ts
let arrTest = ['ntm', 83, true];
arrTest = myTuples; // β
OK (tuple β array)
myTuples = arrTest; // β Error (array β tuple)
```
* You can assign a tuple to a normal array.
* But you **canβt assign** a regular array to a tuple unless its exact structure and types are guaranteed.
---
Great work! Here's the next part of your **TypeScript Notes**, now covering **Type Aliases**, **Function Types**, **Interfaces**, **Optional & Default Parameters**, **Rest Parameters**, and **the `never` Type** β with well-structured explanations.
---
## [Object](#object)
### πΉ Arrays Are Objects
```ts
let myObj: object;
myObj = []; // Valid: arrays are a type of object
myObj = {}; // Valid: plain object
console.log(typeof myObj); // 'object'
```
#### π‘ Explanation:
* In TypeScript (and JavaScript), arrays are technically objects.
* You can assign both arrays and plain objects to a variable of type `object`.
---
### πΉ Working with Object Types
#### Defining and Using Object Type
```ts
type Guitarist = {
name: string;
active: boolean;
album: (string | number)[];
};
let evh: Guitarist = {
name: 'Test',
active: false,
album: ['ntm', 115]
};
let jp: Guitarist = {
name: 'Test',
active: false,
album: ['ntm', 'sas', 115, 83]
};
evh = jp; // Valid assignment
```
#### π‘ Explanation:
* `type` lets you define custom object types.
* Here, `album` accepts an array of `string | number`.
---
### πΉ Optional Object Properties
```ts
type GuitaristOpt = {
name: string;
active?: boolean; // Optional property
album: (string | number)[];
};
let evhOpt: GuitaristOpt = {
name: 'Test',
active: false,
album: ['ntm', 115]
};
let jpOpt: GuitaristOpt = {
name: 'Test',
album: ['ntm', 'sas', 115, 83]
};
evhOpt = jpOpt; // Valid: 'active' is optional
```
#### π‘ Explanation:
* Optional properties (using `?`) allow you to omit them when creating objects.
---
### πΉ Using Object Types in Functions
```ts
const greetGuitarist = (guitarist: Guitarist) => {
return `Hello ${guitarist.name}!`;
};
```
#### π‘ Explanation:
* You can pass a custom object type into a function parameter.
* TypeScript ensures the object matches the type structure.
---
### πΉ Type vs Interface
```ts
type GuitaristTest = {
name: string;
active?: boolean;
album: (string | number)[];
};
interface GuitaristTest2 {
name: string;
active?: boolean;
album: (string | number)[];
}
```
#### π‘ Explanation:
* `type` and `interface` are mostly interchangeable for object shapes.
* Interfaces are preferred in large-scale OOP or when extending.
---
### πΉ Optional Chaining in Functions
```ts
interface Student {
name?: string;
roll: number;
}
const stu1: Student = { name: 'ntm', roll: 83 };
const stu2: Student = { roll: 115 };
const greetStudent = (student: Student) => {
return `Hello ${student.name?.toUpperCase()}`;
// Or with narrowing:
// if (student.name) {
// return `Hello ${student.name.toUpperCase()}`;
// }
// return `Hello`;
};
console.log(greetStudent(stu1)); // Hello NTM
console.log(greetStudent(stu2)); // Hello undefined
```
#### π‘ Explanation:
* Use optional chaining (`?.`) to safely access potentially undefined properties.
* Alternative: use conditional checks (narrowing).
---
### πΉ Enums in TypeScript
```ts
enum Grade {
A = 83,
B, // 84
C // 85
}
console.log(Grade.B); // 84
```
#### π‘ Explanation:
* Enums allow for named constants.
* If one member is initialized (`A = 83`), others increment by 1 automatically unless explicitly set.
---
## [Advanced Types & Functions](#advanced-types--functions)
### π 1. Type Aliases
```ts
type stringOrNumber = string | number;
type stringOrNumberArray = string | number[];
```
* **Type aliases** help you create custom names for union types or complex types.
* Useful for cleaner and more readable code.
---
### π₯ 2. Custom Object Types
```ts
type Member = {
ID: stringOrNumber;
Name: string;
Experience: stringOrNumberArray;
};
```
* The `Member` type uses other custom type aliases.
* Great for defining consistent structure across multiple objects.
---
### π§± 3. Literal Types
```ts
let myName = 'sami';
let userName: 'ntm' | 'sas';
userName = 'ntm'; // β
Allowed
```
* A **literal type** restricts a variable to exactly one or more allowed values.
* Acts like an enum without extra syntax.
---
### π§ 4. Functions with Type Annotations
#### Basic Functions
```ts
const add = (a: number, b: number): number => a + b;
const logMsg = (message: any): void => {
console.log(message);
};
```
* `:number` specifies return type.
* `:void` indicates the function **does not return a value**.
---
#### Function Expressions
```ts
let subtract = function(num1: number, num2: number): number {
return num1 - num2;
};
```
* Function expressions can also have type annotations.
---
### π§Ύ 5. Function Type Aliases & Interfaces
```ts
type mathFunction = (a: number, b: number) => number;
let multiply: mathFunction = (num1, num2) => num1 * num2;
```
```ts
interface mathFunction2 {
(a: number, b: number): number;
}
```
* Define function signatures using `type` or `interface` to enforce structure across function variables.
---
### β 6. Optional & Default Parameters
```ts
const addAll = (a: number, b: number, c?: number): number => {
return c !== undefined ? a + b + c : a + b;
};
const sumAll = (a: number, b: number, c: number = 2): number => {
return a + b + c;
};
```
* `c?: number` = **optional parameter** (can be omitted).
* `c: number = 2` = **default value** (used if not passed).
```ts
const sumAll2 = (a: number = 10, b: number, c: number = 2) => a + b + c;
```
* Default values can also be assigned to parameters other than the last, but usage must match carefully.
---
### π 7. Rest Parameters
```ts
const total = (...nums: number[]): number => {
return nums.reduce((prev, curr) => prev + curr);
};
```
* `...nums: number[]` = accepts any number of arguments into a single array.
* Perfect for aggregation and iteration.
---
### π« 8. The `never` Type
#### Throwing Errors
```ts
const createError = (errMsg: string): never => {
throw new Error(errMsg);
};
```
* `never` means the function **never returns** (due to error or infinite loop).
#### Infinite Loops (commented)
```ts
/* const infinite = () => {
let i: number = 1;
while (true) {
i++;
}
}; */
```
* This also returns `never` because it never terminates.
#### With Break (returns `void`)
```ts
const infinite = () => {
let i: number = 1;
while (true) {
i++;
if (i >= 100) break;
}
};
```
---
### β
9. Type Guards
#### Manual Type Checking
```ts
const numberOrStringFunc = (value: number | string): string => {
if (typeof value === 'number') return 'number';
if (typeof value === 'string') return 'string';
return createError('This should never happen');
};
```
* Type guards allow safe narrowing of union types.
#### Reusable Guard Function
```ts
const isNumber = (value: any): boolean => {
return typeof value === 'number';
};
const numberOrStringFunc2 = (value: number | string): string => {
if (isNumber(value)) return 'number';
if (typeof value === 'string') return 'string';
return createError('This should never happen');
};
```
* Improves readability and reusability by abstracting the guard logic.
---
## [Type Assertions, Unknown, and DOM Handling](#type-assertions-unknown-and-dom-handling)
### π§Ύ 1. Type Assertions (a.k.a. Type Casting)
```ts
type One = string;
type Two = string | number;
type Three = 'hello';
```
#### More to Less Specific (Widening)
```ts
let aa: One = 'ntm';
let bb = aa as Two; // β
Allowed: string β string | number
```
#### Less to More Specific (Narrowing)
```ts
let cc = aa as Three; // β
Allowed: string β 'hello' (but risky unless value matches exactly)
```
* TypeScript allows casting to more or less specific types using `as`.
* **β οΈ Warning**: This bypasses safety checks β you tell TypeScript "Trust me".
---
### π§© 2. JSX vs TypeScript Syntax for Assertions
#### Non-JSX (e.g. Angular, TS files):
```ts
let dd = 'sas';
let ee = 'ntm';
```
* β
Valid in `.ts` files (non-JSX).
* β Not allowed in `.tsx` (React uses angle brackets for JSX elements).
> In `.tsx`, always use `as` syntax instead.
---
### β 3. Return Value Assertion Example
```ts
const addOrConcat = (a: number, b: number, c: 'add' | 'concat'): number | string => {
if (c === 'add') return a + b;
return '' + a + b;
};
```
```ts
// β Error: TS can't guarantee return is a string
// let myVal: string = addOrConcat(2, 2, "concat");
let myVal: string = addOrConcat(2, 2, "concat") as string; // β
let myVal2: number = addOrConcat(2, 2, "concat") as number; // β οΈ Compiles, but incorrect!
```
* Type assertions **do not validate correctness** β use carefully!
* In `myVal2`, a `string` is forcibly treated as a `number`, which may cause runtime bugs.
---
### π΅οΈ 4. The `unknown` Type
```ts
// 10 as string; β Error
(10 as unknown) as string; // β
Allowed
```
* You can **double assert**: from any type to `unknown`, then to the desired type.
* Avoid unless absolutely necessary (used when dealing with third-party or very dynamic data).
---
### π 5. Working with the DOM
#### Non-null Assertion (`!`)
```ts
const myImg = document.querySelector('img')!; // Tells TS this will never be null
myImg.src;
```
* The `!` operator is the **non-null assertion** operator.
* Use with caution β TypeScript will **not warn** if `querySelector` returns `null`.
---
#### Type Casting DOM Elements
```ts
const img = document.getElementById('img') as HTMLImageElement;
img.src;
```
* You must **cast** DOM elements when accessing their specific properties (e.g., `.src` is not available on generic `HTMLElement`).
* This ensures TypeScript knows the correct element type.
---
### β οΈ Summary Tips
| Scenario | TypeScript Behavior |
| ---------------------------- | --------------------------------------- |
| `as` type assertions | Bypass type checking β be careful |
| `unknown` | Safer than `any`, forces type narrowing |
| DOM queries | Often return `HTMLElement` or `null` |
| Use `as HTMLImageElement` | To access image-specific properties |
| Avoid `as number` on strings | Could lead to silent logic errors |
---
This is an excellent and thorough overview of **advanced TypeScript concepts**, especially object-oriented programming and structural typing. Here's a structured summary of everything you've written for quick reference and learning:
---
## [OOP, Interfaces, Index Signatures, and Records](#oop-interfaces-index-signatures-and-records)
### 1οΈβ£ **Classes with Access Modifiers**
```ts
class CodeVis {
constructor(
public readonly name: string,
public music: string,
private age: number,
protected lang: string = 'BN'
) {}
public getAge() {
return `Hello! I am ${this.age}`;
}
}
```
| Modifier | Visibility |
| ----------- | -------------------------------------- |
| `public` | Accessible everywhere |
| `private` | Only inside the class |
| `protected` | Class + subclasses |
| `readonly` | Cannot be changed after initialization |
---
### 2οΈβ£ **Inheritance**
```ts
class WebDev extends CodeVis {
constructor(public computer: string, name: string, music: string, age: number) {
super(name, music, age);
}
public getLang() {
return `I write in ${this.lang}`;
}
}
```
---
### 3οΈβ£ **Interfaces & Implementation**
```ts
interface Musician {
name: string;
instrument: string;
play(action: string): string;
}
class TestClass implements Musician {
constructor(public name: string, public instrument: string) {}
play(action: string): string {
return `${this.name} ${action} ${this.instrument}`;
}
}
```
---
### 4οΈβ£ **Static Properties**
```ts
class Peeps {
static count = 0;
public id: number;
constructor(public name: string) {
this.id = ++Peeps.count;
}
static getCount() {
return Peeps.count;
}
}
```
* Use `ClassName.staticProperty` to access static members.
---
### 5οΈβ£ **Getter & Setter with Validation**
```ts
class Bands {
private dataState: string[] = [];
public get data(): string[] {
return this.dataState;
}
public set data(value: string[]) {
if (Array.isArray(value) && value.every(el => typeof el === 'string')) {
this.dataState = value;
} else {
throw new Error('Param is not an array of string');
}
}
}
```
---
### 6οΈβ£ **Index Signatures**
#### a. Dynamic Keys
```ts
interface Shop {
[index: string]: number;
}
const shopTranscation: Shop = {
Pen: -100,
Chicken: -50,
};
let prop2 = 'Pen';
console.log(shopTranscation[prop2]); // βοΈ
console.log(shopTranscation['Dhaka']); // β undefined but no error
```
#### b. With Specific Keys
```ts
interface shopTranscation2 {
readonly [index: string]: number;
Pen: number;
Chicken: number;
}
const Shop2: shopTranscation2 = {
Pen: 83,
Chicken: 115,
Test: 1907, // allowed due to index signature
};
```
---
### 7οΈβ£ **Iterating Over Object Keys**
#### Using `keyof` or `typeof`
```ts
interface StudentRes {
name: string;
roll: number;
classes?: number[];
}
const stud1: StudentRes = {
name: 'Sami',
roll: 115,
classes: [7026, 1190],
};
for (const key in stud1) {
console.log(`${key}: ${stud1[key as keyof typeof stud1]}`);
}
```
---
### 8οΈβ£ **Using Index Signature in Object**
```ts
interface StudentRes2 {
[key: string]: string | number | number[] | undefined;
name: string;
roll: number;
classes?: number[];
}
```
* Accessing `stud2.gpa` is allowed, even if not declared.
* All keys must have types within the declared union.
---
### 9οΈβ£ **Using `Record` Utility Type**
```ts
type Streams2 = 'salary' | 'bonus' | 'sideHustle';
type Income2 = Record;
const monthlyIncome: Income2 = {
salary: 100,
bonus: 115,
sideHustle: 1190, // string expected? allowed due to union
};
```
#### Strict Alternative:
```ts
type Income = Record<'salary' | 'bonus' | 'sideHustle', number>;
```
---
### π Summary
| Concept | Key Feature |
| ------------------- | ----------------------------------------- |
| Class modifiers | Encapsulation with `private`, `protected` |
| Interface | Contract enforcement |
| Static fields | Shared across instances |
| Getters/Setters | Controlled access to properties |
| Index Signature | Allow unknown keys with known value types |
| `Record` utility | Type-safe object with predefined keys |
| `keyof` + Assertion | Safe dynamic property access |
---
## [Generics](#generics)
### 1. Basic Function with and without Generics
```ts
const stringEcho = (arg: string): string => arg;
```
This function returns the same string that is passed to it. But it's limited to `string` type.
#### Using Generics
```ts
const Echo = (arg: T): T => arg;
```
This version is more flexible. It accepts any type and returns the same type. The type `T` is inferred based on the argument.
---
### 2. Type Guard for Object Type
```ts
const isObj = (arg: T): boolean => {
return (typeof arg === 'object' && !Array.isArray(arg) && arg !== null);
}
```
* Checks if a value is a non-null, non-array object.
* Useful for filtering out arrays and null which are also of type `object` in JavaScript.
#### Example Usage
```ts
console.log(isObj(true)); // false
console.log(isObj(null)); // false
console.log(isObj([1, 2, 3])); // false
console.log(isObj('ntm')); // false
console.log(isObj({ name: 'ntm' })); // true
```
---
### 3. Truthy Check with Custom Logic
```ts
const isTrue = (arg: T): { arg: T, is: boolean } => {
if (Array.isArray(arg) && !arg.length) return { arg, is: false };
if (isObj(arg) && !Object.keys(arg).length) return { arg, is: false };
return { arg, is: !!arg };
}
```
This function checks whether a value is logically "truthy", with special rules:
* Empty array: false
* Empty object: false
* Otherwise: Boolean(arg)
#### Interface Version
```ts
interface BoolCheck {
arg: T,
is: boolean
}
const isTrue2 = (arg: T): BoolCheck => {
// same logic as isTrue
}
```
#### Example Usage
```ts
console.log(isTrue(false)); // { arg: false, is: false }
console.log(isTrue({})); // { arg: {}, is: false }
console.log(isTrue([1,2,3])); // { arg: [1,2,3], is: true }
```
---
### 4. Constrained Generics with Interface
```ts
interface HasID {
id: number;
}
const processUser = (user: T): T => user;
```
This function enforces that the passed object must have an `id` property of type `number`.
```ts
console.log(processUser({ id: 83, name: 'ntm' })); // β
// console.log(processUser({ name: 'sas' })); β Error
```
---
### 5. Dynamic Property Access from Array of Objects
```ts
const getUsersProperty = (users: T[], key: K): T[K][] => {
return users.map(user => user[key]);
}
```
* `T` is a generic object type that must include an `id`.
* `K` is a key of `T`, ensuring type safety for property access.
#### Example:
```ts
const userArray = [
{ id: 1, name: 'Leanne', username: 'Bret', email: 'a@example.com' },
{ id: 2, name: 'Ervin', username: 'Antonette', email: 'b@example.com' }
];
console.log(getUsersProperty(userArray, 'email')); // ['a@example.com', 'b@example.com']
```
---
### 6. Generic Class with Getter/Setter
```ts
class stateObj {
private data: T;
constructor(value: T) {
this.data = value;
}
get state(): T {
return this.data;
}
set state(value: T) {
this.data = value;
}
}
```
* A generic class that stores any type.
* Maintains type throughout access and updates.
#### Example:
```ts
const store = new stateObj("ntm");
store.state = "cse"; // β
// store.state = 83; // β Type error
```
#### Solution for Multi-type
```ts
const myState = new stateObj<(string | number | boolean)[]>([83]);
myState.state = ["ntm", 83, true]; // β
```
---
### Summary of Concepts Covered
* β
Generic Functions
* β
Type Guards (`isObj`)
* β
Logical Evaluation with Extra Rules (`isTrue`)
* β
Interface-based Constraints
* β
`keyof` and Indexed Access Types
* β
Generic Classes with Encapsulation
---
## [Utility Types](#utility-types)
### 1. `Partial`
Makes all properties in `Type` optional.
```ts
interface Assignment {
studentId: string;
title: string;
grade: number;
verified?: boolean;
}
const updateAssignment = (
assign: Assignment,
propsToUpdate: Partial
): Assignment => {
return { ...assign, ...propsToUpdate };
};
const assign1: Assignment = {
studentId: "ntm",
title: "Computer Graphics",
grade: 90,
};
console.log(updateAssignment(assign1, { grade: 100 }));
const assignGraded: Assignment = updateAssignment(assign1, { grade: 100 });
```
---
### 2. `Required` and `Readonly`
* `Required`: Makes all properties required.
* `Readonly`: Makes all properties immutable.
```ts
const recordAssignment = (assign: Required): Assignment => {
return assign;
};
const assignVerified: Readonly = { ...assignGraded, verified: true };
// assignVerified.grade = 90; // β Error: Readonly
recordAssignment({ ...assign1, verified: true });
```
---
### 3. `Record`
Constructs an object type with keys of type `Keys` and values of type `Type`.
```ts
const hexColorMap: Record = {
red: "FF0000",
green: "00FF00",
blue: "0000FF",
};
type studentName = "azraf" | "sami";
type LetterGrades = "A" | "B" | "C" | "D" | "U";
const finalGrades: Record = {
azraf: "A",
sami: "B",
};
interface Grades {
assign1: number;
assign2: number;
}
const gradeData: Record = {
azraf: { assign1: 90, assign2: 93 },
sami: { assign1: 85, assign2: 98 },
};
```
---
### 4. `Pick` and `Omit`
* `Pick` creates a type by picking specific keys.
* `Omit` creates a type by omitting specific keys.
```ts
type AssignmentResult = Pick;
const score: AssignmentResult = {
studentId: "ntm",
grade: 100,
};
type AssignmentPreview = Omit;
const preview: AssignmentPreview = {
studentId: "ntm",
title: "Test Project",
};
```
---
### 5. `Exclude` and `Extract`
* `Exclude`: Excludes types from a union.
* `Extract`: Extracts matching types from a union.
```ts
type adjustGrades = Exclude; // "A" | "B" | "C" | "D"
type highGrades = Extract; // "A" | "B"
```
---
### 6. `NonNullable`
Removes `null` and `undefined` from a type.
```ts
type AllPossibleGrades = "ntm" | "sas" | null | undefined;
type NamesOnly = NonNullable; // "ntm" | "sas"
```
---
### 7. `ReturnType`
Extracts the return type of a function.
```ts
type newAssign = { title: string; point: number };
const createNewAssign = (title: string, point: number): newAssign => {
return { title, point };
};
type newAssign2 = ReturnType;
const tAssign: newAssign2 = createNewAssign("Utility Types", 100);
console.log(tAssign);
```
---
### 8. `Parameters`
Extracts the parameter types of a function as a tuple.
```ts
type AssignParams = Parameters;
const assignArgs: AssignParams = ["Image Processing Project", 100];
const tAssign2: newAssign = createNewAssign(...assignArgs);
console.log(tAssign2);
```
---
### 9. `Awaited`
Helps retrieve the resolved type inside a `Promise`.
```ts
interface User {
id: number;
name: string;
username: string;
email: string;
}
const fetchUsers = async (): Promise => {
const data = await fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => res.json())
.catch((err) => {
if (err instanceof Error) {
console.log(err.message);
}
});
return data;
};
// Awaited extracts User[] from Promise
type FetchUsersReturnType = Awaited>;
fetchUsers().then((users) => console.log(users));
```