# 5 주차 - 타입 스크립트(1)

simoniful·2021년 9월 13일
2

Python, JS, PHP 등은 동적 타입언어입니다. 변수의 타입은 함수, 렌더링이 실행되고 있는 동작안에서 결정됩니다. 반대로 정적타입 언어도 있습니다. Java, C++, Swift 등은 컴파일하는 과정에서 그 변수의 데이터 타입이 결정됩니다. 두 언어의 차이는 단순해 보이지만, 개발할 때 고려할 사항에서 개발자의 소요가 크게 줄어들게 됩니다.

동적 타입언어정적 타입언어
자동적인 타입 지정으로 배우기 쉽습니다.
코드양이 적을 때 생산성이 높습니다.
타입 오류가 런타임 시에 발견됩니다.
변수를 선언할 때 마다 타입을 고민해야합니다.
코드의 양이 많을 때 동적 타입 언어에 비해서 생산성이 올라갑니다.
타입 오류가 컴파일 시 발견됩니다.

프로젝트의 규모에 따라 장단점이 다릅니다.

타입으로 서로 연결된 정적 타입언어의 코드는 모듈화된 코드 간에 이동이 쉽고 변수명이나 함수명을 변경하는 등 리팩토링이 쉽습니다. 한번 지정된 타입에 대해서 import가 별도로 필요없이 접근하기 용이합니다.

사용

function formatDate(d: Date): string {
	let year = d.getFullYear();
	let month = d.getMonth() + 1;
	let day = d.getDate();
	return `${year}${month}${day}`
}

const today = formatDate(new Date());
  • 매개변수의 우측에 콜론(:)과 매개변수의 타입을 정의합니다.
  • return 값의 타입은 소괄호()우측에 타입을 정의합니다.
  • formatDate의 매개변수 d는 Date 객체 타입을 받아야하고, return 값은 문자열이어야 합니다.
let formatDate = (d: Date | number, lang = "ko", delimiter?: string): string => {
	// 로직 생략
};

formatDate(new Date());
formatDate(20201028, "en");
formatDate(20201028, "en", "-");
  • 두 번째 매개변수인 lang의 경우 인자를 전달하지 않으면 "ko"라는 문자열 값이 할당되도록 했습니다.
  • delimiter는 물음표를 사용하여 선택적으로 인자를 전달하도록 했습니다.

타입

정적타입언어는 원래 모든 변수에 정확히 타입을 정의하지 않으면 에러가 나지만, 타입스크립트에서는 타입을 표기하지 않아도 타입스크립트 컴파일러가 변수에 할당된 값을 보고 타입을 추측합니다. 코드량이 줄어들고 불필요한 타입 정의를 생략해서 가독성을 높이기도 합니다. 굳이 필요없는 타입 정의는 생략하되, 나중에 유지보수를 위해서는 타입을 정의하는 것이 스스로에게 좋습니다.

let starArr = [1, 2, 3];
starArr.push('4점');  
// 에러: *Argument of type 'string' is not assignable to parameter of type 'number'.*

Any

any는 어떤 타입도 지정할 수 있습니다. 자바스크립트로 컴파일된 코드를 보면 아무 타입도 지정하지 않은 원래의 자바스크립트 코드와 똑같습니다. 즉, any 타입을 사용하면 타입스크립트를 쓸 이유가 없는 것과 다름 없습니다.

Void, never

void는 any와는 반대로 어떤 타입도 없다는 뜻입니다. 보통 함수에서 반환값이 없는 경우 사용합니다.

function clickButton(): void {
	alert('Clicked!');
}

never는 항상 예외가 발생하여 비정상적으로 종료되거나 무한 루프 때문에 종료되지 않는 함수의 반환 타입일 경우 사용합니다.

function aFunc(): never { 
  while(true) {
    // ...
  }
}

Enum(열거형 타입)

Enum은 이름이 있는 정해진 값의 세트라고 생각하시면 됩니다. 상수로된 세트 값이 필요할 때, 주로 활용합니다.

enum Category {
	Pasta,
	Pizza = 'pizza',
	Dessert = 'dessert'
}

let menuCategory: Category = Category. Pasta;
console.log(menuCategory);
// 특정 값이 없는 Enum의 경우 0부터 값이 주어집니다. 기본 값은 인덱스 number 타입으로 할당이 되나, 특정 값을 지정할 수 있습니다. 

Intersection, Union

Intersection, union 타입은 여러 타입이 올 수 있을 때 사용합니다. 교집합과 합집합을 해당 타입으로 표현할 수 있습니다.

function formatDate(date: string | number | Date): string {
	// 로직 생략
	return `${year}${month}${day}`
}
formatDate(20201028);
formatDate(new Date());
formatDate('20201028');

let 변수: (1 | 3 | 5) & (3 | 5 | 7);
변수 = 3;
변수 = 1;  // 타입 에러
  • formateDate 함수의 매개변수로 문자열, 숫자, Date 객체 타입으로 모두 받을 수 있다면 → 수직선(|)을 사용해서 정의할 수 있습니다.
  • 집합의 개념처럼 원하는 타입으로 지정할 수 있습니다.

Tuple

Tuple(튜플)은 배열과 마찬가지로 데이터를 순차적으로 저장할 수 있는 자료형 중 하나이며, 타입스크립트에서는 배열에 두 개 이상의 타입을 사용하고 싶을 때 주로 사용합니다. 정의한 타입의 배열 내 타입의 값이 모두 있어야 합니다

let batchInfo: [number, string][];
batchInfo = [[1, '1기'], [2, '2기'], [3, '3기']];

union은 사용하고자 하는 타입 중에 하나만 있어도 가능합니다. 튜플을 사용하면 배열의 요소에 정의한 타입이 모두 존재해야 합니다.

Type 별칭 (Type Alias)

type 이라는 키워드를 사용하여 타입에 이름을 붙여서 사용할 수도 있습니다. 타입을 재사용하거나, 객체를 위한 타입을 정의할 때 많이 사용됩니다.

type ID = number | string;
type Info = {
	id: ID;
	pw: string;
};
function checkInfo(info: Info) {
  // ...
}
let id: ID = "1010";
checkInfo({ id, pw: "password" });
  • checkInfo 함수의 매개변수 info 객체를 위해 Info라는 타입을 만들어주었습니다.
  • 객체의 타입을 정의하는 법이 두 가지 있는데 하나는 위와 같이 type으로 정의하는 것이고, 나머지 하나는 Interface 타입을 사용하는 것입니다.

Primitive

const size: number = 123;
const isBig: boolean = size >= 100; 
const msg: string = isBig ? "크다" : "작다";

const values: number[] = [1, 2, 3];
const values2: Array<number> = [1, 2, 3];
values.push('a');  // 타입에러

const data: [string, number] = [msg, size];  // 문자열과 숫자로 구성된 튜플 타입
data[0].substr(1);
data[1].substr(1);  // 타입에러

let v: object;
v = { name: 'abe' };
console.log(v.prop1);  // 타입에러

null, undefined

단독으로 해당 타입을 사용하기 보다는 다른 타입과 함께 유니온 타입으로 정의할 때 많이 사용합니다.

let 변수: number | undefined = undefined;
변수 = 123;

literal

소스 코드의 고정된 값을 대표하여 사용가능합니다.

let 변수: 10 | 20 | 30;
변수 = 10;
변수 = 15;  // 타입 에러

Interface

profile
소신있게 정진합니다.

0개의 댓글