[TIL] TypeScript

최하온·2024년 3월 4일
0

TIL

목록 보기
43/71
post-thumbnail

User라는 추상 클래스를 정의해볼게요. User 클래스는 name, age라는 인자를 받고 getRole이라는 추상 함수를 포함합니다!
❎도전

abstract class User {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  abstract getRole(): string;
}

✅정답

abstract class User {
  constructor(public name: string, public age: number) {}
  abstract getRole(): Role;
  }

💡고찰

  • getRole의 반환값을 string로 지정. 정확도가 떨어지고, 예상치 못한 오류 발생 가능성이 높음! 따로 validation을 해야할 거 같음.
  • 선언 후 초기화가 따로 진행됨. 기능은 같으나 가독성이 떨어짐

Member라는 클래스를 정의해보겠습니다. Member는 User를 상속받아요!
❎도전

class Member extends User {
  constructor(public name: string, public age: number) {
    super(name, age);
  }
  getRole(): Role {
    return Role.MEMBER;
  }
}

✅정답

class Member extends User {
  constructor(name: string, age: number) {
    super(name, age);
  }
  getRole(): Role {
    return Role.MEMBER;
  }
}

💡고찰

  • public 같은 접근 제어자는 상위 클래스에서만 정의하면 됨!

Book이라는 클래스를 정의해보겠습니다. 도서관에는 당연히 책이 있어야겠죠?
책은 이름, 저자, 출판일로 구성이 됩니다
❎도전

class Book {
  constructor(name: string, author: string, publicationDate: number) {}
}

✅정답

class Book {
  constructor(
    public title: string,
    public author: string,
    public publishedDate: Date
  ) {}
}

💡고찰

  • 출판일은 number X! Date O!
  • {}가 비어있으므로 매개변수로 받은 값들이 각각 title, author, publishedDate 속성에 자동으로 할당 !

RentManager라는 인터페이스를 정의해볼게요. 이 친구는 도서관이 꼭 갖추어야 할 기능을 정의한 명세서입니다.

❎도전

interface RentManager {
  add(): void;
  delete(): void;
  borrow(): void;
  return(): void;
}

✅정답

interface RentManager {
  getBooks(): Book[];
  addBook(user: User, book: Book): void;
  removeBook(user: User, book: Book): void;
  rentBook(user: Member, book: Book): void;
  returnBook(user: Member, book: Book): void;
}

💡고찰

  • 타입 지정을 해주어야 함.
  • 책 조회라는 메서드를 생각 못함.

RentManager를 구현하는 Library 클래스를 만들어보겠습니다
getBooks 함수는 books를 깊은 복사해서 던져주세요.
외부에서 books를 수정하는 것을 방지하기 위함이에요.
❎도전

class Library implements RentManager {

    private books: Book[] = []
    getBooks(): Book[] {
        return [];
    }
}

✅정답

class Library implements RentManager {
  private books: Book[] = [];
  // rentedBooks는 유저의 대여 이력을 관리해요!
  private rentedBooks: Map<string, Book> = new Map<string, Book>();

  getBooks(): Book[] {
    // 깊은 복사를 하여 외부에서 books를 수정하는 것을 방지합니다.
    return JSON.parse(JSON.stringify(this.books));
  }

💡고찰

  • string을 키로, Book를 값으로 가짐.
  • json 문자열로 변환 뒤 JS 객체로 변환.
  • 이게 왜 깊은 복사?? => 원본 객체와 복사된 객체에서 동일한 객체 참조를 유지=> 메모리 주소는 다르나 같은 데이터를 가짐.

❎도전
addBook, removeBook는 사서만 호출할 수 있게 해주세요.

    removeBook(user: User, book: Book): void {
        if (user.getRole() !== Role.LIBRARIAN) {
            console.log('올바르지 않은 요청입니다.');
            return;
        } 
    }

✅정답

  removeBook(user: User, book: Book): void {
    if (user.getRole() !== Role.LIBRARIAN) {
      console.log("사서만 도서를 삭제할 수 있습니다.");
      return;
    }

    const index = this.books.indexOf(book);
    if (index !== -1) {
      this.books.splice(index, 1);
    }
  }

💡고찰

  • 인텍스를 찾은 뒤, 책이 존재한다면 그 인덱스만 잘라서 삭제하는 로직

rentBook는 유저만 호출 할 수 있게 해주세요.
rentBook에서는 다른 책을 대여한 유저는 책을 대여할 수 없어야 해요.
❎도전

    rentBook(user: User, book: Book): void {
        if (user.getRole() !== Role.MEMBER) {
            console.log('올바르지 않은 요청입니다.');
            return;
        }
    }

✅정답

  rentBook(user: User, book: Book): void {
    if (user.getRole() !== Role.MEMBER) {
      console.log('유저만 도서를 대여할 수 있습니다.');
      return;
    }

    if (this.rentedBooks.has(user.name)) {
      console.log(`${user.name}님은 이미 다른 책을 대여중이라 빌릴 수 없습니다.`);
    } else {
      this.rentedBooks.set(user.name, book);
      console.log(`${user.name}님이 [${book.title}] 책을 빌렸습니다.`);
    }
  }

💡고찰

  • has를 사용해서 이름을 기준으로 대출 여부 확인.
  • set를 사용하여 name을 키로, book을 값으로 지정하여 map에 넣어줌.

returnBook에서는 책을 빌린 사람들만 반납할 수 있게 해주세요.
❎도전

  returnBook(user: User, book: Book): void {
    if (user.getRole() !== Role.MEMBER) {
      console.log('올바르지 않은 요청입니다.');
      return;
    }
  }

✅정답

  returnBook(user: User, book: Book): void {
    if (user.getRole() !== Role.MEMBER) {
      console.log('유저만 도서를 반납할 수 있습니다.');
      return;
    }

    if (this.rentedBooks.get(user.name) === book) {
      this.rentedBooks.delete(user.name);
      console.log(`${user.name}님이 [${book.title}] 책을 반납했어요!`);
    } else {
      console.log(`${user.name}님은 [${book.title}] 책을 빌린적이 없어요!`);
    }
  }
}

💡고찰

  • get으로 조회 후 이름으로 빌린 책이 동일한지 확인 후 삭제.

0개의 댓글