
자바스크립트로 컴파일이 가능하며 언어가 예측가능하고 읽기 쉬운 코드로 자바스크립트를 사용가능
각 블록에는 해시값을 가지고 있으며 각 블록이 체이닝을 이루고 있다.
$ yarn init -y
$ yarn global add typescript
typescript가 어떻게 javascript로 변환할지 옵션을 설정
// tsconfig.json
{
    "compilerOptions": {
        "module": "CommonJS",
        "target": "ES6",
        "sourceMap": true
    },
    "include": ["index.ts"],
    // 어떤 파일들이 컴파일 과정에 포함되는지
    "exclude": ["node_modules"]
}
$ tsc : ts파일에 있는 코드를 컴파일해서 index.js와 index.js.map을 생성
($ sudo apt install node-typescript)
-> $ yarn start 로 대체
// package.json
"scripts": {
"prestart": "tsc",
"start": "node index.js"
}
파라미터에 ?를 붙이면 파라미터를 옵션으로 사용할 수 있다.
const name = "Nicolas",
  age = 24,
  gender = "male";
const sayHi = (name, age, gender?) => {
  console.log(`Hello ${name}, you are ${age}, your gender is ${gender}`);
};
// const sayHi: (name: any, age: any, gender?: any) => void;
sayHi(name, age);
export {};
const sayHi = (name: string, age: number, gender: string): string => {
  return `Hello ${name}, you are ${age}, your gender is ${gender}`;
};
// const sayHi: (name: string, age: number, gender: string) => string
console.log(sayHi("Nicolas", 24, "male"));
export {};
매번 tsc 명령어를 통해 ts파일을 js파일로 컴파일 하던 것을 자동으로 해준다.
$ yarn add tsc-watch --dev
// package.json
"scripts": {
    "start": "tsc-watch --onSuccess \" node dist/index.js\" "
    }
