TypeScript Handbook 을 통해 알게된 새로운 사실들!

Intro


좋은 기회가 생겨서 TypeScript 의 핸드북을 정독하게 되었고

그동안 인터넷 검색으로 어렴풋이 알고 있었던 TypeScript 사용법을 이번기회에 더욱 명확하게 알 수 있을 것 같다.

해당 글은 그 동안 놓쳤던 부분들을 정리하는 느낌으로 글을 작성하려고 합니다!

Content


우선 핸드북의 순서부터 살펴보면

  • 소개
  • 기초 내용
  • 자주 사용하는 Type
  • 세부 Type
  • 함수
  • 객체 Type
  • Type 조작
  • class
  • 모듈

전체 8가지 항목으로 내용이 생각보다 길다.

이 중 읽으면서 인상 깊었던 파트는 아래와 같다

  • 기초 내용
  • 자주 사용하는 Type
  • 세부 Type
  • 함수

하나씩 정리해보면

기초 파트

기초적인 내용 중 다운 레벨링이라는 용어가 새롭게 들렸다.

컴파일 하기 전 해당 코드를 컴파일 하게 된다면

// test.ts
`Hello ${person}, today is ${date.toDateString()}!`;

아래와 같이 변환 되는데

// test.js
"Hello " + person + ", today is " + date.toDateString() + "!";

이유는 다운 레벨링이라고 하여 컴파일 이후 나오는 JS 문법은 Default 로 아주 구버전인 ES3에 문법에 맞추도록 되어있다.

이렇게 설정한 이유가 조금 놀라웠다.

물론 설정값으로 변환시 사용될 문법을 선택할 순 있지만 컴파일이후 이전에 사용한 모든 JS 도 동일하게 유지하기 위해 가장 구버전을 사용한 부분이 레거시 코드를 고려한 것 같아서 놀랐다

자주 사용하는 Type 파트

해당 항목에서는 자주 쓰는 Type 에 대해서 알려준다.

string, number, any, 등등

또한 이를 가지고 놀 수 있는 유니언 타입, 별칭, 인터페이스, 타입 등등을 알려준다.

여기서 놀랐던 부분은 인터페이스와 타입의 확실한 차이점을 알려주었다.

TypeScript 를 하다보면 inteface 로도 타입 명시가 가능하고 type 으로도 명시가 가능한데

이 2개의 차이점이 대체 뭐지?

이런 궁금증이 있었기 때문이다.

가장 큰 차이점은 인터페이스는 확장과 새로운 타입 선언이 가능하지만 타입은 그렇지 않다

// inteface 확장 -> 항상 확장만 가능 
interface car {
	name: string;
	
}

interface productCar extends car{
	modelNum: number;
}

// type 확장 -> 개방이기 때문에 유지, 추가, 선택 가능
type car {
	name: string;
	
}

type productCar = car & {
	modelNum: number;
}

type anotherCar = car 

type anotherNum = car | {
	modelName: string;
}
// interface 수정 -> 변경이 가능해진다.
interface user {
	name: string;
}

interface user {
	nickName:string 
}

> user.nickName 출력

// type 수정 -> 변경 불가능 
type user = {
	name: string;
}

type user = {
	nickName: string // => ERROR!! Duplicate identifier 'user'.
}

이런 차이를 확인해 봤을 땐 개인적인 생각으로는 type 에 어울리는 문법은 역시 interface 보단 type 같다.

interface 는 interface 의 역할만 하는 것이 적당하다고 생각한다.

세부 Type 파트

유니온 차별화…? 라고 되어있는데 TYPE 을 제한 할 수 있는 부분이다.

해당 파트에서 인상적이였던 부분은 일부 타입을 명시할 수 있다는 점이다.

예를 들어 content type 에는 NOTICE, NORMAL 밖에 안들어간다고 했을 때 2가지의 타입 STRING 이기 때문에 오타 확인은 내부에서 일일이 해줘야한다.

// content type: NOTICE, NORMAL
type content = {
	type: string
}

const content:content = new Content()

if(content.type !== 'NOTICE'){
	throw new Error('error!')
} else if(content.type !== 'NORMAL'){
	throw new Error('error!')
}

하지만 다음과 같이 string 자체를 type으로 명시할 수 있기 때문에 오타에 대한 부분을 덜 수 있다.

type content = {
	type: 'NOTICE'| 'NORMAL'
}

const content:content = new Content()

content.type = 'REVIEW' // ERROR! : NOTICE| NORMAL 중 하나가 아님

이런 기능은 앞으로 더 많이 쓸 것 같아서 기억에 남는다

함수

해당 부분에서 인상 깊었던 부분은 함수 부분이다

단순히 생각해봤을때 당연한 것 같아 작성하였던 부분인데

// function
function testFunction(a: any[]): any{ // 어째뜬 리스트 형태를 받아서
	return a[0] // 리스트 첫번째 인수를 리턴
}

const a = testFunction([1, 2, 4]) // a: number 추론...?

any[] 로 표기를 했으니 당연히 리스트의 존재로 인식할 줄 알았고

이렇게 작성한다면 return type 으로는 input 에 따라 바뀌겠지 했었다

그렇지만 이렇게 한다 하더라도 any[] 는 여전히 any 로 표기를 할 수 있는 부분이고

input 에 따라 달라지다는 명시가 없으므로 어찌보면 당연한 거다.

input 에 따라 바뀌게 수정하고 싶다면 다음과 같이 작성해야한다.

// function
function testFunction<Type>(a: Type[]): Type | undefined{ // 어째뜬 리스트 형태를 받아서
	return a[0] // 리스트 첫번째 인수를 리턴
}

const a = testFunction([1, 2, 4]) // a: number 확정!

type 을 확장시켜서 INPUT 을 제한하는 방법도 인상적이였다.

// function
function lengthCheck<targetType extends {length: number}>(target: targetType): number{
	return target.length 
}

const a = lengthCheck(3) // ERROR!: number is not has 'length'

// <> 내부에서 extends 를 활용하면 type 요소를 제한할 수 있다!

OUTRO


공식 문서를 이렇게 정독해보긴 처음이다.

보통 개발하다가 막히는 부분이 있다고 하면 해당 부분만 발췌하여 읽곤 했는데

한번 정독하는 것도 나쁘지 않은 방법같다. 새롭게 알게 된 내용도 있을 뿐더러

그동안 찾아보기 어렵거나 검색해도 나오질 않았던 부분이 명쾌하게 해결되는 부분도 있다는 것을 알았다.

다만 너무 내용이 지루할 순 있어서 적절히 조절하며 읽어야 겠다.

profile
Full 이 되고 싶은 BackEnd

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN