Contents

Introduction of Typescript

For building some simple frontend apps with React, typescript worth understanding especially for its type strictness and inference. Below code is just a memo for my private reference.

Create template project

Pre-requisite

  • Install node.js
  • Install VSCode
    • Add extensions for VSCode
      • ES7 React/Redux/GraphQL/R (Compliment function for react)
      • Prettier (Code formatter)
    • Configure prettier
      • VSCode > settings > (type “save”) > check “editor: format on save”

Install template

1
npx create-react-app . --template typescript

Then you can start template project by:

1
npm start

Introduction code for reference

src/App.tsx

1
2
3
4
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { NoSubstitutionTemplateLiteral, TypeOfExpression } from 'typescript';

Load json

1
2
3
4
5
// data.json is from https://jsonplaceholder.typicode.com/users
import Data from "./data.json"
import TestComponent from './TestComponent';

type USERS = typeof Data;

Data types

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const name = "hello";

let nameChange = "hello";
nameChange = "hello2";

let username: string = "User1";
let dummyNum = 2;
let bool: boolean = true;

let array1 = [true, false, true]
let array2 = [0,1, "Hello"]

Interface and function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
interface NAME {
  first: string;
  last?: string | null;
}

let nameObj: NAME = {first:"Yamada", }
let nameObj2: NAME = {first:"Yamada", last:"Taro"}
let nameObj3: NAME = {first:"Yamada", last:null}

const func1 = (x: number, y:number): number => {
  return x + y;
}

Intersection types

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
type PROFILE = {
  age: number;
  city: string;
}

type LOGIN = {
  username: string;
  password: string;
}

type USER = PROFILE & LOGIN;

// Inetsection Types
const userA = {
  age: 30,
  city: "Fukuoka",
  password: "aaa",
  username: "tt"
}

Union types

1
2
3
4
5
6
7
// Union Types
let value: boolean | number;
value = true;
value = 10;

let arrayUni: (number | string)[];
arrayUni = [0, 1, 2, "hello"];

Literal types

1
2
3
4
5
6
// Literal types
let gafa: "Google" | "amazon" | "facebook" | "apple";
// gafa = "Tesla"
gafa = "Google"
let memory: 256 | 512;
memory  = 256;

typeof

1
2
3
4
5
6
// typeof (type)
let msg: string = "Hi";
let msg2: typeof msg;

let animal = {cat: "small cat"};
let newAnimal: typeof animal = {cat: "big cat"}

keyof

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// keyof (element)
type KEYS = {
  primary: string;
  secondary: string;
};
let key : keyof KEYS;
key = "primary"

// typeof + keyof
const SPORTS = {
  soccer: "Soccer",
  baseball: "Baseball"
}
let keySports: keyof typeof SPORTS;
keySports = "soccer"

Enum

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// enum (automatically create enum member)
// mitigate bug by enum and raise maintenance ability. 
enum OS {
  Windows,
  Mac,
  Linux,
}
interface PC {
  id: number;
  OSType: OS;
}
const PC1: PC = {
  id: 1,
  OSType: OS.Linux
}
const PC2: PC = {
  id: 2,
  OSType: OS.Windows
}

Compatibility of types

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// compatibility of type
// level of abstraction: string > "test"(literal)
const comp1 = "test";
let comp2:string = comp1;

let comp3:string = "test3";
// let comp4: "test" = comp3;  // this line fails. 

let funcComp1 = (x: number) => {};
let funcComp2 = (x: string) => {};

// Belows don't work
// funcComp1 = funcComp2
// funcComp2 = funcComp1

Generics

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Generics
interface GEN<T>{
  // This is template; item alias type is not defined
  item: T;
}
const gen0: GEN<string> = {item: "hello"};
// const gen1: GEN = {item: "hello"}
const gen2: GEN<number> = {item: 100};

// as default type of generics are specified by interface, caller side can use it without parameter type
interface GEN1<T= string> {
  item: T;
}
const gen1: GEN1 = {item: "hello"};

interface GEN2<T extends string | number> {
  item: T;
}
const gen4: GEN2<number> = {item: 0}

function funcGen<T>(props: T) {
  return {item: props}
}
const gen5 = funcGen<string>("test")
const gen6 = funcGen<number>(3)
const gen7 = funcGen<number | null>(null)

function funcGen1<T extends string | null>(props: T){
  return {value: props};
}
const gen8 = funcGen1("hello");
// const gen9 = funcGen1(1234);

interface Props {
  price: number;
}

// function with Generics
function funcGen3<T extends Props>(props: T){
  return {value: props.price}
}
const gen10 = funcGen3({price: 10});

// arrow function with Generics
const funcGen4 = <T extends Props>(props: T) => {
  return {value: props.price}
}

React Hooks Prop type

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// React Hooks Props type
const App: React.FC = () => {
  return (
    <div className="App">
      <header className="App-header">
        <TestComponent text="Hello from App"/>
      </header>
    </div>
  );
}

export default App;

React Hooks useState, Event handler

src/TestComponent.tsx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import React, { useState } from "react";

interface Props {
    text: string
}
interface UserData {
    id: number;
    name: string;
}

const TestComponent: React.FC<Props> = (props) => {
    // React Hooks useState
    const [count, setCount] = useState<number | null>(0);
    const [user, setUser] = useState<UserData>({id: 1, name: "dummy"})
    const [inputData, setInputData] = useState("");
    
    // Event Handler
    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) =>
  setInputData(e.target.value);
    return (
        <div>
            <h1>{props.text}</h1>
            <h1>{count}</h1>
            <h1>{user.name}</h1>
            <input type="text" value={inputData} onChange={handleInputChange}/>
            <h1>{inputData}</h1>
        </div>
    );
}

export default TestComponent;

Github

typescript-lesson

Reference