타입스크립트 기초 문법 (3)

치이와와·2024년 9월 25일

Web / FrontEnd

목록 보기
4/6

1. 클래스

  • 클래스 선언하기
    • class 키워드를 이용해 선언
    • 필드 선언
    • 생성자 선언
    • 메서드 선언
    • new 클래스명 형태로 호출
 class Student {
  // 필드
  name;
  grade;
  age;

  // 생성자
  constructor(name, grade, age) {
    this.name = name;
    this.grade = grade;
    this.age = age;
  }

  // 메서드
  study() {
    console.log("열심히 공부 함");
  }

  introduce() {
    console.log(`안녕하세요!`);
  }
}

let studentB = new Student("홍길동", "A+", 27);

studentB.study(); // 열심히 공부 함
studentB.introduce(); // 안녕하세요!
  • 타입스크립트의 클래스

    • 클래스의 필드를 선언할 때는 타입을 함께 정의
    • 클래스를 타입으로 사용할 수 있음
    • 파생 클래스에서 생성자를 정의했다면 반드시 super 메서드를 생성자 최상단에 호출해야 함
  • 접근 제어자

  1. public
    : 어디서든 해당 프로퍼티에 접근 가능, 기본값
  2. private
    : 클래스 내부에서만 접근 가능
  3. protected
    : 클래스 외부에서 접근 불가능하나 파생 클래스에서는 접근 가능
  • 필드 생략하기

    • 접근 제어자는 생성자의 매개변수에도 설정 가능
    • 접근 제어자가 설정되면 자동으로 필드도 함께 선언되므로 필드 생략
    • this.필드 = 매개변수가 자동으로 수행되므로 생성자 내부 코드도 생략 가능
    class Employee {
      // 생성자
      constructor(
        private name: string,
        protected age: number,
        public position: string
    ) {}
    
    // 메서드
    work() {
      console.log(`${this.name} 일함`);
    	}
    }
  • 인터페이스와 클래스
    : 인터페이스를 이용해 클래스에 필요한 필드와 메서드 정의

/**
 * 인터페이스와 클래스
 */

interface CharacterInterface {
  name: string;
  moveSpeed: number;
  move(): void;
}

class Character implements CharacterInterface {
  constructor(
    public name: string,
    public moveSpeed: number,
    private extra: string
  ) {}

  move(): void {
    console.log(`${this.moveSpeed} 속도로 이동!`);
  }
}

2. 제네릭

제네릭 : 함수나 인터페이스, 타입 별칭, 클래스 등을 다양한 타입과 함께 동작하도록 만들어주는 기능

  • 제네릭 함수
function func<T>(value: T): T {
  return value;
}

T에 어떤 타입이 할당될 지는 함수가 호출될 때 결정됨

  • 타입 변수 응용 사례
  1. 타입 변수가 여러 개 필요한 경우
    -> 타입 변수 여러 개 사용
  2. 다양한 배열 타입을 인수로 받는 함수가 필요한 경우
    -> 배열의 타입을 타입 변수로 설정
  3. 반환 값 타입을 배열의 특정 요소 타입이 되도록 할 때
    -> 튜플과 rest 파라미터 이용
  4. 타입 변수를 제한하고 싶을 때
    -> 타입 변수를 특정 프로퍼티를 갖는 객체 타입으로 제한
    function getLength<T extends { length: number }>(data: T) {
    	return data.length;
    }
  • 제네릭 인터페이스
interface KeyPair<K, V> {
  key: K;
  value: V;
}

let keyPair: KeyPair<string, number> = {
  key: "key",
  value: 0,
};

let keyPair2: KeyPair<boolean, string[]> = {
  key: true,
  value: ["1"],
};
  • 인덱스 시그니처와 함께 사용
interface Map<V> {
  [key: string]: V;
}

let stringMap: Map<string> = {
  key: "value",
};

let booleanMap: Map<boolean> = {
  key: true,
};
  • 제네릭 타입 별칭
type Map2<V> = {
  [key: string]: V;
};

let stringMap2: Map2<string> = {
  key: "string",
};
  • 제네릭 클래스
    : 클래스 이름 뒤에 타입 변수 선언으로 제네릭 클래스 생성
class List<T> {
  constructor(private list: T[]) {}

  push(data: T) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

3. 타입 조작하기

타입 조작 : 원래 존재하던 타입을 유동적으로 다른 타입으로 변환하는 기능

  1. 인덱스드 액세스 타입
    : 인덱스를이용해 다른 타입 내의 특정 프로퍼티의 타입을 추출하는 타입
interface Post {
  title: string;
  content: string;
  author: {
    id: number;
    name: string;
    age: number; // 추가
  };
}


function printAuthorInfo(author: Post["author"]) {
  console.log(`${author.id} - ${author.name}`);
}
  • Post["author"]는 Post 타입으로부터 author 프로퍼티의 타입을 추출한다.
  • 대괄호 속에 들어가는 스트링 리터럴을 인덱스라고 부르며 인덱스에는 값이 아니라 타입만 들어갈 수 있다.
  1. Keyof 연산자
interface Person {
  name: string;
  age: number;
  location: string; // 추가
}

function getPropertyKey(person: Person, key: keyof Person) {
  return person[key];
}

const person: Person = {
  name: "이정환",
  age: 27,
};
  • keyof 타입 형태로 사용
  • 타입의 모든 프로퍼티 키를 string literal union 타입으로 추출함
  • 오직 타입에만 적용할 수 있는 연산자
  • typeof와 함께 사용하면 특정 변수의 타입을 추론할 수도 있음
(...)

function getPropertyKey(person: Person, key: keyof typeof person) {
  return person[key];
}

const person: Person = {
  name: "이정환",
  age: 27,
};
  1. 맵드 타입
    : 기존의 객체 타입을 기반으로 새로운 객체 타입을 만드는 타입 조작 기능
interface User {
  id: number;
  name: string;
  age: number;
}

type PartialUser = {
  [key in "id" | "name" | "age"]?: User[key];
};
  • PartialUser 타입은 3개의 프로퍼티를 갖는 객체 타입으로 정의됨

    • id : User[id] -> id : number
    • name : User[user] -> name : string
    • age : User[age] -> age : number
  • keyof 연산자를 이용해 코드를 줄일 수 있음

interface User {
  id: number;
  name: string;
  age: number;
}

type PartialUser = {
  [key in keyof User]?: User[key];
};
  1. 템플릿 리터럴 타입
    : 템플릿 리터럴을 이용해 특정 패턴을 갖는 String 타입을 만드는 기능
type Color = "red" | "black" | "green";
type Animal = "dog" | "cat" | "chicken";

type ColoredAnimal = `${Color}-${Animal}`;

0개의 댓글