210502 React with TypeScript TIL - keyof와 typeof의 혼합 사용, JavaScript의 Curring 방식의 함수 작성

React with TypeScript

keyof와 typeof의 혼합 사용

특정 변수의 타입을 정의할때 만약에 해당 타입이 다른 타입과 종속적인 관계에 있다면, 종속관계에 있는 해당 타입의 정의를 참조해서 타입을 정의해야 한다.

아래는 스프라이트 기법으로 이미지를 잘라내서 사용하기 위한 이미지 좌표의 타입 정의이다.

1
2
3
4
5
6
7
8
const coords = {
img1: '0',
img2: '-142px',
img3: '-284px'
} as const;

type a = keyof typeof coords; // coords 타입(typeof)의 key 값(img1 | img2 | img3)
type imgCoords = typeof coords[keyof typeof coords] // '0' | '-142px' | '-284px'
Read more

210427 React with TypeScript TIL - useState에서 빈 배열([])로 초기화시키는 경우, props 타입(함수형, 클래스형 컴포넌트), webpack-dev-server 사용, setTimeout과 useRef의 사용

React with TypeScript

useState에서 빈 배열([])로 초기화시키는 경우

typescript에서 useState hooks를 사용해서 초기 값을 빈 배열로 할 경우, 타입스크립트에서는 빈배열([])을 never type으로 인식하기 때문에 구체적인 타입을 지정해줘야 한다.

type 선언을 위해 사용한 interface는 같은 파일에서 정의를 하지 말고, 별도의 파일(types.ts)로 빼서 다른 파일에서 재사용 가능하도록 정의를 하는 것이 좋다.(코드의 가독성, 재사용성)
types.ts

1
2
3
4
export interface IDetailInfo {
id: string;
contents: string;
}

main.ts

1
2
3
4
import { IDetailInfo } from './types';
...
const [detail, setDetail] = useState<IDetailInfo[]>([]);
...
Read more

210426 React with TypeScript TIL - Webpack + TypeScript, react/react-dom - DefinitelyTyped, webpack.config.json, event handler와 useRef typing, class state typing, useState의 타입추론, useCallback typing, class component의 createRef typing, react-hot-loader 사용

React with TypeScript

프로젝트 기본 구성

typescript, react, react-dom, webpack, webpack-cli 설치

1
2
3
4
5
$ npm i typescript
# 웹 환경에서는 react-dom, 모바일은 react-native
$ npm i react react-dom

$ npm i -D webpack webpack-cli

이전에 React에서 webpack + babel을 사용해서 JavaScript의 최신문법과 JSX 문법을 이전의 JavaScript 문법으로 변환해주었는데, 이번 TypeScript에서는 webpack + TypeScript 조합으로 변환을 해준다.

TypeScript는 자체적으로 babel처럼 최신문법이나 jsx 문법을 이전 문법(ES3 or ES5)으로 바꿔준다. 따라서 별도로 Babel을 사용할 필요는 없다. 하지만 TypeScript + Babel의 조합으로 사용하는 경우도 있기 때문에 이 부분을 알아두도록 하자.

Read more

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