출처:https://learn.microsoft.com/en-us/shows/web-wednesday/what-is-typescript
Typescript is a Superset, still JS
자바스크립트지만, 자바스크립트의 상위 집합이다! 즉 자바스크립트를 래핑한 언어라고 볼 수 있다.
굳이 왜 사용할까?
동적 타입언어를 정적 타입언어로 바꾸어 타입을 안전하게사용하기 위함이다.
동적타입언어도 동적타입만의 장점이 있다. 변수선언시 간편하고, 배열(튜플)에 어떤 타입을 넣어도 된다.
그러나 협업의 관점에선 문제가 생긴다. 타인이 만든 코드의 타입을 하나하나 확인할 수도없다. 코드의 규모가 커지면 커질수록 생산성에 문제가 생긴다.
따라서 우리는 타입스크립트를 사용한다.
타입스크립트는 동적 언어인 자바스크립트를 정적 언어처럼 보이게 만든다. 하지만 정적 언어는 런타임 이전에 타입 검사를 실행해야한다.
이게 어떻게 가능한걸까?
컴파일은 보통 명령어를 이용해서 컴파일을 진행한다. 타입스크립트도 마찬가지로 특정 명령어를 이용해 컴파일한다.
//hello.ts
let message: string = '안녕하세요'
console.log(message)
export default message //모듈오류 방지용 export
위 파일을 타입스크립트 컴파일러를 이용하여 컴파일해보자.
아래와 같은 결과를 받을 수 있다.(컴파일러 버전은 5.4.5임)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var message = '안녕하세요';
console.log(message);
exports.default = message;
타입스크립트의 문법으로 작성되었던 .ts
파일을 자바스크립트의 문법으로 작성된 .js
파일로 변환해준다.
이게 타입스크립트 컴파일러가 하는 일이다.
그렇다면 어떤 과정을 거쳐서 ts => js 변환이 이루어지는걸까? 이전 TIL에서 배웠던 컴파일 과정을 기반으로 한 번 추측해보자.
실제로 위와 같은지 한 번 찾아보자.
출처 : https://www.huy.rocks/everyday/04-01-2022-typescript-how-the-compiler-compiles
tsconfig.json
파일을 읽어 컴파일 세팅값을 맞춘다.getDianostics()
함수를 이용하여 타입도 체크함. 음! 원래 알고있던 컴파일 과정에서 조금씩 추가됐을 뿐, 전체적인 골자는 비슷하다.
다만 고유명사나 내부에서 쓰이는 함수, 기능들이 있어서 살짝 어려웠다.
결국 컴파일과정에 타입 체킹이 들어있다. 하지만 개발자는 타입스크립트 파일을 실시간으로 컴파일하지 않는다.
😮...너무 당연한듯이 사용하고 있었다. 그러면 어떻게 실시간 타입 체킹을 지원하는걸까?
바로 LSP(Languages Server Protocol)을 이용하여 검사한다.
현대엔 다양한 에디터,IDE가 존재한다. 만약 자동완성을 지원한다고 가정해보자.
A편집기는 JAVA로 제작되어있다. B편집기는 C언어로 제작되어있다.
이때 JAVA자동완성이 필요하다고 해보자. A편집기는 쉽게 만들 수 있다. JAVA로 만들었기 때문이다. 하지만 B편집기는 C언어로 제작되었기에 C언어로 JAVA의 도메인모델을 구현해버리는 게 된다. (본말전도)
따라서 이러한 에디터가 기존 라이브러리를 재사용할 수 있다면, 풍부한 편집기능을 지원할때 보다 더 편리해 질 것이다.
이를 통합-추상화하여 만든 것이 LSP다.
출처 : https://www.eclipse.org/community/eclipse_newsletter/2017/may/article1.php
vscode가 언어 서버와 통신하며 자동완성, 오타, 타입체크 검출등의 역할을 수행한다.
그렇단 얘기는 인터넷에 연결되어있지 않으면 작업이 불가능 한걸까?
출처 : https://code.visualstudio.com/api/language-extensions/language-server-extension-guide
NO! 그렇지 않다. VSCODE 내부 99%의 LSP는 로컬 서버다. 따라서 인터넷에 연결되지 않아도 VSCODE가 자동완성, 오타검출, 정의로 이동 등 풍부한 편집기능을 제공해줄 수 있는 것이다!
타입스크립트 딥다이브 핸드북을 훑어보며 잘 몰랐던 타입스크립트의 기능들에 대해 알아보자.
Declare: 선언하다
다른 곳에 존재하는(JS,Coffe Script, Browser, Node,...etc) JS코드를 사용하기 위해 declare
라는 키워드를 사용한다.
foo = 123; // Error: 'foo' is not defined
//declare 사용
declare var foo: any;
foo = 123; //가능함
모듈패턴인 import, export대신 왜 이렇게 쓰는거지?🤔
=> 정확히는 실제 변수를 선언하는게 아니라, 컴파일러에게 선언된 타입이 존재한다라고 알려주는 것이다.
실제로 타입스크립트 내부 파일을 살펴보면
이렇게 개발자가 그냥 사용할 수 있는 값들인 NaN, Infinity
등에 대해서 변수가 존재한다라고 declare
를 통해 타입스크립트 컴파일러에게 알려주는 모습을 볼 수 있다.
보통 외부 API, 라이브러리를 활용할때 주로 사용하게 된다. 이러한 선언들을 ambient declare(주변 선언)라고 한다.
declare typescript의 약자로 수많은 declare들이 모여있는 파일이다. 당연히 외부 라이브러리등이 타입스크립트를 지원하기위해 만든 파일이다.
단순히 declare
만 되어있는 파일도 있고 type, interface
등을 선언해놓은 파일도 있다.
이런식으로 명령어를 주게되면, d.ts
파일을 손쉽게 만들 수 있다.
//hello.d.ts
declare let message: string;
export default message;
Enumeration의 줄임말. 열거 가능한 자료형을 뜻한다. 다른 언어에는 꽤 있는데, JS에는 없다.
Enum의 특징은 뭘까?
enum Direction {
Up,
Down,
Left,
Right
}
이렇게 Direction
이라는 Enum을 선언하면 자동으로 인덱스(0부터)가 할당된다.
이는 마치 JS에서 아래처럼 코드를 작성한 것과 같다.
let Dir;
(function (Dir) {
Dir[(Dir["Up"] = 0)] = "Up";
Dir[(Dir["Down"] = 1)] = "Down";
Dir[(Dir["Left"] = 2)] = "Left";
Dir[(Dir["Right"] = 3)] = "Right";
})(Dir || (Dir = {}));
console.log(Dir);
console.log(Dir.Up);
console.log(Dir[0]);
키-밸류 어느것으로 접근해도 반대 방향을 뱉는 자료구조구나? 참고로 인덱스(숫자)가 아닌 문자열을 대입할 수도 있다.
enum Name{
Kim = 'CheolSoo',
Park = 'JiHun',
}
결론부터 말하자면 index signature는 문자열, 숫자만 가능하다.
js에서는 객체참조를 문자열로 할 수도 있다.
이때 문자열 대신 다른 객체를 넣는다면 JS런타임이 그 타입 내부 toString()
를 강제로 호출한다.
위 내용으로 인하여 TS에서 index signature를 사용할 때 가끔 오류가 발생한다.
let obj = {
toString() {
return "Hello";
},
};
let foo: any = {};
// 오류: 인덱스 서명은 string, number 여야 함...
foo[obj] = "World";
// FIX: TypeScript는 명시적으로 호출하게 강제함
foo[obj.toString()] = "World";
TS에서는 명시적으로 toString()
을 호출하게 강제한다.이는 대개 객체의 기본toString()
구현이 엉망이기 때문이다.
'object Object'
는 어디서 많이 봤다 했더니, 객체를 문자열로 바꾸면 나타나는 현상이었구나🤣
참고로 숫자는 잘 동작한다.
잘 몰랐던 부분들을 속시원하게 긁은 기분이다. 특히 declare
와 index sinagture
은 애매모호했는데 확실히 알게되어 다행이다!
타입스크립트를 계속 사용하게 될텐데, 다음에 또 궁금했던점을 모아 포스팅 하는날이 오지않을까?
아마 다음 TIL은 MVC패턴 + node로 백엔드 or 간단한 nextjs 프로젝트가 될 것 같다.