210425 TypeScript TIL - DefinitelyTyped에 없는 package인 경우(custom package typing), internal module/ external module/ ambient module, 외부 라이브러리의 Typing 5가지 경우, 라이브러리를 만드는 경우, *.d.ts파일과 *.ts파일의 사용, Type intersection, call/bind/apply를 사용한 type 구체화, TS 유틸리티, 데코레이터

TypeScript

DefinitelyTyped에 없는 package인 경우

만약에 사용하고자 하는 package가 기본적으로 type을 제공하지 않고, DefinitelyTyped에도 없는 경우, 이런 경우에는 내가 직접 typing을 해줘야 한다. (전부 typing하지 않고 내가 사용할 부분만 부분 typing한다.)

예를들어, can-use-dom이라는 타입을 제공하지 않는 패키지를 설치해서 사용하는데, DefinitelyTyped에도 없는 경우, 이 경우에는 아래와 같이 프로젝트 폴더 안에 *.d.ts파일을 작성해줘야 한다.
되도록이면 types와 같은 별도 폴더를 생성해서 내부에 *.d.ts파일을 작성해주도록 한다.

/<Project folder>/types/can-use-dom.d.ts

1
2
3
4
declare module "can-use-dom" {
const canUseDOM: boolean;
export default canUseDOM;
}

/<Project folder>/index.ts

1
2
3
import canUseDOM from 'can-use-dom';

console.log(canUseDOM);

이제 작성해준 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": [],
}
Read more

210424 TypeScript TIL-2 - NodeJS의 모듈 시스템과 TypeScript의 모듈 시스템

TypeScript

NodeJS의 모듈 시스템과 TypeScript의 모듈 시스템

타입스크립트의 모듈 시스템을 이해하기 전에 자바스크립트의 모듈 시스템 아니 더 정확하게는 NodeJS의 모듈 시스템에 대해서 알아보도록 하겠다.

  • NodeJS의 모듈 시스템 = commonJS

  • TypeScript의 모듈 시스템 = JavaScript의 최신 문법(ES2015(ES6))을 모듈 시스템에서 그대로 계승

우선 module을 이해하기 이전에 스크립트와 모듈을 구분할 수 있어야 한다.
만약에 자바스크립트 파일 안에 import와 export가 있는 경우, module이며, 없다면 script이다.

그렇다면 모듈이란 무엇일까? 모듈은 다른 자바스크립트 파일에서 특정 자바스크립트 파일을 사용할 수 있도록 만들어주는 것이다. 다시말해 파일을 잘개 쪼개는 효과를 줌으로써 코드의 가독성과 재사용성이 가능하도록 해주는 것이다.

자 이제 모듈의 개념에 대해서 간단하게 이해했으니 이제 NodeJS의 모듈 시스템과 TypeScript의 모듈 시스템의 차이에 대해서 살펴보도록 하겠다.

commonJS

1
2
3
4
5
6
7
8
9
10
// module.js
exports.a = 'b';
exports.b = false;
module.exports = {
a: 'b',
b: false
};

// run.js
const { a, b } = require('./module');
Read more

210424 TypeScript TIL-1 - 구조분해 매개변수의 타입지정, 타입 가드(Type Guard), 객체의 타입이 복잡해지는 경우의 타입지정(interface)

TypeScript

복잡한 인수를 넘겨줄때는 객체 타입으로 작성

함수의 매개변수가 단순한 경우에는 그냥 각 각의 인수를 넣어서 호출해줘도 되지만, 만약에 함수의 매개변수로 넘겨줘야 되는 인수의 갯수가 많아지는 경우, 각 각의 인수가 어떤 역할을 하는지 파악하려면 다시 그 함수를 참조해야 한다.
따라서 넘겨줘야 되는 인수의 갯수가 늘어나는 경우 객체 타입으로 작성해서 각 인수의 역할에 대해서 유추할 수 있도록 작성을 해주면 코드의 가독성이 높아진다.

1
Example({ flag: true, id: '1' });

함수의 구조분해 매개변수에 타입 지정해주기

구조분해한 매개변수의 경우에는 구조분해한 변수의 뒤에 타입을 지정하지 않고 구조분해한 {}뒤에 콜론을 찍고 타입을 지정해준다.

1
2
3
function Example({ flag, id }: { flag: boolean, id: string }) {
...
}

타입 가드(Type Guard)

타입 가드를 사용하면 조건문에서 객체의 타입을 좁혀나갈 수 있다.
타입 가드란 함수의특정 인자가 어떤 타입인지 구분하기 위한 값을 반환하는 함수이다.

사용자 정의 Type Guard

만약 Data 객체가 A 또는 B 객체로 구분된다면 아래와 같이 사용자 정의 Type Guards 방식으로 data 객체의 타입을 좁힐 수 있다.

Read more

