Effective TypeScript 5~9

저니·2023년 7월 18일
0

타입스크립트

목록 보기
1/2

[5] any 타입 지양하기

any는 타입 안정성이 없다

any는 함수 시그니처를 무시해 버린다.

any 타입을 사용하면 IDE에서 code hint 도움을 받기 어렵다.

⇒ 사실상 any 를 쓰는 건 plain javascript를 쓰는 것과 같기 때문에 최대한 지양하라는 의미인 듯 함.

2. 타입 스크립트의 타입 시스템

[6] 편집기를 사용하여 타입 시스템 탐색하기

타입 스크립트를 설치하면, 다음 두 가지를 실행할 수 있다.

  • tsc
  • tsserver

⇒ 타입스크립트가 제공하는 언어 서비스를 최대한 활용하자(편집기 등등).

[7] 타입이 값들의 집합이라고 생각하기

가장 작은 집합은 공집합 = never 타입. 아무런 값도 할당 할 수 없다.

그 다음으로는 unit 타입이라고도 불리는 literal 타입.

type A = 'A'
type B = 'B'
type Twelve = 12;

// 두 개 혹은 세 개로 묶으려면 유니온(union)타입을 사용한다.
type AB = 'A' | 'B';
type AB12 = 'A' | 'B' | 12;

객체 타입에서 & 연산자는 두 타입의 intersection을 계산한다. ⇒ 두 타입의 속성을 전부 가지는 타입을 정의

interface Person {
	name: string;
}
interface Lifespan {
	birth: Date;
	death?: Date;
}

type PersonSpan = Person & LifeSpan;

// 좀 더 일반적으로는 사실 `extends` 키워드를 사용한다.
// extends 를 상속의 의미가 아니라 "~의 부분집합"이라는 개념으로 생각하면 편함.
interface PersonSpan extends Person {
	birth: Date;
	death?: Date;
}

하지만 두 인터페이스의 유니온의 경우엔 다륾.

type K = keyof (Person | Lifespan); // 타입이 never

keyof (A&B) = (keyof A) | (keyof B)
keyof (A|B) = (keyof A) & (keyof B)

[8] 타입 공간과 값 공간의 심벌 구분하기

타입스크립트의 심벌은 타입 공간이나 값 공간 중의 한 곳에 존재한다. 따라서 이름이 같더라도 공간에 따라 다른 것을 나타낼 수 있기 때문에 혼란스러울 수 있다. 아래에 두 Cylinder는 타입으로 쓰일 수도 있고, 값으로 쓰일 수도 있다.

interface Cylinder {
	radius: number;
	height: number;
}

const Cylinder = (radius: number, height: number) => ({radius, height});

classenum은 상황에 따라 타입과 값 두 가지 모두 가능한 예약어이다.

typeof 연산자는 타입에서 쓰일 때와 값에서 쓰일 때 다른 기능을 한다.

// 값에서 쓰일 땐 자바스크립트의 `typeof`연산자를 사용하게 됨.
// 자바스크립트의 런타임 타입은 단 6개로 매우 간단 - string, number, undefined, null, object, function
const v1 = typeof p;
const v2 = typeof email;

다만 class 에 대한 typeof 연산자는 상황에 따라 다르게 동작한다.

const v = typeof Cylinder; // function - 클래스는 자바스크립트에선 실제 함수로 구현되므로.
type T = typeof Cylinder; // typeof Cylinder - 인스턴스의 타입이 아닌 생성자 함수.

💡 생성자 타입 vs 인스턴스 타입

생성자 타입: 클래스의 생성자 함수를 나타내는 타입

인스턴스 타입: 클래스의 인스턴스에 대한 타입. 클래스의 인스턴스에 대한 속성과 메서드를 포함하며, 정적 부분은 포함하지 않음.


속성 접근자인 [] 은 타입으로 쓰여도 동일하게 동작하지만, obj['field']obj.field 는 값이 동일하더라도 타입은 다를 수 있다. 따라서 타입의 속성을 얻을 때는 반드시 첫번째 방법을 사용할 것.

const fist: Person['first'] = p['first']

[9] 타입 단언(as Type)보다는 타입 선언(: Type)을 사용하기

interface Person { name: string }

const alice: Person = { name: 'Alice' } // 타입은 Person - 타입 선언문
const bob = { name: 'Bob' } as Person;  // 타입은 Person - 타입 단언문

타입 선언은 할당되는 값이 해당 인터페이스를 만족하는지 검사한다.

타입 단언은 강제로 타입을 지정했으니 타입 체커에게 오류를 무시하라고 하는 것임.

타입 단언이 꼭 필요한 경우는 타입 체커가 추론한 타입보다 본인이 판단하는 타입이 더 정확할 때 의미가 있다

ex. 타입스크립트가 접근할 수 없는 DOM 같은 경우.

또는 접미사에 ! 단언문을 붙여서 null 이 아님을 단언하는 경우도 있음.

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

소중한 정보 감사드립니다!

답글 달기