40. 타입스크립트 개념 정리 2

yeah·2023년 7월 26일
0

Today I Learned

목록 보기
27/70
post-thumbnail
post-custom-banner

Mission: 타입 스크립트 개념 정리

타입에 대한 이해와 활용의 중요성

타입의 역할

  • 프로그래밍 언어에서 변수는 데이터를 저장하는 공간이며, 변수에 저장되는 데이터는 여러 가지 타입이 있다. 이를 이해하고 올바르게 사용하면 코드의 가독성과 안정성이 향상된다.
  • 타입 안정성은 코드가 예상한 타입대로 동작함을 보장하는 것으로, 타입 안정성이 높을수록 코드의 품질이 좋아지고 실행 시간에 발생할 수 있는 오류를 줄일 수 있다.

    타입 오류와 예방
  • 잘못된 타입을 사용하거나 예상치 못한 타입이 사용될 경우에는 오류가 발생할 수 있다. 이러한 오류는 컴파일 타임에 발생하지 않고 실행 시간에 발생하기 때문에 타입에 대한 제대로 된 이해가 중요하다.

    협업의 효율성
  • 타입을 명확하게 명시하고 사용하면 코드의 가독성이 높아지며 다른 개발자들이 이해하기 쉬워지고 유지보수가 용이해진다. 원활한 협업을 위해 타입을 명확하게 활용하는 것이 중요하다.

    타입의 종류와 사용 사례
  1. boolean: 참(true) 또는 거짓(false) 값을 나타낸다. 조건문, 비교 연산 등에서 주로 사용된다.
  2. number: 모든 숫자를 나타낸다. 정수, 실수, 2진수, 8진수, 16진수 등을 표현할 수 있다.
  3. string: 텍스트 데이터를 나타낸다. 작은 따옴표, 큰 따옴표, 백쿼트를 사용하여 문자열을 표현할 수 있다.
  4. 배열: 기본 타입에 []가 붙은 형태로, 여러 개의 값을 저장하는 데 사용된다.
  5. 튜플(tuple): 서로 다른 타입의 원소를 순서에 맞게 가질 수 있는 특수한 형태의 배열이다.
  6. enum: 관련된 상수 값을 그룹화하고자 할 때 사용한다.

    const, readonly
  • const: 변수가 아닌 상수를 선언한다. 값 변경이 불가능하다.
  • readonly: 객체의 속성을 불변으로 만든다.

    any, unknown, union
  • any: 모든 타입의 슈퍼 타입으로, 타입 안정성을 저해할 수 있으므로 가급적 사용을 지양한다.
  • unknown: any와 비슷하지만, 타입 확인을 통해 안전하게 할당할 수 있다.
  • union: 여러 타입 중 하나를 가질 수 있는 변수를 선언할 때 사용한다.

    타입 안정성과 유지 보수성
  • TypeScript를 사용하면 타입 안정성을 확보하고, 코드의 유지 보수성을 개선할 수 있다. 이런 사소한 습관들이 코드의 안정성과 유지 보수성을 향상시킬 수 있다.

enum과 object literal 비교

enum

  • 간단한 상수 값의 경우에 적합하다.
  • 상수를 그룹화하여 가독성과 명확한 상수 값을 정의할 수 있다.
  • 컴파일 시에 자동으로 숫자 값으로 매핑되므로 값 할당에 신경 쓸 필요가 없다.
  • 단, 특정 숫자 값으로 매핑되어야 한다면 직접 할당할 수 있다.
enum UserRole {
  ADMIN = "ADMIN",
  EDITOR = "EDITOR",
  USER = "USER",
}

object literal

  • 복잡한 구조와 다양한 데이터 타입이 필요한 경우에 적합하다.
  • 키와 값의 쌍으로 구성된 객체를 정의하는 방식이며, 어떤 타입의 값이든 대입할 수 있다.
  • 미리 값이 할당되어야 하므로 런타임 에러 방지에 도움이 된다.
const obj = {
  a: [1, 2, 3],
  b: 'b',
  c: 4
};

언제 사용할까?

  • enum은 간단한 상수 값을 그룹화할 때 유용하며, 각 멤버의 값이 변하지 않아야 한다.
  • object literal은 복잡한 구조와 다양한 데이터 타입이 필요한 경우에 유연하게 사용할 수 있다.

유틸리티 타입

Partial

  • Partial<T> 타입은 타입 T의 모든 속성을 선택적으로 만들어준다.
  • 일부 속성만 제공하는 객체를 쉽게 생성할 수 있다.
interface Person {
  name: string;
  age: number;
}
const updatePerson = (person: Person, fields: Partial<Person>): Person => {
  return { ...person, ...fields };
};

Required

  • Required 타입은 타입 T의 모든 속성을 필수적으로 만들어준다.
  • 모든 속성이 반드시 전부 제공되는 객체를 생성할 때 사용한다.
  interface Person {
  name: string;
  age: number;
  address?: string;
}
type RequiredPerson = Required<Person>;