210423 TypeScript TIL-2 - TypeScript에서의 DOM element 조작, TypeScript 인라인 스타일, strictNullCheck 옵션, JavaScript에서의 클래스와 TypeScript에서의 클래스 정의, interface에서 객체내의 메서드 타입 정의, 제네릭(generic), 제네릭 예시 - addEventListener 함수

TypeScript

TypeScript는 HTML을 인지하지 못한다.

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로 타입의 범위를 좁게 잡아줘야 한다.

1
2
3
4
5
6
7
document.querySelector('#id').style.background = '...'; // error

// 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에 대한 내용도 한 번 정리해보겠다.

Read more

210423 TypeScript TIL-1 - as const와 readonly, interface와 type alias의 비교 및 사용, interface의 다양한 활용 및 문제해결

TypeScript

as const와 readonly의 사용

객체를 as const로 정의를 해주게 되면 객체내의 모든 타입 속성들이 readonly로 바뀌는 것을 확인할 수 있다. 만약 일부의 타입 속성들만 상수로써 바뀌지 않게 하고 싶다면 해당 타입 속성의 변수명의 앞에 readonly를 붙여주도록 한다.
만약 변수의 타입이 상수 타입으로 고정되는 경우, 이 경우에는 별도로 as constreadonly를 붙여주지 않아도 상관없다.

interface와 type alias 비교 및 사용

interface와 type alias를 사용해서 객체의 타입을 정의할때 그 용도를 일관되게 나눠서 사용하는 것이 좋다.
예를들어, 객체의 타입은 interface를 사용해서 정의하고 custom type은 type alias를 사용해서 정의하도록 하는 것이다.
interface와 type 모두 아래와 같이 객체의 타입을 정의할 수는 있지만 코드를 작성할때 일관성을 지켜서 코드를 작성하는 편이 좋다.

interface의 특징

  • interface내에 정의한 타입 속성은 ,(콤마)나 ;(세미콜론), \n(줄바꿈)으로 구분할 수 있다.

  • 다른 type interface를 상속할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    interface ParentExample{
    readonly A: string,
    readonly B: string
    }

    interface ChildExample extends ParentExample{
    readonly C: string
    }
Read more

210422 TypeScript TIL - 암묵적 타입 정의과 명시적 타입 정의, 배열과 튜플, 변수를 상수로 정의해서 사용하기, 객체의 타입 지정, enum 타입, void, Overloading과 ? 연산자, never과 any 타입, 정의된 타입 재정의, 기존 JavaScript를 TypeScript로 전환하는 경우와 처음부터 TypeScript로 작성하는 경우

TypeScript

암묵적 타입 정의, 명시적 타입 정의

아래와 같이 코드를 작성해주면 암묵적으로 num이라는 변수의 타입은 정의된 값 10에 의해 number 타입으로 타입지정이 된다.

1
let num = 10;

그런데 만약에 값을 정의하지 않고 변수만 선언하는 경우, 이러한 경우에는 타입을 지정해서 해당 변수에 할당될 수 있는 값의 타입을 지정해주는 것이 좋다.

1
let num: number;

간혹 타입을 지정할때 Number, String, Boolean, Object 등으로 작성을 해서 실수하는 경우가 있는데, 앞서 작성한 것들은 모두 자바스크립트에서 객체들이기 때문에 타입은 모두 맨 앞을 소문자로 표기해서 타입지정을 해주도록 하자.

배열과 튜플

  • 배열 표기법

    1
    2
    3
    let arr1: Array<string> = ['1', '2', '3'];
    let arr2: (string | number | boolean)[] = [true, 2, '3'];
    let arr3: number[] = [1, 2, 3];

    타입스크립트에서 숫자타입의 배열을 명시적으로 작성할때 Array와 number[] 두 가지 방법으로 작성할 수 있다.
    두 번째 작성한 것과 같이 복합적인 타입 값들로 구성된 배열 타입으로 명시적으로 지정할 수도 있다.

  • 엄격한 배열의 사용

    1
    2
    let arr1: [boolean, number, string] = [true, 2, '3']; // tuple
    let arr2: [boolean, 1, string] = [true, 1, '3']; // 두번째 인자를 고정된 상수 타입으로 지정할 수도 있다.
Read more

210421 TypeScript TIL - JavaScript와 TypeScript, TypeScript 설치, HTML 태그의 타입, 타입스크립트의 점진적 도입, 문법적 설탕(Syntactic sugar), tsconfig.json에서 자주 사용되는 옵션들, 공식문서 handbook 읽기

Deno

JavaScript와 TypeScript

Typescript는 JavaScript의 superset이라고 불리며, 자바스크립트의 변수/함수의 매개변수와 리턴값에 명시적으로 타입을 지정한다.

항상 그러하듯이 공식 사이트를 참고하면서 공부하면 좋다.

https://www.typescriptlang.org/

