[TypeScript] 타입을 선언하는 방법

hyeon·2024년 12월 8일

선언 가능한 모든 타입

타입 선언

1. 주요타입

  • 불린 : boolean | 숫자 : number | 문자열 : string

  • 배열 : Array

let fruits: string[] = ["Apple", "Banana", "Mango"];
let fruits: Array<string> = ["Apple", "Banana", "Mango"];

let oneToSeven: number[] = [1, 2, 3, 4, 5, 6, 7];
let oneToSeven: Array<number> = [1, 2, 3, 4, 5, 6, 7];

let array: (string | number)[] = ["Apple", 1, 2, "Banana", "Mango", 3];
let array: Array<string | number> = ["Apple", 1, 2, "Banana", "Mango", 3];

let someArr: any[] = [0, 1, {}, [], "str", false];

  • 인터페이스 : interface
interface IUser {
  name: string;
  age: number;
  isVaild: boolean;
}

let userArr: IUser[] = [
  {
    name: "Neo",
    age: 10,
    isVaild: true,
  },
  {
    name: "Lewis",
    age: 64,
    isVaild: false,
  },
  {
    name: "Evan",
    age: 123,
    isVaild: true,
  },
];

=> 객체 형태에 우리가 커스텀 타입을 표현하는 방법


  • 타입 별칭: type
type User = {
    name: string;
    age: number;
    isValid: boolean;
};

let userArr: User[] = [
    {
        name: "Neo",
        age: 10,
        isValid: true,
    },
    {
        name: "Lewis",
        age: 64,
        isValid: false,
    },
    {
        name: "Evan",
        age: 123,
        isValid: true,
    },
];

=> 우리가 인터페이스처럼 원하는 타입을 만들려고 할때,
또 쓰는게 있는데 바로 타입 별칭입니다. 영어로는 Type Alias라고 합니다.
커스텀 타입을 선언할때는 파스칼 케이스 로 작성해야합니다!!!

인터페이스와 타입은 몇가지 차이점을 빼면 거의 유사합니다.


  • Null과 Undefined
let undefin: undefined = undefined;
let nul: null = null;

let stringOrNull: string | null = null;
let numberOrUndefined: string | undefined = undefined;

=> 이건 어떨 때 사용할까? 뒤에 나오는 Union 문법과 같이 쓸때
많이 활용됩니다.


  • 모든타입: any
let any: any = 123;
any = 'play game';
any = {};
any = null;

const arr: any[] = [1, true, 'typescript'];

=> 타입스크립트의 치트키입니다. 아무거나 다 들어가는 친구예요.


  • void
function coding(msg: string): void {
  console.log(`Happy ${msg}`);
}

=> void는 "공허하다" 라는 뜻을 가진 단어입니다.
void는 특정 어떤 함수가 리턴 값이 없을 때를 의미합니다.


  • 유니온(Union)

    📌 유니온 타입이란 자바스크립트의 OR 연산자(||)와 같이 A or B 이다 라는 의미
    => | 연산자를 사용해서 여러 타입을 연결하는 방식을
          유니온 타입 정의 방식이라고 합니다.

let union: (string | number);
union = 'Hello World';
union = 777;
union = false; // Error

  • 인터섹션(Intersection)

    📌 타입 인터섹션
    인터섹션 타입은 2개 이상의 타입을 조합하여 하나의 타입으로 합치는 방식입니다. 이는 자바스크립트의 AND 연산자(&&)와 비슷한 개념으로, A 이면서 동시에 B인 타입을 의미합니다.

interface User {
  name: string,
  age: number
}

interface Validation {
  isValid: boolean
}

const testCase2: User & Validation = {
  name: 'jisu',
  age: 30,
  isValid: true
}

  • 함수(Function)
let myFunc: (arg1: number, arg2: number) => number;
myFunc = function(x, y) {
  return x + y;
}
myFunc(1, 2); // 3

let noneFunc: () => void;
noneFunc = function () {
  console.log('hihi');
};

함수에는 타입이 들어갈 수 있는 자리가 크게 2개 있는데,
첫번째는 argument들의 타입이에요 => 인자들의 타입
두번째는 반환 값의 타입이에요

기본적으로 여기까지는 좀 알아둬야 한다라는 타입이고,
아래서부터는 알면 좋다 라는 내용입니다.




2. 이런 타입도 있어요

  • 읽기 전용: readonly
let arrA: readonly number[] = [1, 2, 3, 4];
let arrB: ReadonlyArray<number> = [2, 4, 6, 8];

=> readonly로 선언한 이 변수는 수정이 안됩니다.

