# TypeScript Basics (101)

This post is recording the basics knowledge of TypeScript (TS).

1. What is TypeScript (TS)? Is a superset of JavaScript (JS), which is strongly typed language, which also eventually will complies the code down to the JavaScript level, because browser only understands JavaScript.

Essential concepts:

  1. Variable Types: [Basics: Boolean, Number, String]
  2. Functions
  3. Interfaces
  4. Class
  5. Access Modifiers

Before start, setup basics environment to run TypeScript code:

Please install TypeScript in your browser first by running this command:

// Install first
npm install -g typescript
// Then run version check
tsc -v

How to compile a .ts file to .js file (ts -> js)?

// eg: create a xxx.ts file first
// Then run command
tsc xxx.ts
// you will see js file has been generated as
// xxx.js
// The run this command to run js code:
node xxx.js
// we also can watch the changes by using:
ts xxx --watch

The reason of using types:

  1. Static type checking
  2. Give hint about what's going wrong?
  3. Intelligence suggestions, eg: if you define a number `num`, then you type `num.`, you will find the suggestions only related with numeric type of APIs

Here are the basics implementations for recording purpose only:

// When the time we see this warning: Cannot redeclare block-scoped variable 'message'.ts(2451)
// we add export {}; to resolve it
export {};
let message = "Ahoy, Damon !!";
console.log(message);

// Basic types
let name: string = 'damon'; // string
let isTrue: boolean = false; // boolean
let number: number = 1; // number

// Sub type can be used for initialize a variable or reassign the value to a declared variable
let n = null; // sub-type null
let u = undefined; // sub-type undefined
isTrue = n;
name = u;

// 2 ways to define array:
let arr1: number[] = [1,2,3];
let arr2: Array<number> = [1,2,3,4];

// Tuple type example:
// number of items inside array is fixed & order must be same as declarations
let mixArr: [string, number, boolean] = ['damon', 123, true];

// Enum:
enum Color {Red, Green, Blue};
let redColor: Color = Color.Red; // output is 0, because we haven't assigned value into each enum value
console.log('Enum red color define: ', redColor);
// assign value to each enum value:
enum ColorWithValue {Red="Red", Green="Green", Blue="Blue"};
console.log('Enum color with value: ', ColorWithValue.Green);

// When to use type 'any'?
// When the time we need to reassign value to different type, Eg:
let valueReadFromLibrary: any = 10;
valueReadFromLibrary = false;

// If we only use type 'any' WITHOUT any reassignment, typescript won't give us any error, which cause huge effort for code debugging, eg:
let noReassignTypeAny: any = 10;
// console.log(noReassignTypeAny()); // function, wrong (X)
console.log(noReassignTypeAny.name); // object, wrong (X)

// Type 'unknown':
let unknownVariableType: unknown = 10;
unknownVariableType = 'become a string';
// console.log(unknownVariableType.toUpperCase()); // If not define a type in advance, ts will give us error hint, so we need to predefine like this: 'variable as type'
console.log((unknownVariableType as string).toUpperCase());

// Multiple type variable:
let multipleTypeVariable: number | boolean;
multipleTypeVariable = 10;
multipleTypeVariable = false;

// Big topic: functions for TS
function sum(n1: number, n2?: number): number {
// ? means value is optional, can be fill in or leave it as empty
// the last: number means we defined the function sum output MUST be a number type value
  return n1 + n2;
};

console.log('n2 can be optional: ', sum(1)); // value is NaN !!!

// throw error:
// sum(1, true);
// good example

function preDefinedValueThenSum(n1: number, n2: number = 0): number {
  return n1 + n2;
};

console.log('n2 can be optional: ', preDefinedValueThenSum(1)); // value is 1 !!!

// Another big topic of Interface:
// We can specify the object as type in TypeScript -> Interface !!!!!!
// Use case:
function fullName(person: {firstName: string, lastName: string}) {
  return `${person.firstName}, ${person.lastName}`;
}

let p = {
  firstName: 'Damon',
  lastName: 'Wu'
};

console.log(fullName(p));

// So in above case, we see person: {firstName: string, lastName: string}, which might be repeated for later usage, so if we have function B, C D ..., we all need to defined person like this format, person: {firstName: string, lastName: string}, which is a bad practice, here comes with Interface !!!!

interface Person {
  firstName: string,
  lastName?: string
};

