[Week10] 프론트엔드 기초: React + TypeScript(7)

Younha Lee·2026년 3월 14일

TIL

목록 보기
46/61

지난 시간에 이어 타입스크립트의 다양한 데이터 타입과 클래스 문법에 대해 알아볼게요.

리터럴 타입

특정한 값 자체를 타입으로 지정하는 리터럴 타입이 있어요. 이 타입을 사용하면 코드의 의도를 명확하게 표현할 수 있고, 허용되지 않은 잘못된 값이 들어오는 것을 사전에 방지할 수 있어요.

// 문자열 리터럴
let gender: 'male' | 'female';
gender = 'male'; 
// gender = 'man'; // 에러: 'male'과 'female'만 사용 가능

// 숫자 리터럴
let num: 10 | 100 | 1000;
num = 10; 
// num = 5; // 에러: 10, 100, 1000만 사용 가능

// boolean 리터럴
let flag: true;
flag = true; 
// flag = false; // 에러: true만 사용 가능

// 객체 리터럴
let obj: { pro1: string, pro2: number, pro3: string };
obj = {
  pro1: 'obj', 
  pro2: 123, 
  pro3: 'test'
  // 정의된 타입 형태를 정확히 지켜야 에러가 발생하지 않아요.
}

타입 별칭 (Type Alias)

type 키워드를 사용하면 복잡한 타입에 새로운 이름(별칭)을 부여해서 재사용할 수 있어요.

type Gender = 'male' | 'female';

let gender: Gender;
gender = 'male'; 
// gender = 'woman'; // 에러 발생

any 타입

any 타입은 타입에 아무런 제한을 두지 않겠다는 의미예요. 자바스크립트처럼 타입에 신경 쓰지 않고 코드를 작성할 수 있지만, 타입스크립트의 장점을 잃게 되므로 남용하는 것은 피하는 것이 좋아요. 외부 모듈을 사용하는데 타입을 정확히 알 수 없거나, 타입 지정이 애매한 제한적인 상황에서만 사용하는 것을 권장해요.

let anyEl: any;
anyEl = 5; 
anyEl = true; 
anyEl = 'any'; 

유니온 타입 (공용체)

유니온 타입은 두 개 이상의 타입을 허용하고 싶을 때 기호 | 를 사용하여 지정해요. 리터럴 타입이 허용되는 값의 범위를 지정했다면, 유니온 타입은 허용되는 타입의 범위를 지정해요.

참고로 좁은 범위의 타입 변수에는 더 넓은 범위(유니온 타입 등)의 값을 함부로 할당할 수 없어요.

let numStr: number | string;
numStr = 5; 
numStr = '5'; 
// numStr = true; // 에러: 숫자와 문자열만 사용 가능

타입 가드

타입 가드는 여러 타입이 올 수 있는 상황에서, 특정 타입일 때만 코드가 실행되도록 에러를 미리 예방하는 기법이에요. 런타임에 타입을 먼저 검사하고 안전하게 사용하는 방법이라고 볼 수 있어요.

  • typeof : 원시 값의 타입 확인
  • Array.isArray() : 배열 여부 확인
  • instanceof : 클래스(객체) 타입 확인
  • in : 객체 내부에 특정 속성이 존재하는지 확인

배열과 튜플 타입

배열 타입은 요소들의 타입을 지정할 때 사용해요. 튜플 타입은 일반 배열과 비슷하지만, 배열의 길이와 각 인덱스마다의 타입이 고정되어 있는 배열을 의미해요.

let numArr: number[] = [1, 2, 3, 4];
let strArr: string[] = ['a', 'b', 'c'];

// 배열에 유니온 타입 사용
let mixArr: (number | string)[] = [1, 'a', 2, 'b'];

// 읽기 전용 배열 (수정 불가)
let conArr: ReadonlyArray<number> = [1, 2, 3];
// conArr[0] = 4; // 에러 발생

// 튜플 타입
let tup: [number, string, boolean] = [1, 'a', true];

함수에서 매개변수를 정의할 때 선택적 매개변수( ? )를 사용한다면, 반드시 필수 매개변수들보다 뒤에 위치해야 해요. 또한 선택적 매개변수는 내부적으로 undefined 타입이 유니온으로 추가된다는 점을 유의해야 해요.

// 올바른 예시
function func(a: string, c: string, b?: number) {}

클래스 (Class)

타입스크립트에서 클래스를 만들 때는 필드의 타입을 명시하고, 접근 지정자( public , private , protected )를 사용할 수 있어요. 관례적으로 private 필드는 이름 앞에 _ (언더스코어)를 붙여서 구분하는 편이에요.

type Gender = "male" | "female";

class Human {
  private _name: string;
  private _age: number;
  private _gender: Gender | undefined;

  constructor(name: string, age: number, gender?: Gender) {
    this._name = name;
    this._age = age;
    this._gender = gender;
  }

  getName = (): void => {
    console.log(this._name);
  };
}

let james = new Human("james", 10, "male");
james.getName(); 

// james._age = 11; // 에러: private 필드는 외부에서 접근할 수 없어요.

생성자 함수 내부에서 필드를 선언하고 초기화하는 코드가 길어지는 것을 방지하기 위해, 매개변수에 접근 지정자를 직접 적어주어 코드를 간결하게 줄이는 문법도 제공해요.

class Human {
  // 매개변수에 접근 지정자를 붙이면 필드 선언과 초기화가 자동으로 수행돼요.
  constructor(
    private _name: string,
    private _age: number,
    private _gender?: Gender
  ) {}
}

let james = new Human("james", 10, "male");

private 접근 지정자로 캡슐화된 필드에 안전하게 접근하고 값을 수정하기 위해 getset 키워드를 사용할 수 있어요. 이를 사용하면 객체 외부에서 마치 일반 속성에 접근하듯이 . 표기법을 사용해 값을 읽고 쓸 수 있어요.

class Human {
  constructor(
    private _name: string,
    private _age: number,
    private _gender?: Gender
  ) {}

  getName = (): void => {
    console.log(this._name);
  };
  
  set name(name: string) {
    this._name = name;
  }

  get age(): number {
    return this._age;
  }

  set age(v: number) {
    this._age = v;
  }
}

let james = new Human("james", 10, "male");
james.getName();

// set 키워드로 만든 age에 값 할당
james.age = 11;

// get 키워드로 만든 age의 값 읽기
console.log(james.age); // 11
profile
할 땐 하고 놀 땐 노는 일일놀놀입니다.

0개의 댓글