[Typescript] Typescript로 블록체인 구현 (1/3)

Lee_Sangmin·2022년 6월 27일
0

personal

목록 보기
1/9

Introduction

  • Typescript는 microsoft에서 만들었기 때문에 같은 곳에서 만든 vscode app을 사용하는 것을 추천
  • Typescript의 핵심은 Type Checker와 소통하는 것.

개인적으로 다시 봤을 때, 즉각적으로 이해될 수 있도록 강의의 핵심부분만 기록하였습니다.

Overview of Typescript

type 지정은 사실 typescript가 자동적으로 하게 두는걸 추천한다.

let a = 'hello'; // let a: string = 'hello';
let b = false; // let b: boolean = false;
let c = [1, 2] // let c: number[] = [1, 2];
let d: number[] = []; // 값이 들어있지 않아 형을 알 수 없을 때는 명시적으로 지정해주는 것이 좋다.

Object 내부 인자 형 지정

const player: { name: string; age?: number } = {
  name: 'nico',
}; // player는 자동으로 object타입. (단순하게 :object로 형 지정 하면 안됨)

Alias 지정

type Player = {
  name: string;
  age?: number; // age: number|undefined 라는 뜻!
};

const god: Player = {
  name: 'sangmin',
};

return값의 type 지정

type Player = {
  name: string;
  age?: number;
};

// return 형을 Player로 지정
function playerMaker(name: string): Player {
  return {
    name,
  };
}

const sangmin = playerMaker('sangmin');
sangmin.age = 26;

readonly property

const numbers: readonly number[] = [1, 2, 3, 4];
numbers.push(5); // error : 'readonly number[]' 형식에 'push' 속성이 없습니다.ts(2339)
// Javascript에서는 사용되지 않는 기능.

Tuple

const player: readonly [string, number, boolean] = ['sangmin', 26, true];
player[0] = 26; // error : 읽기 전용 속성이므로 '0'에 할당할 수 없습니다.ts(2540)

unknown / void / never

let a: unknown;
const b = a + 1; // error : 개체가 '알 수 없는' 형식입니다.ts(2571)
if (typeof a === 'number') {
  const c = a + 1;
}

function hello() {
  console.log('return none');
} // 아무것도 리턴하지 않는 함수는 자동으로 void형

function hello2(): never {
  return 'x'; // error: 'string' 형식은 'never' 형식에 할당할 수 없습니다.ts(2322)
  // throw new Error('x')는 정상적으로 가능. return 없이 오류를 발생시키는게 목적.
}

Functions

Call Signatures

// 작동할 함수에 대해 미리 서술 가능.
type Add = (a: number, b: number) => number;

const add: Add = (a, b) => a + b;
// Typescript가 Call Signature를 알고있어서 가능.

Overloading

// Overloading은 일반적으로 함수가 여러개의 call signatures를 갖고있을 때, 발생
// type 지정 시, 사용될 수 있는 다형성을 고려하는 한가지 방식 
type Config = {
  path: string;
  state: object;
};

type Push = {
  (path: string): void;
  (config: Config): void;
};

const push: Push = (config) => {
  if (typeof config === 'string') {
    console.log(config);
  } else {
    console.log(config.path);
  }
};

// 패키지나 라이브러리를 디자인할 때 실제로 자주 사용되는 오버라이딩 구조

Polymorphism(Generics)

type NormalPrint = {
  (arr: number[] | boolean[]): void;
  // generic이란, type의 placeholder같은 것. (모든 call signature를 고려해하는건 너무 구리기 때문)
  // call signatures를 작성하는 때, 들어오는 확실한 타입을 모를때 사용
};

const normalPrint: NormalPrint = (arr) => {
  arr.forEach((i) => console.log(i));
};

normalPrint([1, 2, 3, 4]);
normalPrint([true, false, false]);
normalPrint(['1', '2', '3']); // error: 'string' 형식은 'number | boolean' 형식에 할당할 수 없습니다.ts(2322)

////

type SuperPrint = {
  // generic을 사용하는 예시 (인자로 주로 T나 V를 많이 사용함)
  <TypePlaceholder>(arr: TypePlaceholder[]): void;
};
const superPrint: SuperPrint = (arr) => {
  arr.forEach((i) => console.log(i));
};
superPrint([1, 2, 3, 4]); // 정상적으로 동작 (superPrint<number>([1, 2, 3, 4]) 와 동일)
superPrint([1, 2, true, '3']); // 정상적으로 동작


function superPrint2<V>(a: V[]) {
  return a[0];
}
superPrint2([4, 5, false, '6']); // 정상적으로 동작

Generics Recap

// generic을 하나 더 추가하는 방법
type SuperPrint = <T, M>(a: T[], b: M) => T;
// typeScript는 generic이 처음사용되는 지점을 기반으로 타입을 판단.

const superPrint: SuperPrint = (a) => a[0];

const a = superPrint([1, 2, 3, 4], 'x');
const b = superPrint([true, false, false]); // test.ts(1, 34): 'b'의 인수가 제공되지 않았습니다.

Conclusiions

// Generic의 사용에 대한 더 디테일한 예시들.
// 1)
type Player<E> = {
  name: string;
  extraInfo: E;
};

const sangmin: Player<{ favFood: string }> = {
  name: 'sangmin',
  extraInfo: {
    favFood: 'mandoo',
  },
};

// 2)
type Player<E> = {
  name: string;
  extraInfo: E;
};
type SangminExtra = {
  favFood: string;
};
type SangminPlayer = Player<SangminExtra>;

const sangmin: SangminPlayer = {
  name: 'sangmin',
  extraInfo: {
    favFood: 'mandoo',
  },
};


// 3)
type A = Array<number>;
let a: A = [1, 2, 3, 4];

// 4)
function printAllNumbers1(arr: number[]) {/* ~ */}
function printAllNumbers2(arr: Array<number>) {/* ~ */}

// useState에서 generic을 받기 때문에 주로 사용한다.
// ex) const [state,setState] = useState<number>();

ETC

profile
FE developer

0개의 댓글