개발/타입스크립트

TypeScript로 블록체인 만들기(1)

TTOLBE 2022. 12. 27. 15:53

Overview of TypeScript

이 글은 노마드 코더의 타입스크립트 무료 강의를 보고 노트 정리를 한 글입니다.
강의링크

2.0 How TypeScript Works

타입스크립트는 자바스크립트와 다르게 개발자를 보호해준다. 컴파일 이후에 코드의 에러를 알려주는 자바스크립트와 달리, 타입스크립트는 자바스크립트로 변환되기 전에 에러가 있다면 컴파일 되지 않는다.


  const Tollbe={
    nickname:"Tolby"
  };

  Tollbe.hello()

위와 같은 코드는 자바스크립트에서는 실행후 에러를 보내지만 타입스크립트에서는 실행되기 전 에러를 알려준다.


  function divide(a,b){
    return a/b
  }

  divide("hello")

위 코드 역시 에러가 난다. 나누기 연산을 통해 타입스크립트에서는 변수의 타입이 숫자여야 한다고 생각하고, 또한 변수가 하나밖에 주어지지 않았기 때문이다.

이러한 에러들은 타입스크립트의 특징인 타입 추론을 통해 생긴다.

2.1 Implicit Types vs Explicit Types

타입스크립트에는 타입을 지정해주는 특수한 시스템이 있다. 타입스크립트에서는 모든 변수의 타입이 정해진다. 사용자가 직접 정해주거나, 타입스크립트가 타입 추론을 한다.


  let a="Hello";

여기서 타입스크립트는 a 가 string 이라고 생각한다.


  a="bye";

  a=10;

위 코드를 타입스크립트로 작성하면 a 값을 bye로 재지정한 것은 오류가 나지 않지만, 10으로 재지정하면 오류가 난다. 타입 추론으로 a 값의 타입을 string으로 정한 것이다. 이 코드를 자바스크립트로 실행하면 아무런 문제 없이 작동하지만, 오류의 원인이 될 수 있다.

아래 코드는 사용자가 직접 타입을 정하는 방식이다.


  let b:boolean = false

위와 같은 방식이 TypeChecker와 소통하는 법이다. 아래는 배열의 타입을 정하는 방식이다.


  let c : number[] =[1,2,3]

위와 같이 쓰면 c는 숫자만으로 구성된 배열이 된다.


  c.push("4")

따라서 위와 같은 코드는 오류가 난다. 이는 오브젝트에서도 마찬가지다.


  const Player={
    name:"Ttolbe"
  }

  Player.name=12
  Player.hello()

위의 코드 역시 오류가 난다. Player.name은 이미 string으로 추론 되었고, Player 안에는 hello 라는 메소드가 존재하지 않기 때문이다.

2.2 Types of TS part One

지금까지 살펴본 타입스크립트의 기본 타입은 아래와 같다.


  let a:number=1;
  let b:string="abc;
  let c:boolean=true;

  let d:number[]=[1,2,3];
  let e:string[]=["a","b","c"];
  let f:boolean[]=[true,false,false];

이와 달리 optional type이 존재 한다. 만약 Player라는 object에 모두 name은 존재하지만 age는 optional일때 어떻게 해야 할까. 이때는 object 안의 type을 지정해주고 age에 물음표를 넣어주면 된다.


  const player:{
    name:string,
    age?:number
    }={
    name:"Ttolbe",
  }

하지만 위와 같이 코드 작성 후 아래 함수를 짜면 틀렸다고 나온다.


  if(player.age<10){

  }

age는 undefined일 수도 있기 때문에, age의 여부를 체크하는 보호장치를 넣어야 한다.


  if(player.age && player.age<10){

  }

만약 위 Player 같은 오브젝트를 여러개 만들고 싶은데 계속 일일히 type을 지정하기 싫다면 Alias 타입을 생성해 줄수 있다.


  type PlayerType={
    name:string,
    age?:number
  }

  const PlayerTtol:PlayerType={
    name:"Ttolbe"
  }

  const PlayerLynn:PlayerType={
    name:"Lynn",
    age:23
  }