function fullNameWithInterface(person: Person) {
  return `${person.firstName}, ${person.lastName}`;
};

let p2: Person = {
  firstName: 'Ella',
};

console.log(fullNameWithInterface(p2));

// Just another topic: Class & Access Modifier
// OOP concept: inheritance:

class Employee { // ts class structure:
  employeeName: string; // class variable

  constructor(en: string) { // constructor
    this.employeeName = en;
  }

  greet() { // function
    console.log(`Hi ${this.employeeName}`)
  }
};

let emp1 = new Employee('Damon');
console.log("What is the instance variable value: ", emp1.employeeName); // Important concept
console.log(emp1.greet());

// Now we introduce 'super' usage for another class: (How inheritance works)
class Manager extends Employee {
  constructor(managerName: string) {
    super(managerName);
  }

  delegateNameForManager() {
    console.log('Manager class can call employee class method and assign its value emplyee class like below result: ');
  }
}

let m1 = new Manager('Ella');
m1.delegateNameForManager();
console.log('Employee class variable got value from Manager class: ', m1.employeeName);
m1.greet();

// Access Modifier
// public: (default one) enable to be access by any class or functions
// private: only can be accessed by its own class, not outside the class
// protected: can be access only when within the class and subclasses)

// Example below:

class A {
  protected name: string;
  constructor(_name: string) {
    this.name = _name;
  }
}

class B extends A {
  private department: string;
  constructor(whatever: string, department: string) {
    super(whatever);
    this.department = department;
  }

  public message() {
    return `Hi, my name is ${this.name} and I worked in ${this.department}.`;
  }
}

let p1 = new A('Damon');
console.log('whats p1? ', p1);
// console.log('whats p1? ', p1.name); // got error for accessing p1.name
let instanceOfB = new B('Damon', "IT");
console.log(instanceOfB.message());
// console.log(instanceOfB.name); // got error for accessing instanceOfB.name

2. Difference between interface and type:

Interface: describes the data shapes, eg: object (what the object going to look like)

can do declaration merging, type is not allowed

eg:

interface BaseInterface {
  name: string;
  age: number;
}

interface MergingInterface: BaseInterface {
  hobby: string[];
  boc: string;
}

Type: defines a type of data, eg: a primitive, a tuple or a union

//  type unique feature: allows developer to setup a type alias for just a single core type
type Age = number;

const myAge: Age = 30;

Reference

3. xxx.d.ts: its call typescript declaration file, which is the type definition files that allow to use JavaScript code in Typescript.

tsc --init // autogernate the tsconfig.json file

tsc example.ts --declaration // will generate 2 versions of ts file example.js and example.d.ts file

reference

4. TypeScript for React:

Please hover the error and check the correct type definition

Or

Right click and peek the definition to see the difference

Typescript hooks define type:

  1. useState:

eg:

const [data, setData] = (useState < number) | null | (undefined > 5);
setData(null);

const [data, setData] = useState < { text: string } > { text: "hi" };
setData({ text: "hello" });

Or we can do this way:

interface TextNode {
  text: string;
}
const [data, setData] = useState < TextNode > { text: "hi" };
setData({ text: "hello" });

5. TypeScript tsconfig.json confugurations:

Case 1: "declarations": true // will generate declaration file for you

Case 2: "include": ["src/**/*.ts"] // define to include which files to be compiled to js

Case 3: "exclude": ["src/**/*.spec.ts"] // exclude all test files for compiling to js

Case 4: "extends": ["../tsconfig-base.json"] // get more configurations for tsconfig

Case 5: "noEmitOnError": true // no files will get generated when error detected by ts

Case 6: "sourceMap": true // will generate the *.js.map file for the codebase

Case 7: "inlineSources": true // make sourcemap display in one line format ~

Case 8: "inlineSourceMap": true // inlineSourceMap = sourceMap + inlineSources

Case 9: "strict": true // make typescript in strict mode

Case 10: "traceResolution": true // display the compiled files information in terminal

Case 11: "diagnostics": true // display general infromation of compiled result in terminal

Case 12: "listFiles": true // show all the gernated files in terminal

Case 13: "pretty": true // show some colourful words in terminal

Case 14: "noUnusedParameters": true // remove unused paramemters when compiling from ts to js

Case 15: "noUnusedLocals": true // remove unused var, let const values