Readonly

  • Readonly 타입은 타입 T의 모든 속성을 읽기 전용으로 만들어준다.
  • 불변 객체로 취급하고자 할 때 유용하다.
interface DatabaseConfig {
  host: string;
  readonly port: number;
}
const mutableConfig: DatabaseConfig = {
  host: "localhost",
  port: 3306,
};
const immutableConfig: Readonly<DatabaseConfig> = {
  host: "localhost",
  port: 3306,
};

Pick<T, K>

  • Pick<T, K> 타입은 타입 T에서 K 속성들만 선택하여 새로운 타입을 만든다.
  • 일부 속성만 포함하는 객체를 쉽게 생성할 수 있다.
  interface Person {
  name: string;
  age: number;
  address: string;
}
type SubsetPerson = Pick<Person, "name" | "age">;

Omit<T, K>

  • Omit<T, K> 타입은 타입 T에서 K 속성들을 제외한 새로운 타입을 만든다.
  • 특정 속성을 제거한 새로운 타입을 생성할 때 사용한다.
interface Person {
  name: string;
  age: number;
  address: string;
}
type SubsetPerson = Omit<Person, "address">;

두 번째 TypeScript 프로그램 실습

프로그램 기능

  • 음료 등록 기능 - 어드민
  • 음료 삭제 기능 - 어드민
  • 음료 조회 기능 - 어드민, 고객
  • 음료 주문 기능 - 고객
  • 음료 준비 완료 기능 - 어드민
  • 음료 수령 기능 - 고객
// 인터페이스 & 데이터 정의하기
interface User {
  id: number;
  name: string;
  role: 'admin' | 'customer';
}
interface Beverage {
  name: string;
  price: number;
}
interface Order {
  orderId: number;
  customerId: number;
  customerName: string;
  beverageName: string;
  status: "placed" | "completed" | "picked-up";
}
let beverages: Beverage[] = [];
let orders: Order[] = [];
// 함수 구현하기
function isAdmin(user: User): boolean {
  return user.role === "admin";
}
function isCustomer(user: User): boolean {
  return user.role === "customer";
}
function addBeverage(user: User, name: string, price: number): void {
  if (!isAdmin(user)) {
    console.log("권한이 없습니다.");
    return;
  }
  const newBeverage: Beverage = { name, price };
  beverages.push(newBeverage);
}
function removeBeverage(user: User, beverageName: string): void {
  if (!isAdmin(user)) {
    console.log("권한이 없습니다.");
    return;
  }
  beverages = beverages.filter((beverage) => beverage.name !== beverageName);
}
function getBeverages(user: User): Beverage[] {
  if (!user) {
    return [];
  }
  return beverages;
}
function findBeverage(beverageName: string): Beverage | undefined {
  return beverages.find((beverage) => beverage.name === beverageName);
}
function placeOrder(user: User, beverageName: string): number {
  if (!isCustomer(user)) {
    console.log("권한이 없습니다.");
    return -1;
  }
  const beverage = findBeverage(beverageName);
  if (!beverage) {
    console.log("해당 음료를 찾을 수 없습니다.");
    return -1;
  }
  const newOrder: Order = {
    orderId: orders.length + 1,
    customerId: user.id,
    customerName: user.name,
    beverageName,
    status: "placed",
  };
  orders.push(newOrder);
  return newOrder.orderId;
}
function completeOrder(user: User, orderId: number): void {
  if (!isAdmin(user)) {
    console.log("권한이 없습니다.");
    return;
  }
  const order = orders.find((order) => order.orderId === orderId);
  if (order) {
    order.status = "completed";
    console.log(
      `[고객 메시지] ${order.customerName}님~ 주문하신 ${order.beverageName} 1잔 나왔습니다~`
    );
  }
}
function pickupOrder(user: User, orderId: number): void {
  if (!isCustomer(user)) {
    console.log("권한이 없습니다.");
    return;
  }
  const order = orders.find((order) => order.orderId === orderId);
  if (order && order.status === "completed") {
    order.status = "picked-up";
    console.log(
      `[고객 메시지] ${order.customerName}님~ 주문하신 ${order.beverageName} 수령하셨습니다~`
    );
  } else {
    console.log("주문이 아직 준비되지 않았습니다.");
  }
}
const adminUser: User = { id: 1, name: "Admin", role: "admin" };
const customerUser: User = { id: 2, name: "Customer", role: "customer" };
// 어드민이 음료 추가하기
addBeverage(adminUser, "아메리카노", 3000);
addBeverage(adminUser, "카페라떼", 3500);
// 어드민이 음료 삭제하기
removeBeverage(adminUser, "아메리카노");
// 음료 조회하기
const beveragesList = getBeverages(adminUser);
console.log(beveragesList);
// 고객이 음료 주문하기
const orderId = placeOrder(customerUser, "카페라떼");
console.log(`고객 주문 ID: ${orderId}`);
// 어드민이 주문 준비 완료하기
completeOrder(adminUser, orderId);
// 고객이 음료 수령하기
pickupOrder(customerUser, orderId);
profile
기록과 회고
post-custom-banner

0개의 댓글