Alias 타입을 선언하면 여러번 재사용 가능하기 떄문에 편하다. (Alias 타입명은 항상 대문자로 시작해야 한다.) Alias 타입은 오브젝트뿐 아니라 모든 형식에 사용할 수 있다.

함수 역시도 타입을 정할 수 있다.


  function playerMaker(name:string){
    return{
      name
    }
  }

  const ttolbe=playerMaker("ttolbe")

  ttolbe.age=20

위와 같이 ttolbe의 age 항목을 더하려고 하면 수정 되지 않는다. 이미 함수에서 오브젝트의 타입을 정했기 때문이다. 만약 playerMaker가 PlayerType의 오브젝트를 리턴한다고 명시하려면 아래와 같이 수정하면 된다.


  function playerMaker(name:string):PlayerType{
    return{
      name
    }
  }

  const ttolbe=playerMaker("ttolbe")

  ttolbe.age=20

위 함수에서는 age 값을 추가할수 있게 된다.

위와 같이 함수의 변수, 함수의 return 값 모두 type을 지정해 줄 수 있다.

참고로 화살표 함수에서는 아래와 같이 써주면 된다.


  const playerMaker=(name:string) :PlayerType =>({name})

2.3 Types of TS part Two

원하면 type에 readonly 속성을 추가 해줄수도 있다.


type PlayerType={
  readonly name:string,
  age?:number
}

위와 같이 readonly를 앞에 붙이면 해당 값은 바꿀 수 없다. readonly는 어떤 값이든 추가해 줄수 있다.


const numbers: readonly number[] = [1,2,3,4]

numbers.push(5)

numbers는 readonly값이기 떄문에 push하면 에러가 난다.

이번에는 Tuple에 관한 걸 배워보자. Tuple은 array를 생성하는데, 특정 길이를 가졌고, 특정 위치에 특정 값이 있어야 한다. 만약 차례대로 string, number, boolean 값이 있는 길이 3의 array가 필요하다고 해보자.


  const player:[string, number, boolean]=["ttolbe",20,true]

여타 다른 타입은 아래와 같은 것들이 있다.


let a:undefined =undefined;

let b:null=null;

또 다른 타입은 any 가 있다.


let a:any=1

any는 그 어떤 타입도 될 수 있다. 하지만 any를 사용하면 타입스크립트의 보호장치를 잃게 되기 때문에 추천되지 않는다.


let a:any=1;

let b:any=true;

a+b

보통 타입스크립트에서는 위의 코드가 오류 나지만 여기서는 type을 any로 지정했기 때문에 오류가 나지 않는다.

2.4 Types of TS part Three (07:21)

여기서 다루는 type은 타입스크립트 만의 type이다.


let a:unknown;

unknown은 변수의 타입을 알 수 없을 떄 쓰는 타입이다. 이럴 떈 변수를 사용 전에 변수가 어떠한 타입인지 확인하는 작업을 거쳐야 한다.


let a:unknown;

if(typeof a==="number"){
 let b=a+1;
}
if(typeof a=="string"){
  let b = a.toUpperCase();
}

void는 리턴하지 않는 함수를 의미한다.


function hello():void{
  console.log('hello')
}

마지막으로 다룰 타입은 never이다. never는 함수가 절대 리턴하지 않을 때 사용되는 타입이다.


function hello():never{
  console.log('hello')
}

never가 쓰이는 경우는 한가지 더 있다.


function hello(name:string|number){
  if(typeof name=="string"){

  }else if(typeof name=="number"){

  }else{

  }
}

위 함수에서 name은 반드시 string 또는 number이기 때문에 if에서의 name은 string, else if에서의 name은 number, 그리고 else에서의 name은 never타입이 된다.