TypeScript Slides PDF
Document Details
Uploaded by Deleted User
Tags
Summary
These slides provide an introduction to TypeScript, details its differences with JavaScript, and explain its features. The content covers various topics such as, types, syntax, and configuration, highlighting benefits like enhanced type safety.
Full Transcript
Typescript 1 Introduction TypeScript is a superset of JavaScript that adds optional type annotations and other features such as interfaces, classes, and namespaces. JavaScript is a dynamically-typed language that is primarily used for client-side web development and can also be used f...
Typescript 1 Introduction TypeScript is a superset of JavaScript that adds optional type annotations and other features such as interfaces, classes, and namespaces. JavaScript is a dynamically-typed language that is primarily used for client-side web development and can also be used for server-side development. Here are a few key differences between TypeScript and JavaScript: Types: TypeScript has optional type annotations while JavaScript is dynamically-typed. This means that in TypeScript, you can specify the data type of variables, parameters, and return values, which can help catch type-related errors at compile- time. Syntax: TypeScript extends JavaScript syntax with features like interfaces, classes, and namespaces. This provides a more robust and organized structure for large-scale projects. Tooling: TypeScript has better tooling support, such as better editor integration, type checking, and code refactoring. Backwards Compatibility: TypeScript is fully compatible with existing JavaScript code, which means you can use TypeScript in any JavaScript environment. 2 Introduction Typescript was created by microsoft addressing the shortcomings of JavaScript Typescript is build on top of javascript so every javascript file is a valid typescript file Typescript is an extended version of javascript: it needs a TS compiler for the browser to execute the code. Typescript is more suitable for big projects. 3 Pros & Cons Pros More robust Easily Spot Bugs Readability Popular Cons There is always a compilation step (browsers can not execute typescript code so it needs to be translated into javascript by a typescipt compiler => Transpilation) Discipline in code More to learn Not true Static Typing 4 Setup To use the typescript compiler we need to install the package: npm i -g typescript Create a typescript file with ts as extention. Any javascript code is a valid typescript code. Then compile your code using tsc index.ts in your cmd => a compiled javascript version of the typescript file will be created 5 Syntaxe let age: number = 20; // age = "a"; // we can not do this! We can annotate the variables. After compiling we get the index.js file: var age = 20; Notice the var keyword. By default the typescript compiler uses an older version of javascript. We need to configure the typescript compiler! 6 Configuration We create the configuration file by executing the command: tsc --init. In tsconfig.json we have a number of setting that most of them are commented off "target": "es2016", Here we specify the version of javascript that we want. ES2016 is the safest option since it is compatible with all browsers "module": "commonjs" , "rootDir": "./src" , "outDir": "./dist" , "removeComments": true, "noEmitOnError": true , With this configuration file, to compile the file we can just write tsc in the cmd 7 Basic TS Types TS is a statically typed language. The type cannot be changed during program execution. This allows you to reduce a large number of errors and identify many of them even at the compilation stage. TS has several simple data types: numbers, strings, structures, Boolean. It supports all types that are available in JS, complementing the convenient enum type Boolean, Number, String The any Type Arrays Tuples Enums Void Null and Undefined 8 Built-in Types let age = 20; let decimal: number = 6; let text = 'Typescript'; let name: string = "bob"; let is_published = true; let level; Typescript can annotate the variable to their specific type without the need to specify it. If we declare a variable with no value, its type will be set to any. 9 "Any" type let level; level = 1; level = "a"; Because the variable level is of type any we will not have any errors. But this defies wht typescript was created which is type safety! => Best practice: A void using any type as best as possible 10 "Any" type One way of solving this problem is to annotate the variable with the type any function render(doc: any) { console.log(doc); } But we can use the tsconfig file to avoid the error when you implicitly use a variable with type any "noImplicitAny": false, Use with caution, because you'll loose the benefit of typescript 11 Arrays In javaScript we could write let numbers = [1, 2, "3"]; However if we want to specify that our array should contain only numbers, we can use typescript and write let list: number[] = [1, 2, 3]; let list: Array = [1, 2, 3]; If we declare an empty array, its elements will be of type any, hence we will have the possibility to have an array with elements of different types. let numbers = []; numbers = 1; numbers = "hello"; //OR let list: any[] = [1, true, "free"]; 12 Tuples The Tuple type gives you the ability to declare an array with a known fixed number of elements that do not have to be of the same type. For example, you want to have the Tuple value as a pair of “string” and “number”: // Declare a tuple type let x: [string, number]; // Initialize it x = ["hello", 10]; // OK // Initialize it incorrectly x = [10, "hello"]; // Error Tuples are useful only if we have two elements. Any more then that and the code will be messy and unreadable. console.log(x.substring(1)); // OK console.log(x.substring(1)); // Error, 'number' does not have 'substring' 13 Tuples Optional Tuple Elements: Like function signatures, we can also have optional tuple elements. This is achieved with the help of the symbol? in the tuple definition: let optionalTuple: [string, boolean?]; optionalTuple = ["test2", true]; console.log(`optionalTuple: ${optionalTuple}`); optionalTuple = ["test"]; console.log(`optionalTuple: ${optionalTuple}`); 14 Enum Enum is a special type borrowed from other languages like C#, C ++, and Java that provides a solution to the special numbers problem. Enum binds a human-readable name for a specific number. As in languages like C#, the enum type is a more convenient way to give clear names to a set of numeric values Instead of: const small = 1; const medium = 2; const large = 3; We define an enum as enum Size {Small , Medium, Large} let mySize: Size = Size.Medium; console.log(mySize); By default Small will have the value 0, Medium 1 and Large 2 but we can change it as follows enum Size {Small = 1 , Medium , Large } // OR enum Size {Small = 's', Medium = 'm', Large = 'l'} 15 Enums In the js file created we have: "use strict"; var Size; (function (Size) { Size[Size["Small"] = 1] = "Small"; Size[Size["Medium"] = 2] = "Medium"; Size[Size["Large"] = 3] = "Large"; })(Size || (Size = {})); let mySize = Size.Medium; console.log(mySize); But if we use: const enum Size {Small , Medium, Large} let mySize: Size = Size.Medium; console.log(mySize); The associated js file: "use strict"; let mySize = 2; console.log(mySize); 16 String Enums Another variant of the enum type is a string enumeration, in which numeric values are replaced with strings: enum DoorStateString { Open = "open", Closed = "closed", Ajar = "ajar" } var openDoorString = DoorStateString.Open; console.log('openDoorString = ${openDoorString}'); 17 Void Void is the opposite of Any: the absence of any types. It is most often used as the return type of functions that do not return any value. function warnUser(): void { alert("This is my warning message"); } Declaring variables with the void type is useless, because you can only assign them undefined or null values. let unusable: void = undefined; 18 NULL & Undefined The Null and Undefined types correspond to the same types in JS. These types are subtypes for all other types by default. let n: number = null; // Primitive types can be null let m: number = undefined; // Primitive types can be undefined let x = null; // same as x: any = null let y = undefined; / / same as y: any = undefined let e: Null; // Error let r: Undefined; // Error If you declare a variable of type null or undefined, then such a variable can only be assigned the value null or undefined, respectively, which has no practical application. let n: null = null; // Only this value can be assigned to n = 1; // Error! let m: undefined = undefined; m = "some string"; // Error! 19 Non-Null assertion The non-null assertion operator (!) is a type assertion in TypeScript that allows you to tell the compiler that a value will never be null or undefined. let name: string | null = null; // we use the non-null assertion operator to tell the compiler that name will never be null let nameLength = name!.length; The non-null assertion operator is used to assert that a value is not null or undefined, and to tell the compiler to treat the value as non-nullable. However, it’s important to be careful when using the non-null assertion operator, as it can lead to runtime errors if the value is actually null or undefined. 20 Type assertions Sometimes you find yourself in a situation where you know more about the value of a variable than TS does. This usually happens when you know that the type of an entity may be more specific than its current type. Type assertion is like typecasting in other languages, but it doesn’t do any special checks or data restructurings. The type conversion has no effect at the execution stage of the program and is used only by the compiler. TS assumes that the programmer will do all the necessary checks that are required. The type conversion can be done in two ways. The first is the use of angle brackets syntax let someValue: any = "this is a string"; let strLength: number = (someValue).length; let someValue: any = "this is a string"; let strLength: number = (someValue as string).length; 21 Functions The TS language slightly expands the capabilities of functions compared to JavaScript, making working with them even more convenient. function add(x: number, y: number): number { return x + y;} in tsconfig.json "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, , 22 Functions In TypeScript, functions can be typed in a few different ways to indicate the input parameters and return type of the function. Function declaration with types: function add(a: number, b: number): number { return a + b; } Arrow function with types: const multiply = (a: number, b: number): number => { return a * b; }; Function type: let divide: (a: number, b: number) => number; divide = (a, b) => { return a / b; }; 23 Function Overloading Function Overloading in TypeScript allows multiple functions with the same name but with different parameters to be defined. The correct function to call is determined based on the number, type, and order of the arguments passed to the function at runtime. function add(a: number, b: number): number; function add(a: string, b: string): string; function add(a: any, b: any): any { return a + b; } console.log(add(1, 2)); // 3 console.log(add('Hello', ' World')); // "Hello World" 24 Objects let employee = { id: 1 }; employee.name = "Amal"; let employee: { id: number; name: string; } = { id: 1 }; employee.name = "Amal"; 25 Objects We can make the name property optional let employee: { id: number; name?: string; } = { id: 1 }; employee.name = "Amal"; To make some properties read only let employee: { readonly id: number; name: string; } = { id: 1, name: "Amal" }; 26 Objects let employee: { readonly id: number; name: string; retire: (date: Date) => void; } = { id: 1, name: "Amal", retire: (date: Date) => { console.log(date); }, }; 27 Advanced types Type aliases Unions and intersections Type narrowing Nullable types The unknown type 28 Type aliases Using type aliase we can create a custom type. type Employee = { readonly id: number; name: string; retire: (date: Date) => void; }; let employee: Employee = { id: 1, name: "Amal", retire: (date: Date) => { console.log(date); }, }; 29 Union Types function kgToLbs(weight: number | string): number { // Narrowing if (typeof weight === "number") { return weight * 2.2; } else { return parseInt(weight) * 2.2; } } 30 Intersection type Draggable = { drag: () => void; }; type Resizable = { resize: () => void; }; type UIWidget = Draggable & Resizable; let textBox: UIWidget = { drag: () => {}, resize: () => {}, }; Now the textBox variable is both of Draggable type AND Resizeble type 31 Literal types // Literal (exact, specific) let quantity: 50 | 100 = 50; type Quantity = 50 | 100; let quantity: Quantity = 50; 32 Nullable / undefined Types By default typescript is very strict when working with null and undefined values, because it is the source of bugs in vanilla javascript code. function greet(name: string | null | undefined ) { if (name) { console.log(name.toUpperCase()); } else console.log("Hola!"); } greet(null); greet(undefined); 33 Nullable / undefined Types type Customer = { birthday: Date; }; function getCustomer(id: number): Customer | null | undefined { return id === 0 ? null : { birthday: new Date() }; } let customer = getCustomer(0); // Optional property access operator console.log(customer?.birthday); 34 Unknown unknown is the type-safe counterpart of any. Anything is assignable to unknown, but unknown isn’t assignable to anything but itself and any without a type assertion or a control flow based narrowing. Likewise, no operations are permitted on an unknown without first asserting or narrowing to a more specific type. function f1(a: any) { a.b(); // OK } function f2(a: unknown) { // Error: Property 'b' does not exist on type 'unknown'. a.b(); } 35 Interfaces Interfaces in TypeScript provide a way to define a contract for a type, which includes a set of properties, methods, and events. It’s used to enforce a structure for an object, class, or function argument. Interfaces are not transpiled to JavaScript and are only used by TypeScript at compile-time for type-checking purposes. Here’s an example of defining and using an interface in TypeScript: interface User { name: string; age: number; } const user: User = { name: 'John Doe', age: 30, }; In this example, the User interface defines the structure of the user object with two properties, name and age. The object is then typed as User using a type-assertion: User. 36 Interface VS Types alias Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable. Extending an interface interface Animal { name: string; } interface Bear extends Animal { honey: boolean; } const bear: Bear = { name: "test", honey: true, }; Extending a type via intersections type Animal = { name: string; } type Bear = Animal & { honey: boolean; } const bear: Bear = { name: "test", honey: true, }; 37 Interface VS Types alias Adding new fields to an existing interface interface User { id: string; email: string; } interface User { name: string; } // Now you can add all the three values to the User interface const user: User = { id: "2323232", email: "[email protected]", name: "Foo", }; A type cannot be changed after being created type User = { id: string; } type User = { email: string; } // ❌ ERROR: Duplicate identifier "User" 38 Classes Classes in TypeScript are a blueprint for creating objects (instances of a class), providing a way to structure objects and encapsulate data and behavior. Classes in TypeScript have a similar syntax to classes in other object-oriented programming languages, such as Java and C#. A class in TypeScript is defined using the class keyword, followed by the name of the class. The class definition can include fields (also known as properties or attributes), methods (functions), and a constructor. class Animal { name: string; constructor(name: string) { this.name = name; } makeSound(): void { console.log(`${this.name} is making a sound`); } } const dog = new Animal('Dog'); dog.makeSound(); // Output: Dog is making a sound 39 Classes class BadGreeter { name: string; // Error: Property 'name' has no initializer and is not definitely assigned in the constructor. } class Base { k = 4; } class Derived extends Base { constructor() { // Prints a wrong value in ES5; throws exception in ES6 console.log(this.k); // Error: 'super' must be called before accessing 'this' in the constructor of a derived class. super(); } } 40 Classes (Constructor Overloading) In TypeScript, you can achieve constructor overloading by using multiple constructor definitions with different parameter lists in a single class. Given below is the example where we have multiple definitions for the constructor: class Point { // Overloads constructor(x: number, y: string); constructor(s: string); constructor(xs: any, y?: any) { // Only One definition of the Constructor } } Note that, similar to function overloading, we only have one implementation of the consructor and it’s the only the signature that is overloaded. 41 Classes (access modifiers) In TypeScript, access modifiers are keywords used to control the visibility and accessibility of class properties and methods. There are three access modifiers in TypeScript: public : This is the default access modifier. Properties and methods declared as public can be accessed from anywhere, both inside and outside the class. private : Properties and methods declared as private can only be accessed within the same class. They are not accessible from outside the class. protected : Properties and methods declared as protected can be accessed within the class and its subclasses. They are not accessible from outside the class and its subclasses. Access modifiers in TypeScript allow you to define the level of visibility and accessibility of properties and methods in your class, making your code more maintainable and secure. 42 Classes (access modifiers) class Person { private ssn: string; private firstName: string; private lastName: string; constructor(ssn: string, firstName: string, lastName: string) { this.ssn = ssn; this.firstName = firstName; this.lastName = lastName; } getFullName(): string { return `${this.firstName} ${this.lastName}`; } } let person = new Person('153-07-3130', 'John', 'Doe'); console.log(person.ssn); // compile error 43 Abstract Classes Abstract classes in TypeScript are classes that cannot be instantiated on their own and must be subclassed by other classes. Abstract classes provide a blueprint for other classes and can have abstract methods, which are methods without a body and must be overridden by the subclass. These classes are useful for defining a common interface or basic functionality that other classes can inherit and build upon. abstract class Animal { abstract makeSound(): void; move(): void { console.log('moving...'); } } class Dog extends Animal { makeSound(): void { console.log('bark'); } } 44 Inheritance vs Polymorphism Inheritance refers to a mechanism where a subclass inherits properties and methods from its parent class. This allows a subclass to reuse the code and behavior of its parent class while also adding or modifying its own behavior. In TypeScript, inheritance is achieved using the extends keyword. Polymorphism refers to the ability of an object to take on many forms. This allows objects of different classes to be treated as objects of a common class, as long as they share a common interface or inheritance hierarchy. In TypeScript, polymorphism is achieved through method overriding and method overloading. class Animal { makeSound(): void { console.log('Making animal sound'); } } class Dog extends Animal { makeSound(): void { console.log('Bark'); } } class Cat extends Animal { makeSound(): void { console.log('Meow'); } } let animal: Animal; animal = new Dog(); animal.makeSound(); // Output: Bark animal = new Cat(); animal.makeSound(); // Output: Meow 45 Generics Generics in TypeScript are a way to write code that can work with multiple data types, instead of being limited to a single data type. Generics allow you to write functions, classes, and interfaces that take one or more type parameters, which act as placeholders for the actual data types that will be used when the function, class, or interface is used. For example, the following is a generic function that takes a single argument of any data type and returns the same data type: function identity(arg: T): T { return arg; } let output = identity('Hello'); // type of output will be 'string' In this example, the identity function takes a single argument of any data type and returns the same data type. The actual data type is specified when the function is called by using before the argument "Hello". 46 TP: Book Reading tracker Create an HTML file where we have a form that register new books (use tailwindCSS to style it) Each book have a title(string), author(string), number of pages(number), status(String Enum), price (number), number of pages read (number < number of pages), format(String Enum), suggested by(string), finished(boolean). Status can have one of the following values: Read, Re-read, DNF, Currently reading, Returned Unread, Want to read Format can have one of the following values: Print, PDF, Ebook, AudioBook Be default finished is equal to 0, the finished value will change to 1 automatically when number of pages read is euqal to number of pages Create a class book have the following methods: a constructor, currentlyAt, deleteBook The book class should be its own module. Create a web page where we can track our reading by listing books and showing the percentage of reading for each book, and a global section where you can see the total amount of book read and the amount of pages The books are stored in MongoDB 47