타입스크립트를 배워보자

최근 많은 회사와 개발자들이 사용하고 있는 TypeScript!
많은 장점을 가지고 있다고 하는데 기존 자바스크립트만 사용했을 때와 타입스크립트를 도입하면 어떤 차이점이 있는지 궁금증이 생겨 포스팅을 합니다.

image.png

개발자 중심의 산업 분석 회사인 RedMonk가 GitHub 저장소와 Stack Overflow의 데이터에 기초해 발표한 프로그래밍 언어 순위에서 TypeScript는 2019년 1월에 12위였지만 2019년 6월에는 10위를 차지했다. 5개월 만에 Object-C와 Swift를 밀어내고 2계단이나 상승할 정도로 가파른 성장세에 있음을 확인할 수 있다.

TypeScript란?

Javascript + Type = TypeScript

타입스크립트는 자바스크립트의 대체 언어의 하나로서 자바스크립트의 Superset(상위확장)이고,
Microsoft에서 발표한 오픈소스로, 정적 타이핑을 지원하며 ES6의 클래스, 모듈 등과 ES7의 Decorator 등을 지원한다.

왜 TypeScript?

느슨한 타입의 언어인 자바스크립트를 사용해 만든 프로젝트에서는 규모가 커질수록 코드가 복잡해지고, 디버그와 테스트 공수가 증가하는 문제가 있어 이런 자바스크립트의 단점을 극복하고자 AltJs(자바스크립트 대체 언어)인 타입스크립트 가 등장했다고 한다.

image.png

타입스크립트의 장점

  • 정적 타입 - 컴파일 단계에서 오류를 포착할 수 있는 장점
  • 도구의 지원 - IDE와 같은 도구에 타입 정보를 제공함으로써 높은 수준의 코드 어시스트, 타입 체크, 리팩토링 등을 지원받을 수 있으며 이러한 도구의 지원은 대규모 프로젝트를 위한 필수 요소이다.
  • 강력한 객체지향 프로그래밍 지원 - Java, C# 등의 클래스 기반 객체지향 언어에 익숙한 개발자가 자바스크립트 프로젝트를 수행하는데 진입 장벽을 낮추는 효과가 있다.
  • ES6 / ES NEXT 지원 - 현재 ES6를 완전히 지원하지 않고 있는 브라우저를 고려하여 Babel 등의 트랜스파일러를 사용해야 하는 현 상황에서 TypeScript가 새로운 스펙의 유용한 기능을 안전하게 도입하는데 유리하다.

작업환경 설정

터미널에서 설치
yarn add typescript ts-node

  • typescript 타입스크립트를 사용하기 위해 설치
  • ts-node 따로 컴파일하지 않아도 ts파일을 실행시켜준다

타입스크립트 파일 설치
yarn run tsc --init

타입스크립트의 확장자로는 .ts를 사용하며, 컴파일의 결과물로 JavaScript 파일인 .js를 출력하고 최종적으로 런타임에서는 이렇게 출력된 JavaScript 코드를 구동시키게 된다.

변수에 알맞는 타입을 설정 후 해당하는 타입을 값으로 지정한다.
src > practice.ts

const message: string = "hello world";
const one: number = 1;

설정한 타입과 다른 타입의 값을 지정하게 되면 오류가 발생해 사소한 실수를 방지할 수 있다.

const message: string = 2;    // Error
const one: number = true;    // Error

기본 타입 알아보기

// number 타입의 변수이다.
let count = 0;

const message: string = "hello world";
const done: boolean = false;

const numbers: number[] = [1, 2, 3];
const messages: string[] = ["hi", "world"];

// 두가지의 타입은 | 연산자 사용
let mightBeUndefined: string | undefined = "hi";
let nullOrNumber: null | number = 3;

// 특정 값 하나만 지정하고 싶은 경우
let color: "red" | "orange" | "blue" = "red";
color = "blue";

color의 값은 자동완성이 지원된다.
image.png

함수 사용해보기

x, y 파라미터를 number 타입으로 지정하고, return하는 값도 number로 지정할 수 있다.

