개발 일기

20250904 TypeScript 본문

TIL

20250904 TypeScript

종현종현 2025. 9. 4. 20:52

타입스크립트의 Class

접근 제어자

타입스크립트는 클래스 멤버의 접근 수준을 제어할 수 있는 접근 제어자를 제공한다.

 

- public : (기본값) 어디에서나 클래스 멤버에 접근할 수 있다.

- private : 클래스 내부에서만 클래스 멤버에 대한 접근을 허용한다.

- protected : 클래스와 상속받은 클래스에서만 접근 가능하다. (Java에서 더 자세히 다룰 예정)

 

class Person {
  private name: string;

  public constructor(name: string) {
    this.name = name;
  }

  public getName(): string {
    return this.name;
  }
}

const person = new Person("Jane");
console.log(person.getName()); // Jane 출력
console.log(person.name); // 오류: name은 private 멤버이므로 클래스 외부에서 접근 불가

 

readonly

class Person {
  private readonly name: string;

  public constructor(name: string) {
    this.name = name;
  }

  setName(newName: string) {
    // this.name = newName; // 오류 발생
  }
}

 

생성자에서 초기화할 때만 값을 할당 가능하고 그 이후에는 클래스 내부든 외부든 수정할 수 없게 된다.

 

implements 상속 구현

interface Shape {
  getArea: () => number;
}

class Rectangle implements Shape {
  public constructor(protected readonly width: number, protected readonly height: number) {}

  public getArea(): number {
    return this.width * this.height;
  }
}

 

interface는 implements 키워드를 통해 클래스가 따라야 하는 유형을 정의하는 데 사용할 수 있다.

 

extends 상속 구현

interface Shape {
  getArea: () => number;
}

class Rectangle implements Shape {
  public constructor(protected readonly width: number, protected readonly height: number) {}

  public getArea(): number {
    return this.width * this.height;
  }
}

class Square extends Rectangle {
  public constructor(width: number) {
    super(width, width); // 부모 생성자를 호출. 양 변이 같음으로 width, width
  }

  // getArea gets inherited from Rectangle
}

 

Square는 Rectangle에서 정의된 getArea() 메서드를 그대로 상속받아 사용할 수 있다. super()는 부모 클래스의 생성자나 메서드를 호출할 때 사용된다.

 

override 키워드

interface Shape {
  getArea: () => number;
}

class Rectangle implements Shape {
  public constructor(protected readonly width: number, protected readonly height: number) {}

  public getArea(): number {
    return this.width * this.height;
  }
}

class Square extends Rectangle {
  public constructor(width: number) {
    super(width, width);
  }

  public getAre(): string {
  	console.log(`넓이는 ${this.width * this.width}입니다.`); 
  }

const squ = new Square(5);
squ.getArea(); // Rectangle 클래스의 getArea()가 호출됨.

 

override는 위처럼 원치않는 메서드의 호출이 되는 상황을 방지하는 데 사용된다.

 

 

사용 예시

interface Shape {
  getArea: () => number;
}

class Rectangle implements Shape {
  public constructor(protected readonly width: number, protected readonly height: number) {}

  public getArea(): number {
    return this.width * this.height;
  }
}

class Square extends Rectangle {
  public constructor(width: number) {
    super(width, width);
  }

  public override getArea(): string {
  	return `넓이는 ${this.width * this.width} 입니다.`;
  }
}

 

abstract 키워드

abstract는 모든 멤버를 구현하지 않고도 다른 클래스의 기반 클래스로 사용될 수 있도록 작성할 수 있게 해준다.

abstract class Polygon {
  public abstract getArea(): number;

  public toString(): string {
    return `Polygon[area=${this.getArea()}]`;
  }
}

class Rectangle extends Polygon {
  public constructor(protected readonly width: number, protected readonly height: number) {
    super();
  }

  public getArea(): number {
    return this.width * this.height;
  }
}

 

멤버가 abstract이면 클래스에도 붙여주어야 된다. 미완성된 메서드는 상속받아 호출해도 실행되지 않고 구체화해주어야 실행된다.

 

 타입스크립트 제네릭

제네릭은 타입 변수를 사용하여 클래스, 함수, 타입 별칭 등을 정의할 수 있게 해준다. 이를 통해 타입을 명시적으로 지정하지 않고도 다양한 타입에 대해 안전하게 동작하는 코드를 작성할 수 있다.

 

함수에서 제네릭 사용

function createPair<S, T>(v1: S, v2: T): [S, T] {
  return [v1, v2];
}

 

S와 T는 타입 변수로 함수 호출 시 실제 타입으로 대체된다.

 

사용 예시

console.log(createPair<string, number>('hello', 42)); // ['hello', 42]

 

메서드명 뒤에 < > 사이에 타입을 명시해서 사용한다.

 

클래스에서 제네릭 사용

class NamedValue<T> {
  private _value: T | undefined;

