타입스크립트 사용자 정의 타입 가드

서성원·2025년 2월 7일
5

타입스크립트

목록 보기
1/1
post-thumbnail

예제

type Dog = {
  name: string;
  isBark: boolean;
};

type Cat = {
  name: string;
  isScratch: boolean;
};

type Animal = Dog | Cat;

function warning(animal: Animal) {
  if ("isBark" in animal) {
    console.log(animal.isBark ? "짖습니다" : "안짖어요");
  } else if ("isScratch" in animal) {
    console.log(animal.isScratch ? "할큅니다" : "안할퀴어요");
  }
}

2개의 타입 Dog와 Cat의 유니온 타입인 Animal 타입까지 정의했습니다.

매개변수로 Animal 타입의 값을 받아 동물에 따라 각각 다른 경고를 콘솔에 출력하는 함수를 만들었습니다. 이때, Dog또는 Cat타입인지 알기 위해 in 연산자를 이용해 타입을 좁힙니다.

하지만 Dog타입이나 Cat타입의 프로퍼티가 중간에 수정되거나 추가 또는 삭제될 때 타입가드는 제대로 동작하지 않습니다.

커스텀 타입 가드

function isDog(animal: Animal): animal is Dog {
  return (animal as Dog).isBark !== undefined;
}

function isCat(animal: Animal): animal is Cat {
  return (animal as Cat).isScratch !== undefined;
}

function warning(animal: Animal) {
  if (isDog(animal)) {
    console.log(animal.isBark ? "짖습니다" : "안짖어요");
  } else {
    console.log(animal.isScratch ? "할큅니다" : "안할퀴어요");
  }

isDog함수의 매개변수로 받은 값이 Dog 타입이라면 true 아니라면 false를 반환합니다. 이때 반환값의 타입으로 animal is Dog 를 정의해 줍니다.

이렇게 하면 함수가 true를 반환하면 조건문 내부에서는 이 값이 Dog타입임을 보장한다는 의미가 됩니다.

타입 가드를 사용하는 경우

1. API 응답 데이터 검증

type User = {
  id: number;
  name: string;
  email: string;
};

function isUser(data: any): data is User {
  return (
    typeof data.id === 'number' &&
    typeof data.name === 'string' &&
    typeof data.email === 'string'
  );
}

여기서 isUser는 매개변수로 전달된 data가 User타입인지 검사합니다. 조건이 모두 참이어야 true를 반환하고, 아니면 false를 반환합니다.

반환 타입에서 data is User는 타입스크립트에게 이 값이 User타입이다라고 알리는 역할을 합니다.

const response = { id: 1, name: 'John Doe', email: 'john@example.com' };

if (isUser(response)) {
  console.log(response.name);
} else {
  console.error('Invalid user data'); // 타입이 User가 아님
}

조건문 안에서 typescript는 response를 자동으로 User타입으로 간주합니다. 타입 가드가 없을 때보다 코드의 안전성이랑 가독성이 올라갑니다.

2. 선택적 프로퍼티를 가진 객체 판별

type Admin = {
  id: number;
  role: 'admin';
  permissions?: string[];
};

function isAdmin(data: any): data is Admin {
  return (
    typeof data.id === 'number' &&
    data.role === 'admin' &&
    (data.permissions === undefined || Array.isArray(data.permissions))
  );
}

const person = { id: 1, role: 'admin', permissions: ['read', 'write'] };

if (isAdmin(person)) {
  console.log(person.permissions); 
}

isAdmin함수에서 permissions는 선택적 속성이므로 두 가지를 검사해야 합니다.

  1. permissions가 undefined인 경우
  2. permission가 존재한다면 배열이어야 함

자바스크립트에서 배열은 객체로 취급되기 때문에 typeof로 배열을 정확히 판별할 수 없습니다. Array.isArray()는 값이 배열인지 정확하게 검사합니다.

3. 폼 데이터 검증

1️⃣ 동적 데이터 타입

타입 스크립트는 정적 타입검사(컴파일 타임)를 통해 오류를 방지하려고 하지만, 동적 데이터에서는 타입 보장이 어렵습니다.

function processFormData(data: FormData) {
  console.log(data.username.toUpperCase());
}

const formData = { username: 'JohnDoe', age: '30' }; // 잘못된 타입 (age가 문자열)

processFormData(formData);  // 컴파일 시 오류 없음 -> 런타임에 문제 발생 가능

2️⃣ 명시적으로 타입을 검사

타입스크립트는 타입을 명시적으로 검사하는 코드가 없으면 자동으로 타입을 추론할 수 없습니다.

const formData = { username: 'JohnDoe', age: '30' };

if (typeof formData.age === 'number') {
  console.log(formData.age.toFixed(2));  // 타입이 맞는 경우에만 안전하게 동작
} else {
  console.log('Invalid data');
}

3️⃣ 불필요하게 타입 검사 반복

타입 가드를 사용하지 않으면 타입 검사를 반복적으로 수행해야 합니다.

const formData = { username: 'JohnDoe', age: '30' };

// 여러 곳에서 타입을 수동으로 검사
if (typeof formData.username === 'string' && typeof formData.age === 'number') {
  console.log(formData.username.toUpperCase());
}

if (typeof formData.age === 'number') {
  console.log(formData.age.toFixed(2));
}

타입 가드 함수로 동적 데이터 검증

타입 가드를 사용하면 한 번의 타입 검사를 통해 타입을 안전하게 사용할 수 있습니다. 또한, 여러 곳에서 타입 검사를 하지 않고 타입 가드 함수를 재사용할 수 있습니다.

type FormData = {
  username: string;
  age: number;
};

function isValidFormData(data: any): data is FormData {
  return typeof data.username === 'string' && typeof data.age === 'number';
}

const formData = { username: 'JohnDoe', age: 30 }; 

if (isValidFormData(formData)) {
  console.log('Valid form data:', formData);
} else {
  console.error('Invalid form data');
}

참고

한 입 크기로 잘라먹는 타입스크립트

profile
FrontEnd Developer

0개의 댓글

관련 채용 정보