TypeScript 타입 정의

Yuno·2021년 8월 23일
4
post-thumbnail

타입스크립트란 자바스크립트 기반으로 타입을 추가한 자바스크립트의 슈퍼셋입니다.
조금 더 엄격한 문법으로 작성할 수 있습니다.

TS를 쓰는 이유

버그 방지
두 숫자를 더하는 함수에서,

function add(a,b) {
  return a+b
}
add(1,2);

add('1','2');

위 경우는 의도한 대로 3이 나오지만
아래는 '12'로 의도하지 않은 결과가 나오게 됩니다.

맞지 않는 타입의 변수나 함수에서 에러를 발생시켜 버그를 사전에 제거할 수 있습니다.

코드 자동 완성
타입이 정해지면, 개발 툴의 기능을 최대한 발휘할 수 있습니다.

add함수는 항상 숫자를 반환하지만, 툴은 그것을 인지하지 못합니다.
때문에, 숫자 반환 값에 대한 자동 완성을 제공하지 않습니다.

function add(a: number, b: number): number {
  return a + b;
}

const total = add(10, 20);
total.toLocaleString();

반환 값에 number 타입이 지정되어 있기 때문에,
toLocaleString 자동 완성이 제공됩니다.

또한, 자바스크립트와 호환 된다는 점
프론트엔드 프레임워크에서 지원한다는 점도 사용 이유에 속합니다.

CRA

React 초기 개발 환경을 설정해 주는 CRA에서 옵션 하나 추가로,
타입스크립트를 사용할 수 있는 환경을 설정할 수 있습니다.

npx create-react-app my-app --template typescript

타입 정의

타입스크립트로 타입을 정의할 수 있습니다.

콜론을 이용하여 타입을 정의합니다.

const name: string = 'yuno';

📃 기본 타입

가장 자주 쓰는 string, number, boolean 타입이 있습니다.

const name: string = 'yuno';
const age: number = 24;
const isArmy: boolean = false;

비교적 쉽게 정의하고 사용할 수 있습니다.

📃 배열 타입

배열 타입도 정의할 수 있습니다. 내부 데이터에 대한 타입을 정의합니다.

const scores: number[] = [10,20,30];

//제네릭 사용
const scores: Array<number> = [10,20,30];

튜플은 배열의 길이가 고정되며 각 요소의 타입이 정의됩니다.

길이가 고정되어 있어, 확장성이 떨어질 수 있는데 어떤 활용도가 있을까요?

const arr:[string,number] = ['abc',10]

위치에 해당하는 타입이 아니거나, 정의한 인덱스가 아니라면 에러가 발생합니다.

함수 타입 정의

함수 정의

함수의 타입을 정의할 수 있습니다.

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());

마찬가지로 콜론을 통해 매개변수 타입을 정의합니다.
반환 값의 타입은 소괄호 우측에 타입을 정의합니다.

위 함수는 Date 객체 타입을 받아, 문자열을 리턴해야합니다.

만약, 반환 값이 없는 함수라면 void 타입을 지정합니다.

function showMessage(message:string): void {
  // ...
} 

void는 어떤 타입도 없다는 뜻으로, 보통 함수에 반환값이 없을 때 사용합니다.

화살표 함수도 마찬가지로 정의합니다.

const formatDate = (d:Date): string => {}

매개 변수 타입

함수의 유연성을 위해 여러 타입의 변수를 받을 수 있습니다.

let formatDate = (d: Date | number, lang = "ko", delimiter?: string): string => {
	// ...
};

formatDate(new Date());
formatDate(20201028, "en", "-");

|를 통해 Date 또는 number를 받을 수 있습니다. 이를 union이라 합니다.

?:를 사용하여, 선택적으로 인자를 전달할 수 있습니다.

자바스크립트와 동일하게 기본 값을 설정할 수 있습니다.
위에서는 타입을 정의하지 않았는데, 이는 타입 추론에 의해 string으로 정의됩니다.

Rest 문법
ES6의 Rest 문법은 타입스크립트에서 다음 처럼 정의합니다.

function sum(a: number, b: number, ...restNumbers: number[]) {

}

새로운 타입

자바스크립트에서는 사용되지 않지만, 타입스크립트에서 볼 수 있는 타입입니다.

Any
any는 어떤 타입도 지정할 수 있습니다. 이는, Javascript와 다르지 않습니다.
실제로, js로 컴파일된 코드를 보면 원래의 js와 동일합니다.

ts를 쓰는 이유가 없는 것과 다름 없습니다.

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

📂 Enum

Enum은 js외의 다른 언어에는 존재하는 데이터 타입입니다.

이름이 있는 정해진 값(상수)의 세트라고 생각하면 됩니다.
변수가 상수의 세트 값 중 하나를 가지게 하고 싶다면 사용합니다.