모든 컴파일된 것들은 dist 폴더로 들어간다.
// tsconfig.json
{
    "compilerOptions": {
        "outDir": "dist"
    },
    "include": ["src/**/*"],
}
타입스크립트를 작성하기 위해 필요
오류 : "Cannot find module 'typescript/bin/tsc"
해결 : $ npm install typescript --save-dev
인터페이스는 자바스크립트로 컴파일 되지 않는다.
interface Human {
  name: string;
  age: number;
  gender: string;
}
const person = {
  name: "nicolas",
  age: 22,
  gender: "male",
};
const sayHi = (person: Human): string => {
  return `Hello ${person.name},
    you are ${person.age},
    your gender is ${person.gender}!`;
};
console.log(sayHi(person));
export {};
인터페이스는 자바스크립트로 컴파일되지 않지만, 클래스는 가능하다.
자바스크립트를 인터페이스로 사용하면 타입스크립트 측면에서 좀더 안전하다.
그러나, react, express 등을 사용할 때는 코드에서 클래스를 사용해야한다.
private은 클래스 내부에서만 접근 가능
class Human {
    public name: string;
    public age: number; // ex) private age: number
    public gender: string;
    constructor(name: string, age: number, gender: string) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
}
const lynn = new Human("Lynn", 18, "Female");
const sayHi = (person: Human): string => {
    return`Hello ${person.name},
    you are ${person.age}, // ex) error 발생
    your gender is ${person.gender}!`;
};
console.log(sayHi(lynn));
export {};
// index.js
class Human {
    constructor(name, age, gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
}
class Block {
    public index: number;
    public hash: string;
    public previousHash: string;
    public data: string;
    public timestamp: number;
    constructor(
        index: number,
        hash: string,
        previousHash: string,
        data: string,
        timestamp: number
    ) {
        this.index = index;
        this.hash = hash;
        this.previousHash = previousHash;
        this.data = data;
        this.timestamp = timestamp;
        }
}
const genesisBlock: Block = new Block(0, '7412667', '', 'Hello', 123456);
// `blockchain`은 오직 `Block`에 관련된 것만 추가된다.
const blockchainn: Block[] = [genesisBlock];
console.log(blockchain);
export {};
해쉬값을 암호화하는 라이브러리
$ yarn add crypto-js
import * as CryptoJS from "crypto-js";
class Block {
  // 클래스가 생성되지 않아도 호출할 수 있는 method
  // index.js에서 클래스의 바깥에 나타난다.
  static calculateBlockHash = (
    index: number,
    previousHash: string,
    timestamp: number,
    data: string
  ): string =>
    CryptoJS.SHA256(index + previousHash + timestamp + data).toString();
}
const genesisBlock: Block = new Block(0, "7412667", "", "Hello", 123456);
const blockchain: Block[] = [genesisBlock];
// 블록체인의 길이를 알기 위해
const getBlockchain = (): Block[] => blockchain;
// 가장 최근의 블록
const getLatestBlock = (): Block => blockchain[blockchain.length - 1];
const getNewTimeStamp = (): number => Math.round(new Date().getTime() / 1000);
export {};
import * as CryptoJS from "crypto-js";
class Block {
  // 타입 체크
  static validateStructure = (aBlock: Block): boolean =>
    typeof aBlock.index === "number" &&
    typeof aBlock.hash === "string" &&
    typeof aBlock.previousHash === "string" &&
    typeof aBlock.timestamp === "number" &&
    typeof aBlock.data === "string";
}
const createNewBlock = (data: string): Block => {
  const previousBlock: Block = getLatestBlock();
  const newIndex: number = previousBlock.index + 1;
  const newTimestamp: number = getNewTimeStamp();
  const newHash: string = Block.calculateBlockHash(
    newIndex,
    previousBlock.hash,
    newTimestamp,
    data
  );
  const newBlock: Block = new Block(
    newIndex,
    newHash,
    previousBlock.hash,
    data,
    newTimestamp
  );
  // 새로운 블록을 만들때 블록체인에 추가
  addBlock(newBlock);
  return newBlock;
};
// 블록의 해쉬 얻기
const getHashforBlock = (aBlock: Block): string =>
  Block.calculateBlockHash(
    aBlock.index,
    aBlock.previousHash,
    aBlock.timestamp,
    aBlock.data
  );
// 블록체인의 기반은 블록들이 자신의 전 블록으로 링크가 되있기 때문에
// cadidate 블럭과 previous 블럭을 비교가 필요
const isBlockValid = (candidateBlock: Block, previousBlock: Block): boolean => {
  if (!Block.validateStructure(candidateBlock)) {
    return false;
  } else if (previousBlock.index + 1 !== candidateBlock.index) {
    return false;
  } else if (previousBlock.hash !== candidateBlock.previousHash) {
    return false;
  } else if (getHashforBlock(candidateBlock) !== candidateBlock.hash) {
    return false;
  } else {
    return true;
  }
};
// 블록체인에 블록을 추가
const addBlock = (candidateBlock: Block): void => {
  if (isBlockValid(candidateBlock, getLatestBlock())) {
    blockchain.push(candidateBlock);
  }
};
createNewBlock("second block");
createNewBlock("third block");
createNewBlock("fourth block");
console.log(blockchain);
/* [
  Block {
    index: 0,
    hash: '7412667',
    previousHash: '',
    data: 'Hello',
    timestamp: 123456
  },
  Block {
    index: 1,
    hash: '685619eeffd544173c3aba38c72cedb09236da037bf6745bf17a66bd02934a15',
    previousHash: '7412667',
    data: 'second block',
    timestamp: 1610462771
  },
  Block {
    index: 2,
    hash: 'ffb63d0c98b6cd2688e3441e06fbe023332dd297134842059627c5cb7638f66f',
    previousHash: '685619eeffd544173c3aba38c72cedb09236da037bf6745bf17a66bd02934a15',
    data: 'third block',
    timestamp: 1610462771
  },
  Block {
    index: 3,
    hash: '7d958c9f4dbec239a28559ccd2f80606d054d580f38d2b75d87f5a904d1208a5',
    previousHash: 'ffb63d0c98b6cd2688e3441e06fbe023332dd297134842059627c5cb7638f66f',
    data: 'fourth block',
    timestamp: 1610462771
  }
]
*/
export {};