만약에 사용하고자 하는 package가 기본적으로 type을 제공하지 않고, DefinitelyTyped에도 없는 경우, 이런 경우에는 내가 직접 typing을 해줘야 한다. (전부 typing하지 않고 내가 사용할 부분만 부분 typing한다.)
예를들어, can-use-dom이라는 타입을 제공하지 않는 패키지를 설치해서 사용하는데, DefinitelyTyped에도 없는 경우, 이 경우에는 아래와 같이 프로젝트 폴더 안에 *.d.ts파일을 작성해줘야 한다. 되도록이면 types와 같은 별도 폴더를 생성해서 내부에 *.d.ts파일을 작성해주도록 한다.
이제 작성해준 can-use-dom.d.ts파일을 *.ts 파일 내에서 인식시키기 위해서 tsconfig.json파일에서 "typeRoot"옵션의 속성값으로 작성해준 *.d.ts파일의 폴더 경로를 적어줘야 한다.
tsconfig.json
1 2 3 4 5 6 7 8 9 10 11 12
{ "compilerOptions": { ... "typeRoots": ["./types", "./node_modules/@types"], ... }, "exclude": ["*.js"], // "include"에는 구체적으로 특정 파일을 작성하지 않도록 한다. // 만약 구체적으로 파일을 명시하게 되면 해당 타입스크립트 파일만 컴파일되기 때문에 // 내가 작성한 *.d.ts 파일이 컴파일 되지 않는다. "include": [], }
함수의 매개변수가 단순한 경우에는 그냥 각 각의 인수를 넣어서 호출해줘도 되지만, 만약에 함수의 매개변수로 넘겨줘야 되는 인수의 갯수가 많아지는 경우, 각 각의 인수가 어떤 역할을 하는지 파악하려면 다시 그 함수를 참조해야 한다. 따라서 넘겨줘야 되는 인수의 갯수가 늘어나는 경우 객체 타입으로 작성해서 각 인수의 역할에 대해서 유추할 수 있도록 작성을 해주면 코드의 가독성이 높아진다.
1
Example({ flag: true, id: '1' });
함수의 구조분해 매개변수에 타입 지정해주기
구조분해한 매개변수의 경우에는 구조분해한 변수의 뒤에 타입을 지정하지 않고 구조분해한 {}뒤에 콜론을 찍고 타입을 지정해준다.
TypeScript는 HTML 자체를 인식하지 못하기 때문에 HTML 내의 요소를 참조할때 null로 인식하는 경우가 있다.
따라서 확실하게 HTML에 요소가 존재하는 경우에는 개발자가 !로 존재를 보증해주거나 if 문으로 조건처리를 해서 작성을 해줘야 한다.
1 2 3
if (document.querySelector('#id')) { (document.querySelector('#id') as HTMLElement).style.background = '......'; }
TypeScript에서 inline styling
타입스크립트에서 inline 스타일링을 하기 위해 HTML element를 참조하게 되면 .style을 하거나 .textContent를 하는 경우에 에러가 발생한다. 그 이유는 아래와 같이 querySelector로 HTML 요소를 참조하게 되면 해당 참조 요소의 타입은 Element를 상속받는 제네릭 타입 E가 된다. 이 Element에는 style, textContent 속성이 없다.
1
querySelector<E extends Element = Element>(selectors: string): E | null;
따라서 Element type을 HTMLDivElement로 타입의 범위를 좁게 잡아줘야 한다.
// as로 Type casting (document.querySelector('#id') as HTMLDivElement).style.background = '...';
// generic으로 Type casting document.querySelector<HTMLDivElement>('#id').style.background = '...';
tsc로 타입스크립트 파일을 컴파일할때에는 파일명을 넣지 않는다.
타입스크립트 파일을 컴파일할때 npx tsc -w과 같이 컴파일할 파일을 명시하지 않도록 한다. 그 이유는 파일명을 구체적으로 명시해주게 되면, 프로젝트 폴더 내에 정의한 타입스크립트 설정파일(tsconfig.json)이 무시가 되서 설정된 사항들이 적용이 안될 수 있기 때문이다.
비슷한 속성의 객체는 같은 interface로 타입을 정의할 수 있다.
타입스크립트의 장점은 interface에 작성해준 타입의 정의를 보고 프로그램의 구조에 대한 힌트를 얻을 수 있다.
아래에 사람(Person)과 레스토랑(Restaurant) 인터페이스를 작성해보았다. 아래 예시 코드를 통해 "strictNullCheck": true일 경우의 null과 undefined에 대한 내용도 한 번 정리해보겠다.
객체를 as const로 정의를 해주게 되면 객체내의 모든 타입 속성들이 readonly로 바뀌는 것을 확인할 수 있다. 만약 일부의 타입 속성들만 상수로써 바뀌지 않게 하고 싶다면 해당 타입 속성의 변수명의 앞에 readonly를 붙여주도록 한다. 만약 변수의 타입이 상수 타입으로 고정되는 경우, 이 경우에는 별도로 as const나 readonly를 붙여주지 않아도 상관없다.
interface와 type alias 비교 및 사용
interface와 type alias를 사용해서 객체의 타입을 정의할때 그 용도를 일관되게 나눠서 사용하는 것이 좋다. 예를들어, 객체의 타입은 interface를 사용해서 정의하고 custom type은 type alias를 사용해서 정의하도록 하는 것이다. interface와 type 모두 아래와 같이 객체의 타입을 정의할 수는 있지만 코드를 작성할때 일관성을 지켜서 코드를 작성하는 편이 좋다.
interface의 특징
interface내에 정의한 타입 속성은 ,(콤마)나 ;(세미콜론), \n(줄바꿈)으로 구분할 수 있다.
Typescript는 언어이자 라이브러리로, 프로그래밍 언어는 실행기가 필요하다. JavaScript의 실행기는 ‘Browser’와 ‘Node’가 있다. 이 실행기가 프로그래밍 언어를 해석해주는 역할을 해준다. 그렇다면 TypeScript의 실행기는 무엇일까? TypeScript의 실행기는 현재 개발중에 있는 Deno이다. 아직은 안정적인 버전이아니기 때문에 라이브러리가 TypeScript의 실행기이다. 실행기가 라이브러리라서 좋은 점은 빠르게 release할 수 있다는 점이 있지만 단점으로는 여러가지 버그가 존재한다는 것이다. TypeScript의 라이브러리(실행기)를 설치하기 위해서는 Node를 설치해줘야 되기 때문에 Node에 대해서 어느정도는 이해해야 한다. 이 TypeScript 라이브러리가 TypeScript를 JavaScript로 코드 변환을 해주는데 이는 브라우저는 JavaScript 코드만 이해할 수 있기 때문이다.
이 포스팅은 O’Reilly TypeScript책을 통해 공부한 내용과 실습한 내용을 기반으로 작성하였습니다.
오늘 공부한 내용
타입(type)에 대한 이해
이번에 독서를 통해서 타입(type)대해서 다시 정의해 볼 수 있었다. 기존에는 type에 대한 정의를 단순 data의 형식(string, number, list)에 국한된 개념으로만 알고 있었다.
하지만 이 책에서는 타입을 값과 이 값으로 할 수 있는 일의 집합으로 정의하고 있다. 예를들어, number 타입을 정의하자면 number라는 type으로써의 값과 숫자에 적용할 수 있는 모든 연산(+,-,*,/,%,||,&&,?등)과 숫자에 호출할 수 있는 모든 메서드(.concat, .toUpperCase 등)를 포괄적으로 포함하는 개념으로 정의할 수 있다.
이렇게 정의된 타입(type)의 정의를 통해 타입검사기(typechecker)는 주어진 값으로 할 수 있는 유효한 동작과 유효하지 않은 동작을 구분해서 유효하지 않은 동작이 실행되는 일을 예방할 수 있다.
이 포스팅은 O’Reilly TypeScript책을 통해 공부한 내용과 실습한 내용을 기반으로 작성하였습니다.
오늘 공부한 내용
컴파일과 실행에 대한 이해
이번에 읽은 내용에서 가장 유익하다고 느꼈던 내용이다. 실제 코드를 작성하고 실행을 했을때 내부에서 구체적으로 어떤 과정에 의해서 처리가 되는지 잘 몰랐었는데 이번 기회에 제대로 알 수 있었던 것 같다. 특히 타입스크립트는 자바스크리트나 자바와 같은 주요 언어와는 다른 방식으로 동작하기 때문에 이 부분에 대해서 정리를 해보려고 한다.
일반적으로 프로그래머가 작성한 텍스트(코드)는 컴파일러(compiler)라는 프로그램이 파싱(Parsing)하여, AST(Abstract Syntax Tree, AST)라는 자료구조로 변환된다. 이 AST는 공백, 주석, 탭, 공백 등의 결과를 무시한다.
컴파일러는 이 AST 자료구조를 바이트 코드(bytecode)라는 하위 수준의 표현으로 변환을 한다. 이렇게 만들어진 바이트 코드는 런타임(runtime)이라는 다른 프로그램에 입력해서 평가하고 결과를 얻을 수 있는 것이다.
텍스트 코드 => 컴파일러(Compiler) => AST(Abstract Syntax Tree)