TS LAB
TS 3.5 · 3부. 인터페이스와 제네릭

클래스와 접근 제한자

public · private · readonly 로 드러낼 것을 정합니다.

예상 학습 시간 16분 실행 단추가 있는 예제는 고쳐서 실행해 볼 수 있습니다 난이도 중급
개념 설명

클래스에도 타입을 적습니다

클래스는 JavaScript 문법입니다(JS 6.1). TypeScript 는 여기에 필드의 타입과 드러낼 것과 감출 것을 적게 합니다.

main.ts
class Product {
	name: string;
	price: number;

	constructor(name: string, price: number) {
		this.name = name;
		this.price = price;
	}

	label(): string {
		return `${this.name} ${this.price}원`;
	}
}

const p = new Product("연필", 1000);
console.log(p.label());
출력
연필 1000원

필드를 위에 미리 적어 두어야 합니다. JavaScript 에서는 this.name = name 만으로 만들어졌지만, TypeScript 는 어떤 필드가 있는지 알아야 하기 때문입니다.

상세 사용법

같은 것을 세 번 적지 않기

위 코드에서 name 이 세 번 나옵니다 — 필드 선언, 매개 변수, 대입. 생성자 매개 변수 앞에 접근 제한자를 붙이면 한 번으로 끝납니다.

main.ts
class Product {
	constructor(
		public name: string,
		private price: number,
		readonly code: string
	) {}

	label(): string {
		return `${this.name} ${this.price}원 (${this.code})`;
	}
}

const p = new Product("연필", 1000, "A-1");
console.log(p.label());
console.log(p.name);
출력
연필 1000원 (A-1) 연필

이것은 TypeScript 에만 있는 문법입니다. 바뀐 JavaScript 를 보면 this.name = name 이 들어가 있습니다 — 적어 주지 않은 것을 대신 만들어 준 것입니다.

상세 사용법

드러낼 것과 감출 것

제한자어디서 사용할 수 있나
public어디서나. 적지 않으면 이것입니다
private그 클래스 안에서만
protected그 클래스와 물려받은 클래스에서
readonly읽기만 됩니다. 위의 것들과 함께 붙일 수 있습니다
main.ts
class Product {
	constructor(public name: string, private price: number) {}
}

const p = new Product("연필", 1000);

console.log(p.price);
출력
7:15 TS2341 'price' 속성은 private이며 'Product' 클래스 내에서만 액세스할 수 있습니다.

이것은 검사할 때만 막습니다. 바뀐 JavaScript 에는 this.price 가 그냥 들어 있어 실행 중에는 읽을 수 있습니다. 실행할 때도 막으려면 JavaScript 의 # 를 사용합니다(JS 6.1).

상세 사용법

인터페이스를 지키게 하기

implements 로 이 인터페이스를 갖추었다고 적어 두면, 빠뜨린 것을 클래스 쪽에서 잡아 줍니다.

main.ts
interface Printable {
	label(): string;
}

class Product implements Printable {
	constructor(public name: string) {}
}

const p = new Product("연필");
출력
5:7 TS2420 'Product' 클래스가 'Printable' 인터페이스를 잘못 구현합니다. 'label' 속성이 'Product' 형식에 없지만 'Printable' 형식에서 필수입니다.

extends 는 물려받는 것이고 implements 는 갖추었는지 확인만 하는 것입니다. 물려받을 것이 없으므로 내용은 직접 적어야 합니다.

흔한 실수

처음에 자주 걸리는 것

필드를 적지 않고 this 에 담는 것

생성자에서 this.total = 0 만 적으면 그런 속성이 없다고 막습니다. 위에 total: number; 를 적거나 매개 변수에 제한자를 붙입니다.

private 을 보안으로 여기는 것

검사할 때만 막습니다. 실행 중에는 그냥 속성이라 읽고 쓸 수 있습니다. 정말 감추려면 # 입니다.

implements 가 타입을 채워 주지 않습니다

implements 를 적어도 메서드의 매개 변수 타입은 직접 적어야 합니다. 확인만 할 뿐 물려주지 않습니다.

실습 문제

직접 해보기

1. 세는 클래스 난이도 중

숫자를 감춰 두고 더하기만 할 수 있는 클래스를 만드세요. 현재 값은 읽을 수 있어야 합니다.

class Counter {
	constructor(private count: number = 0) {}

	add(n: number = 1): void {
		this.count += n;
	}

	get value(): number {
		return this.count;
	}
}

const c = new Counter();
c.add();
c.add(5);

console.log(c.value);
2. 인터페이스 지키기 난이도 중

label(): string 을 요구하는 인터페이스를 만들고, 그것을 갖춘 클래스를 작성하세요.

interface Printable {
	label(): string;
}

class Product implements Printable {
	constructor(public name: string, private price: number) {}

	label(): string {
		return `${this.name} ${this.price}원`;
	}
}

console.log(new Product("연필", 1000).label());
요약

이 단원의 정리

  • 필드는 위에 미리 적어 두어야 합니다.
  • 생성자 매개 변수에 제한자를 붙이면 선언과 대입이 한 번에 됩니다.
  • private 는 검사할 때만 막습니다. 실행할 때 감추려면 # 입니다.
  • readonly 는 만든 뒤 바뀌지 않아야 할 것에 붙입니다.
  • implements 는 갖추었는지 확인만 하고 물려주지 않습니다.