arrA.push("a")

만약 위처럼 명령어를 친다면,
Property 'push' does not exist on type 'readonly number[]'

이런 오류를 보게 됩니다.

=> 여기서 우리가 알 수 있는 점은 타입스크립트는 자바스크립트에 있는 원시 타입 뿐만 아니라, 타입스크립트가 가지고 있는 어떠한 기능들을 추가적으로 가지고 있다는 것을 캐치할 수 있습니다.


  • 튜플: Tuple
    튜플은 배열 형태인데, 길이와 값이 어느정도 정해져있는 배열을 뜻해요. 밑에 예시를 보면 배열안에 [string, number] 가 이렇게 들어가 있죠? 그러니깐 첫번째엔느 string이 들어가고 두번째에는 number가 들어가는거에요
let tuple: [string, number];
tuple = ['a', 1];
tuple = [1, 'a']; // Error

let userA: [number, string, boolean] = [1234, 'juyoung', true];

let usersA: [number, string, boolean][];
let usersB: Array<[number, string, boolean]>
usersA = [[1, 'chisus', true], [2, 'jisu', false]];

let tupleA: [1, number];
tupleA = [1, 2];
tupleA = [2, 3]; // Error

let a: readonly [string, number] = ['rest', 123];
a[0] = 'work'; // Error

  • 열거형: enum
enum Week {
  Sun,
  Mon,
  Tue,
  Wed,
  Thu,
  Fri,
  Sat
}

enum Color {
  Red = 'red',
  Green = 'green',
  Blue = 'blue'
}

어떤 여러가지 값들에 대한 것 (예를들어, 한주의 요일 같은 것)을 표현하고 싶을때 타입을 객체로 표현하는 것이 아니라, 우리가 원하는 대주제(Week)에 대해서 여러가지 소 카테고리들을(Sun,Mon...,Sat) 타입으로 표현하고 싶을때 사용합니다.


  • 객체: object
let obj: object = {};
let arr: object = [];
let func: object = function () {};
let date: object = new Date();

interface Users {
  name: string,
  age: number
}

let userA: Users = {
  name: 'juyoung',
  age: 27
};

이렇게 쓸 수 도있지만, 위에 배웠던 인터페이스나 타입 별칭을 훨씬 더 많이 사용합니다. 그래서 object 타입이구나 타입으로 되어있구나 정도만 알면 됩니다. 맨 위에 사진을 보면 Object는 Array, Function 등을 포함하고 있는 타입입니다. 그래서 여러분이 알고 있는 객체라는 것보다는 조금 더 넓은 타입입니다.


  • 알 수 없는 타입: unknown
let u: unknown = 123;
let test1: number = u; // Error
let test2: number = u as number;
let test3: any = u;

unknown 타입은 타입 위계에 가장 위쪽에 있는 전체 집합 같은 친구예요. 그래서 우리가 타입을 알 수 없을 때 쓰게 됩니다.

  • Never
function error(message: string): never {
  throw new Error(message);
}

const never: [] = [];
never.push(3); // Error

Never는 타입 위계에 가장 아래쪽에 있죠? 이거는 집합에서 공집합을 의미합니다. 아무 타입도 포함하고 있지 않은 타입이에요.




Type alias vs interface

// Type alias
type ExampleType = {};
type StringType = string;
type UnionType = string | number

// interface
interface ExampleInterface {
	example : string;
}

둘다 비슷한 개념이라고 앞에서 설명했는데,
그렇다면 둘 중에 뭐가 좋을까??

우리가 집중할 내용은 "매우 유사하며, 많은 경우 자유롭게 선택할 수 있습니다" 입니다.

하지만 대표적인 차이점을 알고 넘어가야겠죠?

1. 확장성(Extensibility)

interface Hello {
	name: string
}

interface Hello {
	age: number
} // ✅ 가능, Hello 는 name 과 age 모두를 포함하게 됨

type Hello2 = {
	name: string
}

type Hello2 = {
	age: number 
} // 🙅‍♂️ 불가능

첫번째는 확장성이 달라요. 인터페이스의 경우에는 확장해서 추가하는 것이 가능해요.


2. 복잡한 타입 표현(Complex Type Expressions)

  • 인터페이스(interface): 객체 형태의 타입을 정의하는데 주로 사용
  • 타입 별칭(type alias): 객체 뿐만 아니라, 유니온 타입, 튜플, 매핑된 타입 등 복잡한 타입표현에 유리합니다
    => type A = B | C 처럼 더 다양한 타입을 정의할 수 있습니다.
profile
당근🥕

0개의 댓글