function sum(x: number, y: number): number {
  return x + y;
}

타입스크립트에서 함수의 파라미터의 타입을 지정하지 않았을 경우 모든 타입을 받는 : any가 기본으로 설정된다.

숫자 배열을 가져와서 총 합을 구하는 함수

function sumArray(numbers: number[]): number {
  return numbers.reduce((acc, current) => acc + current);
}

const total = sumArray([1, 2, 3, 4, 5]);
console.log(total); // 15

return 값이 없는 함수
타입이 void로 지정된다.

function returnNothing() {
  console.log("아무것도 리턴하지 않음");
}

returnNothing(); // returnNothing(): void

Interface

class 또는 객체를 지정하기 위해 사용되는 문법이다.

클래스는 객체를 만들기 위한 설계도이고 이 설계도를 토대로 만들어진 무언가가 객체이다.

Class

Shape 인터페이스는 결과물이 number getArea() 함수를 포함하고 있다.

interface Shape {
  getArea(): number;
}

// Circle이 Shape 인터페이스를 구현하도록 처리
class Circle implements Shape {        // 반지름 구하기
  radius: number;

  constructor(radius: number) {
    this.radius = radius;
  }
  getArea() {
    return this.radius * this.radius * Math.PI;
  }
}

class Rectangle implements Shape {    // 너비 구하기
  width: number;
  height: number;

  constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
  }

  getArea() {
    return this.width * this.height;
  }
}

// 사용
const circle = new Circle(5);
const rectangle = new Rectangle(2, 5);

Public & Private

타입스크립트 내부에서만 유의미한 속성으로 코드를 간편하게 만들어준다.

// public은 조회 가능
class Circle implements Shape {
  constructor(public radius: number) {
  }
  getArea() {
    return this.radius * this.radius * Math.PI;
  }
}

// private는 조회 불가능
class Rectangle implements Shape {
    constructor(private width: number, private height: number) {
  }
  getArea() {
    return this.width * this.height;
  }
}

객체

// 인터페이스 생성
interface Person {
  name: string;
  age?: number; // ? 는 age가 존재하거나 존재하지 않도록 설정
}

interface Developer extends Person {
  // Person 인터페이스의 속성을 상속받은 새 인터페이스
  skills: string[];
}

// 객체 생성
const person: Person = {
  name: "Jon",
  age: 23
};

const expert: Developer = {
  name: "김개발",
  skills: ["js", "css", "typescript"]
};

Type Alias

type을 사용해서 interface와 똑같이 작동하는 코드를 생성한다.

type Person {
  name: string;
  age?: number; // ? 는 age가 존재하거나 존재하지 않도록 설정
}

type Developer = Person & {
  // Person 인터페이스의 속성을 상속받은 새 인터페이스
  skills: string[];
}

// 객체 생성
const person: Person = {
  name: "Jon",
  age: 23
};

const expert: Developer = {
  name: "김개발",
  skills: ["js", "css", "typescript"]
};

Alias(별칭)은 type에 별칭을 줄 수 있다.

type People = Person[];
const people: People = [person, expert];

type Color = "red" | "orange" | "yellow";
const color: Color = "orange";

객체에 대한 타입을 정의할 때 대부분의 경우에는 type Alias를 사용하지만
라이브러리에 대한 타입을 정의하는 경우에는 Interface를 권장하며, 일관성 있게 사용해야 한다.

Generics

타입스크립트에서 함수, 클래스, 인터페이스, Type Alias등 여러 종류에 타입에 대해 호환을 맞추는 경우에 사용된다.

파라미터의 타입이 정해지지 않는 경우에 Generics를 적용한다.

function merge<T1, T2>(a: T1, b: T2) {
  return {
    ...a,
    ...b
  };
}

const merged = merge({ foo: 1 }, { bar: 2 });

Generics <T1, T2>를 사용해 실제 파라미터에 넣는 타입을 유추할 수 있다.

function wrap<T>(param: T) {
  return {
    param
  }
}

const wrapped = wrap('a');    // string 

담기는 값에 따라 타입을 유추한다.

참조

https://d2.naver.com/helloworld/2108442