[이펙티브 타입스크립트] 7장 코드를 작성하고 실행하기
주요 내용
- 자바스크립트와 타입스크립트 호환 관련하여 지양해야할 점
- 정보 은닉 하는 방법(클로저)
- 소스맵 정의
아이템53 타입스크립트 기능보다는 ECMAScript 기능을 사용하기
타입스크립트와 자바스크립트간의 호환성문제로 유의해야 하는 것들
- enum
const enum Flavor {
V = 0,
C = 1,
S = 2,
}
function scoop(flavor: Flavor)
scoop('vanilla'); // 자바스크립트에서는 정상
scoop('vanilla'); // 타입스크립트에서는 에러 'vanilla' 형식은 'Flavor' 형식의 매개변수에 할당될 수 없습니다
자바스크립트와 타입스크립트에서 동작이 다르기때문에 문자열 열거형은 사용하지 않는 것이 좋다.
열거형 대신 리터럴 타입의 유니온을 사용하자.
type Flavor = 'vanilla' | 'chocolate' | 'strawberry';
let flavor: Flavor = 'chocolate'; //정상
function scoop(flavor: Flavor) {
if (flavor === 'v
// 자동완성이 'vanilla'를 추천합니다.
}
자바스크립트와 호환도 되고, 열거형처럼 자동완성 기능을 사용할 수 있다.
- 매개변수 속성
- 클래스 초기화시 생성자와 매개변수 사용 문법(JS/TS)
// 자바스크립트
class Person {
name: string;
constructor(name: string){
this.name = name;
}
}
// 타입스크립트
class Person {
constructor(public name: string){}
}
해당 타입스크립트 코드의 문제점
- 코드가 줄어들지만, 매개변수 속성은 늘어나는 문법임
- 매개변수 속성과 일반 속성(JS 예시)를 섞어서 사용하면 더 혼란스러워짐
- 트리플 슬래시 임포트
- 타입스크립트 초창기 시절 모듈 시스템(임포트 하기 위한)
namespace foo {
function bar() {}
}
/// <reference path="other.ts"/>
- 데코레이터
- 클래스, 메소드, 속성등에 어노테이션을 붙임으로써 기능을 추가하는데 사용할 수 있다.
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@logged
greet() {
return "Hello, " + this.greeting;
}
}
function logged(target: any, name: string, descriptor: PropertyDescriptor) {
const fn = target[name];
descriptor.value = function() {
console.log('Calling ${name}');
return fn.apply(this, arguments);
};
}
- 타입스크립트 코드에서 모든 타입 정보를 제거하면 자바스크립트가 되지만 enum, 매개변수 속성, 트리플 슬래시 임포트, 데코리에터는 타입 정보를 제거한다고 자바스크립트가 되지 않는다.
- 타입스크립트의 역할을 명확하게 하려면, enum, 매개변수 속성, 트리플 슬레시 임포트, 데코레이터는 지양하는게 좋음.
아이템54 객체를 순회하는 노하우
우리가 개발하면서 일상에서 자주 겪는 ts 에러이다.
const obj= {
one: 'uno',
two: 'dos',
three: 'tres',
}
for(const k in obj) {
const v = obj[k]; // - obj 에 인덱스 시그니처가 없기 때문에 엘리먼트는 암시적으로 'any' 타입입니다.
}
해결 방안
const obj= {
one: 'uno',
two: 'dos',
three: 'tres',
}
// 해결방안1
let k: keyof typeof obj;
for( k in obj) {
const v = obj[k];
}
// 해결방안2
function foo(abc: ABC) {
for (const [k, v] of Object.entries(abc)) {
k // string 타입
v // any 타입
}
}
- 해결방안1) K의 타입을 구체적으로 알려줌
- 해결방안2) Object.entries 사용
아이템55 DOM 계층 구조 이해하기
아래 코드는 타입스크립트에서 수많은 오류가 발생함
function handleDrag(eDown: Event) {
const targetEl = eDown.currentTarget;
ta rgetEl.classList.add(‘dragging1);
const dragStart = [eDown-clientX, eDown.clientY];
const handleUp = (ellp: Event) => {
targetEl.classList.remove('dragging');
targetEl.removeEventListener('mouseup', handleUp);
const dragEnd = [ellp.clientX, eUp-dientY];
console.log('dx, dy =', [0, l].map(i => dragEnd[i] - dragStart[i]));
}
targetEl.addEventListener('mouseup', handleUp);
}
const div = document.getElementByld('surface');
div.addEventListener('mousedown', handleDrag);
이럴경우에는 타입 단언문을 사용한다.
HTMLParagraphElement는 HTMLElement의 서브타입
HTMLElement는 Element 의 서브타입
Element는 Node의 서브타입
Node는 EventTarget 의 서브타입
아이템56 정보를 감추는 목적으로 private 사용하지 않기
class Foo {
_private = 'secret123';
}
class Diary {
private secret = 'cheated on my English test';
}
const diary = new Diary();
(diary as any).secret // 정상
클래스에서 _ 접두사를 이용하여 비공개 속성을 만들어서 사용하지만, 런타임에는 아무런 효력이 없을뿐더러 타입단언문을 사용하면 private에도 접근이 가능하다.
정보를 은닉하기위해선 클로저를 사용해야 한다.
클로저 예시
declare function hash(text: string): number;
class Passwordchecker {
checkPassword: (password: string) => boolean;
constructor(passwordHash: number) {
this.checkPassword = (password: string) => {
return hash(password) === passwordHash;
}
}
}
const checker = new PasswordChecker(hash('s3cret'));
checker.checkPassword('s3cret'); // 결과는 true
- 장점) Passwordchecker 생성자 외부에서 passwordHash 변수에 접근할 수 없다 -> 정보 은닉 성공
- 단점) passwordHash에 접근하는 메서드 역시 내부에 작성되어야하고, 인스턴스가 생성될때마다 메서드의 복사본이 생성됨 -> 메모리 낭비 발생
현재 표준화 진행중인 정보 은닉 방법
class Passwordchecker {
#passwordHash: number;
constructor(passwordHash: number) {
this.#passwordHash = passwordHash;
}
checkPassword(password: string) {
return hash(password) === this.#passwordHash;
}
}
const checker = new Passwordchecker(hash('s3cret1'));
checker.checkPassword('secret'); // 결과는 false
checker.checkPassword('s3cret'); // 결과는 true
이런 문법은 2021년도 기준으로 자바스크립트 표준3단계라고 함.
아이템57 소스맵을 사용하여 타입스크립트 디버깅하기
타입스크립트 코드를 실행한다 -> 타입스크립트 컴파일러가 생성한 자바스크립트 코드를 실행한다는 의미
변환된 자바스크립트코드는 복잡해서 디버깅하기 어려움 -> 이를 해결하기위해 Source Map 이 만들어짐
- Source Map
- 변환된 코드의 위치와 코드를 매핑함
- 원본코드가 그대로 유출되지 않도록 주의해야함
아래는 소스맵 관련해서 자세하게 설명되어있는 좋은 글이 있어서 공유한다.
https://yozm.wishket.com/magazine/detail/2082/?utm_source=oneoneone