Typescript는 언어이자 라이브러리로, 프로그래밍 언어는 실행기가 필요하다. JavaScript의 실행기는 ‘Browser’와 ‘Node’가 있다. 이 실행기가 프로그래밍 언어를 해석해주는 역할을 해준다. 그렇다면 TypeScript의 실행기는 무엇일까? TypeScript의 실행기는 현재 개발중에 있는 Deno이다. 아직은 안정적인 버전이아니기 때문에 라이브러리가 TypeScript의 실행기이다. 실행기가 라이브러리라서 좋은 점은 빠르게 release할 수 있다는 점이 있지만 단점으로는 여러가지 버그가 존재한다는 것이다.
TypeScript의 라이브러리(실행기)를 설치하기 위해서는 Node를 설치해줘야 되기 때문에 Node에 대해서 어느정도는 이해해야 한다.
이 TypeScript 라이브러리가 TypeScript를 JavaScript로 코드 변환을 해주는데 이는 브라우저는 JavaScript 코드만 이해할 수 있기 때문이다.

Read more

210219 TypeScript Book TIL

이 포스팅은 O’Reilly TypeScript책을 통해 공부한 내용과 실습한 내용을 기반으로 작성하였습니다.

오늘 공부한 내용

타입별칭

일반적으로 변수를 선언하듯이 type 키워드로 type을 선언해서 사용할 수 있다.

1
2
3
4
5
type Age = number
type persono = {
name: string
age: Age
}
1
2
3
4
5
6
7
8
9
10
type Person = {
name: string
age: number
}
type Age = number
let age: Age = 55
let driver: Person = {
name: 'James May',
age: age
}

타입의 union과 intersection type

Read more

210216 TypeScript Book TIL

이 포스팅은 O’Reilly TypeScript책을 통해 공부한 내용과 실습한 내용을 기반으로 작성하였습니다.

오늘 공부한 내용

  • 타입(type)에 대한 이해

    이번에 독서를 통해서 타입(type)대해서 다시 정의해 볼 수 있었다. 기존에는 type에 대한 정의를 단순 data의 형식(string, number, list)에 국한된 개념으로만 알고 있었다.

    하지만 이 책에서는 타입을 값과 이 값으로 할 수 있는 일의 집합으로 정의하고 있다.
    예를들어, number 타입을 정의하자면 number라는 type으로써의 값과 숫자에 적용할 수 있는 모든 연산(+,-,*,/,%,||,&&,?등)과 숫자에 호출할 수 있는 모든 메서드(.concat, .toUpperCase 등)를 포괄적으로 포함하는 개념으로 정의할 수 있다.

    이렇게 정의된 타입(type)의 정의를 통해 타입검사기(typechecker)는 주어진 값으로 할 수 있는 유효한 동작과 유효하지 않은 동작을 구분해서 유효하지 않은 동작이 실행되는 일을 예방할 수 있다.


Read more

210215 TypeScript Book TIL

이 포스팅은 O’Reilly TypeScript책을 통해 공부한 내용과 실습한 내용을 기반으로 작성하였습니다.

오늘 공부한 내용

  • 컴파일과 실행에 대한 이해

    이번에 읽은 내용에서 가장 유익하다고 느꼈던 내용이다. 실제 코드를 작성하고 실행을 했을때 내부에서 구체적으로 어떤 과정에 의해서 처리가 되는지 잘 몰랐었는데 이번 기회에 제대로 알 수 있었던 것 같다.
    특히 타입스크립트는 자바스크리트나 자바와 같은 주요 언어와는 다른 방식으로 동작하기 때문에 이 부분에 대해서 정리를 해보려고 한다.

    • 일반적으로 프로그래머가 작성한 텍스트(코드)는 컴파일러(compiler)라는 프로그램이 파싱(Parsing)하여, AST(Abstract Syntax Tree, AST)라는 자료구조로 변환된다. 이 AST는 공백, 주석, 탭, 공백 등의 결과를 무시한다.

      컴파일러는 이 AST 자료구조를 바이트 코드(bytecode)라는 하위 수준의 표현으로 변환을 한다.
      이렇게 만들어진 바이트 코드는 런타임(runtime)이라는 다른 프로그램에 입력해서 평가하고 결과를 얻을 수 있는 것이다.
      1. 텍스트 코드 => 컴파일러(Compiler) => AST(Abstract Syntax Tree)
      2. AST(Abstract Syntax Tree) => 컴파일러(Compiler) => 바이트 코드(bytecode)
      3. 런타임(Runtime) => 바이트 코드(bytecode)

    즉 일반적으로 프로그램을 실행한다는 것은 컴파일러가 소스코드를 파싱해서 AST로 만들고 이 AST를 바이트코드로 변환한 것을 런타임이 평가하도록 지시하는 일련의 과정을 의미한다.

Read more