enum Category {
	Pasta,
	Pizza,
	Dessert
}

let menuCategory: Category = Category.Pasta;

Category Enum을 타입으로 정의하였습니다.
이는, Enum 내부 상수 값 중 하나로만 할당될 수 있음을 말합니다.

Enum에 값을 부여하여 해당 값을 사용합니다.

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

let menuCategory: Category = Category. Pasta;

상수 세트를 정의하는 방법으로 볼 수 있습니다.

타입스크립트에서는 상수 객체를 사용하기 보다,
enum을 정의하고 값을 사용하고, 타입으로 정의할 수 있습니다.

//types.ts
enum MenuTitle {
  Home : "홈",
  Search : "탐색",
  Category : "카테고리",
}

// Menubar.tsx
import {MenuTitle} from './types';

📂 union

여러 타입이 올 수 있을 때 사용합니다.

function formatDate(date: string | number | Date): string {
  // ...
}

인자로 string, number, Date가 모두 올 수 있습니다.

튜플은 정확한 형식을 지켜야합니다.

let arr: [number,string][] = [[1,'yuno'],[2,'admin']];

union은 여러가지 중 하나가 올 수 있습니다.

let arr: (number|string)[] = [1,2,'3',4,5,'6'];

소괄호를 주의해야 합니다.
위 경우는 배열 안에 number나 string 모두 올 수 있습니다.

let arr: number[] | string[] 

위 타입은 number만 있는 배열이거나, string만 있는 배열이어야 합니다.

📂 type 별칭 (Type Alias)

type 키워드를 통해 타입에 이름을 붙혀 사용할 수 있습니다.
어떤 타입을 재사용해야 하거나, 객체를 위한 타입등을 정의합니다.

type ID = number | string;
type Info = {
  id : ID; // 세미콜론 주의
  pw : string;
}

function checkInfo(info:Info) {}

객체 타입을 정의하는 방법에는 type 별칭 외에도, Interface를 사용할 수 있습니다.

타입추론
TS에서는 타입을 생략하고, 자바스크립트처럼 작성을 해도 잘 동작합니다.
이는 컴파일러가 변수에 할당된 값을 보고 타입을 추측하기 때문입니다.

Interface

자바에서 인터페이스는 클래스에서 꼭 구현해야하는 메서드를 정의할 때 사용됩니다.
(클래스의 설계도 처럼 사용)

타입스크립트의 인터페이스는 객체를 정의할 때 자주 사용됩니다.

객체 타입을 직접 정의할 수도 있습니다.

funtion setInfo(restaurant: {name: string}): void {
  // ...
}

하지만, 객체의 프로퍼티가 많아지면, 코드가 길어지고 가독성이 떨어집니다.

인터페이스를 작성하여 객체의 타입을 정의합니다.

interface Restaurant {
  name: string;
  star: number;
}

function setInfo(restaurant: Restaurant) {
  // ...
}

프로퍼티 타입

객체의 프로퍼티를 정의할 때 다양하게 사용할 수 있습니다.

interface Restaurant {
  readonly name: string;
  star: number;
  address?: string;
}

인터페이스 확장

extends를 사용하여 기존 정의된 인터페이스를 확장해 사용할 수 있습니다.

interface Info {
  name: string;
  star: number;
}

interface DetailInfo extends Info {
  address: string;
  phone: string;
}

기존 인터페에스를 확장하여, 새로운 인터페이스를 정의할 수 있습니다.

객체의 타입을 정의할 때, type 별칭과 interface 모두 사용할 수 있습니다.

type은 객체외에도 어떤 타입을 변수처럼 만들 때 별칭을 만들 수 있고,
interface는 객체 타입을 정의할 때 확장등의 기능을 가집니다.

디버깅 상황에서, type은 모든 프로퍼티를 확인할 수 있고, interface는 확인할 수 없습니다.

상황에 따라 적절히 사용할 수 있습니다.

타입스크립트 공식 문서에는 type보다 interface를 사용하라고 합니다.

제네릭

타입스크립트에서 타입을 명시하고, 올바른 타입을 할당하면서 사용할 수 있습니다.
제네릭을 사용하면 화살괄호< >를 사용하여, 유동적으로 타입을 정의할 수 있스니다.

고정된 타입이 아니라, 원하는 타입을 지정해서 사용할 때 제네릭을 사용합니다.

function makeArray<T>(element:T[]): T[] {
  return [element]
}

makeArray<number>(1); // :number[]
makeArray<number>("1"); // :string[]

함수명 우측에 화살괄호로 감싸 변수명으로 사용합니다.
함수 호출 시 제네릭에 입력된 타입으로 함수의 여러 타입들에 사용할 수 있습니다.

위 예시는 제네릭에 입력받은 타입의 배열형으로 인자를 받고, 반환합니다.

profile
web frontend developer

0개의 댓글