Typescript is a superset of Javascript. Browser's cannot execute TS, neither can Node. TS is a powerful compiler that compiles your code into JS. You didn't write the JS, the JS is automatically generated and is better code than you would've written yourself. The compiler creates a more complex workaround in JS that is very simple to write in TS. Errors are caught early. Why Use Typescript?

Note that strings are passed instead of numbers. You'd get an unwanted error at runtime-- JS will concatenate the strings. Not five, but 23. JS has mitigation strategies-- if checks that validate. But we'd rather have something that worked in runtime. A more indepth example of the same thing-- JS accidentally making strings instead of numbers: Consider two inputs with a JS file that adds them

const button = document.querySelector("button"); const input1 = document.getElementById("num1"); const input2 = document.getElementById("num2"); function add(num1, num2) { return num1 + num2; } button.addEventListener("click", function () { console.log(add(input1.value, input2.value)); });

Where is this error coming from? When the button is clicked, the values are accessed. It's important to know in JS that when values are withdrawn from inputs, they are ALWAYS strings. Even if the html type is something else. So two strings are getting passed. We could work around this problem by adding to our add function: if (typeof num1 === 'number && typeof num2 === 'number){the rest of our code} but we wrote some extra code for an error that we'd rather prevent in the first place. We shouldn't allow strings to ever be passed here in the first place.

Installing Typescript npm i -g typescript - This means we will need NodeJS. It must be installed because we need the compiler. Now we can run the tsc command which will compile TS to JS. Now our previously JS file has errors. That is great!

The values are errors because there's no real way to know in JS if the inputs have values attached to them. To say "we are sure we will get something back", we can add an exclamation mark at the end.

//by adding an exclamation point, we say we are sure //we will always //get something back adding as HTMLInputElement //is an example of "typecasting" const input1 = document.getElementById("num1")! as HTMLInputElement; const input2 = document.getElementById("num2")! as HTMLInputElement;

This is a great advantage, but even better is specifying the types we will get back. Hover over any value and it will say "any". We can change with this colong:

function add(num1: number, num2: number) { return num1 + num2; }

Typescript Overview TS adds Types. Modern IDEs give us better autocompletes. Can use next-gen JS features and they get compiled down for older browsers. Can add interfaces and generics, features that help us during development but don't belong to JS. Also adds meta-programming features like decorators. It has rich configuration options. Course Type Assignments and Type Inferences Type inference means TS does its best to understand what type something is even if you don't say it. You can hover over the variable name in a TS file and it will show you what type it thinks it is. In const result = 5 for instance, the type returns as 5 (the number), bc const is strict. But either way it assumes its type is number because you initialized it as a number. if let number1 = 5 the hover says number1: number. We can assign types to variables, too let number1: number = 1. But it's not a good idea unless you simply declare it without a value (let number1). Inference knows what it's doing. TS yells at you if you use a type other than what it inferred.

"Type number is not assignable to type string" This is its core task, and mission: to yell at you when you use incorrect types. Core Types TS adds many more types to vanilla JS, as well as enabling us to write our own types. Basic Types that JS Already Knows: number. There is no special type for integers or floats, numbers with decimals, without, negative, no difference. string - text. Single quotes, double quotes, or backticks. boolean - true or false. Just these two, no truthy or falsy values. Working with basic data types in TS Numbers, Strings, and Booleans Starting with a normal code snippet in JS:

function add(n1, n2) { return n1+n2 } const number1 = 5 const number2 = 3.2 const result = add(number1, number2) console.log(result)

We add something that will break the code in regular JS:

function add(n1, n2) { return n1+n2 } const number1 = "5" const number2 = 3.2 const result = add(number1, number2) console.log(result)

Result now logs 53.2, because it concatenates strings when they're added. This kind of problem can happen a lot of ways. User input, other developers. TS can add type assignments to our parameters

The error in the red squiggly line is "Argument "5" not assignable to type number". This is what we want. Note the type assignments in the function parameters. JS will still compile our files with errors. By default, TS does not step in to block compilation, it only yells at you. typeof is a built in operator in JS. Trying console.log(typeof number1), returns number. We could add this into vanilla JS, but we don't need to throw the error. We could just write it properly in TS. JS is "dynamically typed", which means the type of a variable can change. TS is statically typed. The point here is JS already knows about types. But it is better to fail in development, not at runtime, the raison detre of TS. An example of adding boolean and string types:

function add(n1: number, n2: number, showResult: boolean, phrase: string) { const result = n1+n2; if(showResult){console.log(phrase+result)} else{return n1+n2} } const number1 = 5 const number2 = 3.2 const printResult = true const resultPhrase = "Result is " const result = add(number1, number2, printResult, resultPhrase)

Objects More specific typing of objects is possible. Has to have these properties, this constructor options, etc. Trying to add a property that doesn't exist will register a TS error. This is because it infers the specifics about the object. A name and age object Person will be inferred to have name: string and age: number. This info is written as an object type. They look like JS objects except they have a semicolon at the end of each value.

const person: object = { name: 'Joe', age: 33 } //same as const person: {} = { name: 'Joe', age: 33 }

This only tells TS it's an object, not the specific properties. To define an object type:

const person: { name: string; age: number; } = { name: 'Joe', age: 33 }

It is suboptimal to do this manually though. Better to let TS define it with inference. This manual definition doesn't get stored in any JS whatsoever. Arrays The types of arrays can be flexible or strict in TS.

const person = { name: 'Joe', age: 33, hobbies: ['Sports', 'Cooking'] }

TS infers the hobbies array belongs to strings. hobbies: string[] it says. Adding a number would throw an error. If we want to store multiple types in an array, we'd use any[]. Interestingly, if TS knows the type of something, it will suggest methods pertaining to that type.

Methods pertaining to other types will throw an error, which is helpful. Types unique to TS Tuples Tuples are fixed-length arrays. Also fixed-type. An example:

const person = { name: 'Joe', age: 33, hobbies: ['Sports', 'Cooking'], //TS says `role: number | string` // ie, it's either a number or string role: [2, 'author'] } //this is not ideal, we can do things that break it: person.role.push('admin') person.role[1] = 10; const person: { name: string; age: number; hobbies: string[]; //marks tuple role: [number, string]; } = { name: 'Joe', age: 33, hobbies: ['Sports', 'Cooking'], //TS says `role: number | string` role: [2, 'author'] } //push is an exception and can work with tuples //but it will enforce length person.role.push('admin') //this throws error: person.role[1] = 10;

Enum create with enum { NEW, OLD }. It automatically gives you an enumerated global constant list. Gives you human-identifiable numbers. Gives you a strict name: number identification scheme that makes big projects easier.

//conventional js way of doing name: number pairs const ADMIN = 0; const READ_ONLY = 1; const AUTHOR = 2; //easy TS version enum Role { ADMIN, READ_ONLY, AUTHOR }; //call it in our object const person= { name: 'Joe', age: 33, hobbies: ['Sports', 'Cooking'], role: Role.ADMIN }

Can assign custom numbers javascript enum Role { ADMIN = 5, READ_ONLY, AUTHOR }; //readonly will be 6, author 7 Any type

    • most flexible type. You want to avoid it whenever possible. Defeats the purpose of TS. Union If we need to accept multiple different values somewhere, calls either or. Just put a | pipe for different types in the definitionfunction combine(input1: number | string, input2: number | string) { let result if(typeof input1 === 'number' && typeof input2 === 'number') {result = input1 + input2;} else{ result = input1.toString() + input2.toString() } return result } Literals Not only type but value is clearly defined. If you use const, it is inferred that the value is literal. Can be very useful for strings. Say you want to make a parameter one of two string options:function combine(input1: number ... resultConverstion: 'as-number' | 'as-text'){} The literal values are passed and brought together in a union type (an either or). Now the only parameters that can be passed to the function in this place are as number or as text. Can be cumbersome to always create union types. Type aliases workaround this://create it before you use it //add type keyword then the name of your custom alias // any name that isn't built into JS is allowable type mySpecialCustomType = number | string; type myLiteralUnion = "as-number" | "as-string" //now the union type is marked by the new name instead of typing it out over and over Functions Can assign types to function parameters, but you can do more. You can add "return types" to a function. It usually infers. You can hover over a TS function to see what it infers will be returned. Examples (seen on hover) ```typescript //TS infers this return type is number function add(n1:number, n2:number){ return n1+n2 }

//TS infers this return type is string function add(n1:number, n2:number){ return n1.toString()+n2.toString() }

//can also add manually function add(n1:number, n2:number): number{ ... }``` VOID method

function printResult(num:number){ //what is the return type here? string? no. // because there is no return call, the type is VOID console.log('result' + num) } printResult(add(5,12))

It means "this function doesn't return anything". It executes its code but doesn't bring anything back. In Javascript, if we use the return function on something without a return, we get back undefined. Undefined is a type in TS too. Function Type

function add(n1:number, n2:number): number{ return n1+n2 } let combineValues; combineValues = add; console.log(combineValues(8,8)) //this works //but the following doesnt: let combineValues; combineValues = add; combineValues= 33 console.log(combineValues(8,8)) //there is no error in TS, it can't know bc combineValues' type is any //so how do we specify it should be a function?

let combineValues: () => number;

To be more specific:

let combineValues: (a:number, b:number) => number;


function addNHandle(n1: number, n2: number, cb: (num:number)=> void) { const res = n1+n2; cb(res) //you can still return something, the void doesn't restrict us //it just ignores the return type inside the function //anything you might return will not be used! }

The unknown type

Error comes from the conflict between string and unknown. It's more restrictive than any. This makes it work

Better choice than any if you're unsure what you'll get but know what you'll do with it eventually. Never type Never is something functions can return. It's for use in error utilities:

function generateError(msg:string, code:number):never{ throw{msg:msg, errorCode:code} } generateError("error", 500)

JS stops the script when there's an error, so it will NEVER return anything. You can't store the result. Also true of While(true) loops. Compiler and Config deep dive The compiler Thus far, we've kept running tsc app.ts over and over. You can run the compiler to not have to do this and also to add some config. You can run npm start after initializing npm. Then the browser auto-reloads. Still have to rerun compilation though. Instead, we run watch mode on a file. tsc app.ts -w. Now it says "watching for file changes." But what about if you have multiple files? First tell TS what your project is. Run tsc --init in the root. It creates tsconfig.json. Now we can run tsc by itself, without pointing to a file. Can also be applied to watchmode. tsc -w will watch all files. TSConfig The first object is full of specific instructions to the compiler. Create a second object to define these options:

//at the end of tsconfig.json "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, "exclude": [ //paths to files that won't be included "analytics.ts", //wildcard "*.dev.ts", //common "node_modules" ], "include": [ //only files in here will be run "*.ts" ] }

Common to exclude node modules. But the modules are excluded as a default setting. Compiler Options in tsconfig.json HOW our TS code is compiled. In "compilerOptions" "target" means what javascript version TS will compile to. "lib" helps you know what environment JS is running in-- node, browser, etc. So, you can find buttons with queryselector bc it assumes all DOM APIs are available. d.ts files are declarations auto-compiled by Typescript that tell you every type used. This is the API Reference for Obsidian API SourceMap helps us debug. Make it true and youll get .js.map files compiled. Then in the sources tab of the inspect element dev tools in browser you can read your typescript. You can select out different pieces of the code and pause them, etc. outDir and rootDir: src and dist folders are common, src for TS and dist for the compiled JS. It's how you change the default output. outDir tells TS where the outputted files should be stored. a subfolder will get replicated too. very useful. Then set rootDir to ./src, so it won't look in other folders for your Typescript. It will also make sure the project structure is the same in the TS folder as it is in the JS folder. noEmit generates no JS files. used to just check errors noEmitOnError option: boolean. If there's an error, TS will not compile. Makes TS extra strict. Strict Options strict: true enables all strict type-checking options (ie, everything below it) No Implicit Any: doesn't let you skip defining types. Strict Null Checks: if false, it lets methods get run on things that could potentially be null. Opens up runtime errors in JS. An exclamation mark at the end of an operation tells TS you're sure something exists. If you're kinda unsure, do an if check if the possibly null thing is true Bind Call Apply: Using this and bind, which I've never used. Additional Checks all just make your code cleaner. It'll complain if you don't use a variable, or have an implicit return, Fireship TypeScript in 100 Seconds - YouTube:

Using Typescript in Node.js - YouTube: https://www.youtube.com/watch?v=1UcLoOD1lRM If you want to compile your Node in TS, add tsc to npm build command in package json. ts-node is a package that can run Node with TS no worries, also add to packagejson ts-node-dev will watch files on the server. nodemon is a package that works with windows runs dev server Adding express with TS: How to know type definitions in Express values? add definitions-- @types/express, etc. @types/node does built in by node too