# Typescript
## Basic Typing
There are 3 basic types in TypeScript
```ts
var isDone: boolean = false;
let lines: number = 69;
const name: string = 'Jajang';
```
But **you can omit** the type annotation if the variables are **derived** from explicit literals
```ts
var isDone = false;
let lines = 69;
const name = 'Jajang';
```
When it's impossible to know, there is the `any` type
```ts
let notSure: any = 4;
notSure = 'maybe a string instead';
notSure = false; // okay, definitely a boolean
```
Use `const` keyword for *constants*
```ts
const numLivesForCat = 9;
numLivesForCat = 1; // Error
```
For *collections*, there are typed arrays and generic arrays
```ts
let list: number[] = [1, 2, 3];
// Or, using the generic array type
let list: Array<number> = [1, 2, 3];
```
For *enumerations*
```ts
enum Color { Red, Yellow, Green };
let c: Color = Color.Green;
if (c === Color.Green) {
console.log('Lets go!');
}
```
Lastly, `void` is used in the special case of a function returning nothing.
```ts
function bigHorribleAlert(): void {
alert('I'm a little annoying box!');
}
```
## Functions
Functions are first class citizens, support the lambda 'fat arrow' syntax and use type inference.
The following are equivalent, the same signature will be inferred by the compiler, and same JavaScript will be emitted
1. Regular function
```ts
// Function Declaration
function f1(i: number): number {
return i * i;
}
// Function Expression
let f1 = function (i: number): number {
return i * i;
}
```
2. Return type inferred
```ts
let f2 = function (i: number) {
return i * i;
}
```
3. 'Fat arrow' syntax
```ts
let f3 = (i: number): number => {
return i * i;
}
```
4. 'Fat arrow' syntax with return type inferred
```ts
let f4 = (i: number) => { return i * i; }
```
5. 'Fat arrow' syntax with return type inferred, *braceless* means no return keyword needed.
```ts
let f5 = (i: number) => i * i;
```
---
## `var`, `let`, and `const`
Declaring a variable using the above keywords:
* Both type and initial value.
```ts
var width:number = 100;
let height:number = 200;
const key:string = 'abc123';
```
* Without type, but with an initial value.
```ts
var width = 100;
let height = 200;
const key = 'abc123';
```
* Only the type.
```ts
var width: number;
let height: number;
// const does not support without initial value
```
* Without type and initial value.
```ts
var width;
let height;
// const does not support without initial value
```
---
## Variable Scoping
```cpp
void leFn() {
std::string umurWawan = 25;
std::cout << umurWawan; // ok
}
void leOtherFn() {
std::cout << umurWawan; // WaWAn saHA ANyI...
}
```
### `var` is **Function** Scoped
```ts
function someFn() {
if (true) {
// defined locally
// its scope ends where curly braces ends
var local = 1000;
console.log(local); //ok
}
console.log(local); //ok
function nested() {
console.log(local); //ok
}
}
console.log(local); //error
```
### `let` and `const` are **Block** Scoped
```ts
function someFn() {
if (true) {
// defined locally
// its scope ends where curly braces ends
let local = 1000;
console.log(local); // ok
}
console.log(local); //error
function nested() {
console.log(local); //error
}
}
console.log(local); //error
```
---
## Interfaces
Interfaces are **structural**, anything that has the properties is compliant with the interface.
```ts
interface Person {
name: string;
// Optional properties, marked with a '?'
age?: number;
// And of course functions
move(): void;
}
```
Object that implements the `Person` interface can be treated as a `Person` since it has the name and move properties
```ts
let p: Person = {
name: 'Bobby',
move: () => { }
};
let validPerson: Person = {
name: 'Bobby',
age: 42, // optional property
move: () => { }
};
```
Object below is **not** a person because age is not a number and there is no `move` function.
```ts
let invalidPerson: Person = {
name: 'Bobby',
age: true
};
```
Interfaces can also describe a function type
```ts
interface SearchFunc {
(source: string, subString: string): boolean;
}
```
Only the **parameters' types** are important, names are not important.
```ts
let mySearch: SearchFunc;
mySearch = function (src: string, sub: string) {
return src.search(sub) != -1;
}
```
---
## Classes
Class members are public by default
```ts
class Point {
// Properties
x: number;
/* Constructor - the public/private keywords
* in this context will generate the boiler
* plate code for the property and the
* initialization in the constructor.
*
* In this example,
* 'y' will be defined just like 'x' is,
* but with less code
*
* Default values are also supported
*/
constructor(x: number, public y: number = 0) {
this.x = x;
}
// Functions
dist() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
// Static members
static origin = new Point(0, 0);
}
```
```ts
let p1 = new Point(10, 20);
let p2 = new Point(25); //y will be 0
```
Classes can be explicitly marked as implementing an interface.
Any missing properties will then cause an error at compile-time.
```ts
class PointPerson implements Person {
name: string;
move() {}
}
```
Class inheritance
```ts
class Point3D extends Point {
constructor(x: number, y: number, public z: number = 0) {
// Explicit call to the super class constructor
// is mandatory
super(x, y);
}
// Override
dist() {
let d = super.dist();
return Math.sqrt(d() * d() + this.z * this.z);
}
}
```
---
## Generics
Classes
```ts
class Tuple<T1, T2> {
constructor(public item1: T1, public item2: T2) {}
}
```
Interfaces
```ts
interface Pair<T> {
item1: T;
item2: T;
}
```
And functions
```ts
let pairToTuple = function <T>(p: Pair<T>) {
return new Tuple(p.item1, p.item2);
};
```
```ts
let tuple = pairToTuple({
item1: 'hello',
item2: 'world'
});
```
## Template strings
Template Strings: strings that use backticks (\`).
String Interpolation with Template Strings
```ts
let name = 'Tyrone';
let greeting = `Hi ${name}, how are you?`
```
Multiline Strings with Template Strings
```ts
let multiline = `This is an example
of a multiline string`;
```
---
## Iterators
* `for..of` statement. Iterate over the list of **values** on the object being iterated.
```ts
let arrayOfAnyType = [1, 'string', false];
for (const val of arrayOfAnyType) {
console.log(val); // 1, 'string', false
}
let list = [4, 5, 6];
for (const i of list) {
console.log(i); // 4, 5, 6
}
```
* `for..in` statement. Iterate over the list of **keys** on the object being iterated.
```ts
for (const i in list) {
console.log(i); // 0, 1, 2
}
```
* Higher order functions
```ts
let arrayOfAnyType = [1, 'string', false];
arrayOfAnyType.forEach(i => console.log(i));
// 1, 'string', false
const names = ['Ujang', 'Supardi', 'Wawan']
names.forEach((name: string) => {
console.log(`Halo, selamat datang ${name}`);
})
```
---
## More Types
* Union Types (`|`)
```ts
let code: string | number;
code = 123; // ok
code = 'ABC'; // ok
code = false; // compiler error
```
* Intersection Types (`&`)
```ts
interface Animal {
kind: string;
}
interface Person {
firstName: string;
lastName: string;
age: number;
}
interface Employee {
employeeCode: string;
}
let employee: Animal & Person & Employee = {
kind: 'human',
firstName: 'Jane',
lastName: 'Smith',
age: 20,
employeeCode: '123'
}
```