WEB/TypeScript

[TypeScript] 개요 및 블록체인 예시

소개

TypeScript MS사에서 만든 open-source 언어이다. 

기반은 JS이다. 즉, javascript superset이다.

 

개인적인 견해로는 JS의 상위 호환 언어이다.

마치 C/C++ 관계처럼..

 

JS와 차이점

가장 크게 차이나는 점은 변수 type명시이다. 

 

JS의 특징 중 하나가 뭐든 일단 받는다.

그러다 보니 작업하다 보면 이게 맞는지 헷갈린다.

 

하지만, typescript는 명시를 하기 때문에 코드를 작성하면서 예측이 가능하다.

-> 인수나 변수 타입이 안 맞는 경우 ts자체적으로 컴파일 불가하다.

 

이외 세세한 것들은 공식 문서를 참고해보자.

www.typescriptlang.org/docs/

 

The starting point for learning TypeScript

Find TypeScript starter projects: from Angular to React or Node.js and CLIs.

www.typescriptlang.org

 

개발 흐름

.ts컴파일 결과물.js 파일이 출력된다. 

최종적으로 런타임에서는 출력된 .js파일을 구동시킨다.

 

개발 환경

ts를 사용하려면 npm이 필요하다.

즉, Node.js가 사전에 설치가 필요하다.

 

npm을 통해 yarn도 설치해줘야 한다.

 

package.json 파일

필자 개발 환경은 window10이다.

인 경우 start에서 npx를 빼도 잘된다.

{
  "name": "typechain",
  "version": "1.0.0",
  "description": "Learning Typescript by making a blockchain whith it",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "npx tsc-watch --onSuccess \"node dist/index.js\" "
  },
  "devDependencies": {
    "@types/node": "^14.14.35",
    "ts-node": "^9.1.1",
    "tsc-watch": "^4.2.9",
    "typescript": "^4.2.3"
  },
  "dependencies": {
    "crypto-js": "^4.0.0"
  }
}

 

tsconfig.json 파일

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES2015",
        "sourceMap": true,
        "outDir": "dist"
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules"
    ]
}

.ts은 src 파일에 .js는 dist 파일에 생성되도록 설정했다.

js는 ES6(ES2015)를 사용했다.

 

 

예시 : 블록체인( 노마드 코더 )

import * as CryptoJS from "crypto-js";

class Block {
    static calculateBlockhash = (index: number, previousHash: string,
        timestamp: number, data: string): string =>
        CryptoJS.SHA256(index + previousHash + timestamp + data).toString();

    static vaildateStructure = (aBlock: Block): boolean =>
        typeof aBlock.index === "number" &&
        typeof aBlock.hash === "string" &&
        typeof aBlock.previousHash === "string" &&
        typeof aBlock.timestamp === "number" &&
        typeof aBlock.data === "string";

    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.data = data;
        this.hash = hash;
        this.previousHash = previousHash;
        this.timestamp = timestamp;
    }
}

const genesisBlock: Block = new Block(0, "hello", "20202020202020", "", 123456);

let blcokchian: Block[] = [genesisBlock];

const getBlockchain = (): Block[] => blcokchian;

const getLatestBlcok = (): Block => blcokchian[blcokchian.length - 1];

const getNewTimeStamp = (): number => Math.round(new Date().getTime() / 1000);

const createNewBlock = (data: string): Block => {
    const previousBlcok: Block = getLatestBlcok();
    const newIndex: number = previousBlcok.index + 1;
    const newTimestamp: number = getNewTimeStamp();
    const newHash: string = Block.calculateBlockhash(
        newIndex,
        previousBlcok.hash,
        newTimestamp,
        data
    );
    const newBlock: Block = new Block(
        newIndex,
        newHash,
        previousBlcok.hash,
        data,
        newTimestamp
    );
    addBlock(newBlock);
    return newBlock;
}

const getHashforBlock = (aBlock: Block): string => Block.calculateBlockhash(aBlock.index, aBlock.previousHash, aBlock.timestamp, aBlock.data);

const isBlcokVaild = (candiateBlcok: Block, previousBlcok: Block): boolean => {
    if (!Block.vaildateStructure(candiateBlcok)) {
        return false;
    }
    else if (previousBlcok.index + 1 !== candiateBlcok.index) {
        return false;
    }
    else if (previousBlcok.hash !== candiateBlcok.previousHash) {
        return false;
    }
    else if (getHashforBlock(candiateBlcok) !== candiateBlcok.hash) {
        return false;
    }
    else {
        return true;
    }
}

const addBlock = (candidateBlock: Block): void => {
    if (isBlcokVaild(candidateBlock, getLatestBlcok())) {
        blcokchian.push(candidateBlock);
    }
}

createNewBlock("second block");
createNewBlock("third block");
createNewBlock("4th block");

console.log(blcokchian);

export { };

코드 블록에 ts가 없어 js파일로 올리다 보니 하이라이트 처리가 제대로 안됐다. 

-> public이나 변수 이름들을 주목하자.

 

결과