  constructor(private name: string) {}

  public setValue(value: T) {
    this._value = value;
  }

  public getValue(): T | undefined {
    return this._value;
  }

  public toString(): string {
    return `${this.name}: ${this._value}`;
  }
}

let value = new NamedValue<number>('myNumber');
value.setValue(10);
console.log(value.toString()); // myNumber: 10

 

함수에서 사용했던 것처럼 동일하게 사용된다. 만약 class NameValue<T = string> {} 으로 작성하게 되면 인스턴스 생성 시 타입을 명시하지 않으면 기본값으로 string이 사용된다.

 

Type Aliases

type Wrapped<T> = { value: T };

const wrappedValue: Wrapped<number> = { value: 10 };

 

type 키워드의 제네릭을 사용하면 재사용성이 더 높은 유형을 만들 수 있다.

 

타입스크립트 Utility 타입

1. Partial

객체 타입의 모든 속성을 선택적으로 만든다.

interface Point { x: number; y: number; }
let pointPart: Partial<Point> = {}; // x와 y는 선택적
pointPart.x = 10;

 

2. Required

객체 타입의 모든 속성을 필수로 만든다.

interface Car {
  make: string;
  model: string;
  mileage?: number;
}

let myCar: Required<Car> = {
  make: 'Ford',
  model: 'Focus',
  mileage: 12000 // 마일리지도 무조건 선언해야된다.
};

 

3. Record

특정 키 타입과 값 타입을 갖는 객체 타입을 정의한다.

const nameAgeMap: Record<string, number> = {
  'Alice': 21,
  'Bob': 25
};

 

4. Omit

객체 타입에서 특정 키를 제외한 타입을 생성한다.

interface Person {
  name: string;
  age: number;
  location?: string;
}

const bob: Omit<Person, 'age' | 'location'> = {
  name: 'Bob'
};

 

5. Pick

객체 타입에서 특정 키만 선택한 타입을 생성한다.

interface Person {
  name: string;
  age: number;
  location?: string;
}

const bob: Pick<Person, 'name'> = {
  name: 'Bob'
  // name키만 선택했기 때문에 age와 location은 제외
};

 

6. Exclude

유니온 타입에서 명시한 타입을 제외한 타입을 생성한다.

type Primitive = string | number | boolean
const value: Exclude<Primitive, string> = true; // string을 제외한 boolean, number만 가능

 

7. ReturnType

함수 유형의 반환 유형을 추출한다.

type PointGenerator = () => { x: number; y: number; };
const point: ReturnType<PointGenerator> = {
  x: 10,
  y: 20
};

 

8. Parameters

함수 유형의 매개변수 유형을 배열로 추출한다.

type PointPrinter = (p: { x: number; y: number; }) => void;
const point: Parameters<PointPrinter>[0] = {
  x: 10,
  y: 20
};

 

타입스크립트 keyof

keyof란?

keyof는 객체 타입에서 키 이름 들만 골라내어 문자열 또는 숫자 리터럴 Union 타입으로 만들어주는 타입 연산자이다.

 

사용 예제

interface Person {
  name: string;
  age: number;
}
// `keyof Person`는 name과 age 유니온 타입을 만들고 다른 문자열은 들어올 수 없다.
function printPersonProperty(person: Person, property: keyof Person) {
  console.log(`Printing person property ${property}: "${person[property]}"`);
}
let person = {
  name: "Max",
  age: 27
};
printPersonProperty(person, "name");

 

객체 타입에 인덱스 시그니처에도 사용 가능하다.

 

객체 타입에 인덱스 시그니처가 있을 경우 keyof는 해당 키 타입 전체를 반환한다.

type StringMap = { [key: string]: unknown };
type K = keyof StringMap; // type K = string

 

 

 

'TIL' 카테고리의 다른 글

20250908 OOP 3대 concept  (1) 2025.09.08
20250907 자바스크립트 V8 엔진  (0) 2025.09.07
20250903 TypeScript  (0) 2025.09.04
20250902 JavaScript 비동기  (0) 2025.09.02
20250901 JavaScript 화살표 함수와 this  (0) 2025.09.01
Comments