typescript keyof

example.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export type User = {
name: string;
email: string;
};

const user: User = {
name: 'chinsung',
email: 'chin_sung@naver.com',
};

// keyof User === 'name' | 'email'
const updateUser = (name: keyof User, value: string) => {
return {
...user,
[name]: value,
};
};

updateUser(''); // wow 자동완성!!
  • 나이수

참고

typescript is keyword

1
2
3
4
5
function isValidPostAttributes(
attributes: any
): attributes is PostMarkdownAttributes {
return attributes?.title;
}
  • remix 튜토리얼하다가 요상한 문법을 보았다
  • any같은 . 찍으면 자동완성 안뜨는 타입들을 특정 타입으로 좁혀줘서, 자동완성 지원도 받을 수 있다
example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function isNumber(x: any): x is number {
return typeof x === 'number';
}

function isString(x: any): x is string {
return typeof x === 'string';
}

function hello(value: any) {
if (isNumber(value)) {
return value.toFixed();
}
if (isString(value)) {
return value.length;
}
throw new Error(`hello error`);
}
  • any로 받았는데, 타입 가드를 통과하면
  • 해당 타입처럼 다룰 수 있다
  • as로 강제 캐스팅하여 사용하지 않아도 된다!

참고

ts enum spread

example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum TestStatus {
PENDING,
ACCEPTED,
WRONG_ANSWER,
}
console.log(Object.values(TestStatus));
// [ 'PENDING', 'ACCEPTED', 'WRONG_ANSWER', 0, 1, 2 ]

export enum Actor {
USER = 'USER',
HOST = 'HOST',
ADMIN = 'ADMIN',
}

console.log(Object.values(Actor));
// [ 'USER', 'HOST', 'ADMIN' ]
  • 일반 Numeric enums의 경우 멤버 이름과 값이 나온다
  • String enums의 경우 값만 나온다
  • es2017 이상에서 사용할 수 있다

참고

tsconfig baseUrl eslint

tsconfig에 baseUrl을 ./src로 설정했다
그런데 eslint가 못 알아먹는다
알아먹도록 해보자

상황

  • 타입스크립트 프로젝트에서 npx eslint --init을 통해 eslint 환경을 구성했다
  • 그런데 tsconfig에 설정한 baseUrl을 eslint가 알아먹지 못했다

eslint-import-resolver-typescript 설치

terminal
1
yarn add -D eslint-import-resolver-typescript

eslintrc 수정

.eslintrc.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
// ...
"parserOptions": {
// ...
"project": "./tsconfig.json"
},
// ...
// https://github.com/import-js/eslint-plugin-import/issues/1485#issuecomment-535351922
"settings": {
"import/resolver": {
"typescript": {}
}
}
}
  • parserOptions.projectsettings.import/resolver.typescript에 위 내용처럼 추가한다
  • eslint config를 수정하면 항상 ESLint: Restart ESLint Server 또는 Developer: Reload Window을 꼭 해주자

참고

typescript에서 jest 쓰기

Jest encountered an unexpected token
SyntaxError: Cannot use import statement outside a module

따라하기

terminal
1
2
3
4
5
6
7
# jest 설치
yarn add --dev jest
yarn add --dev @types/jest

# typescript에서 jest 돌리기 위한 추가 종속성 설치
yarn add --dev @babel/preset-typescript
yarn add --dev babel-jest @babel/core @babel/preset-env
  • 종속성을 설치한다
babel.config.js
1
2
3
4
5
6
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
};
  • babel.config.js 를 추가한다

eslint를 같이 사용하고 있다면

eslintrc.json
1
2
3
4
5
6
7
{
"env": {
// ...
"jest": true
}
// ...
}
  • eslintrc 에 env.jest를 true로 해준다

참고

typescript Partial

자주 쓰는 타입 유틸 ; Partial, Pick, Omit, Record

Partial

  • Partial을 사용해서 각 필드를 옵셔널로 만들 수 있다
example.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Todo = {
title: string;
description: string;
};

const updateTodo = (todo: Todo, fieldsToUpdats: Partial<Todo>) => {
return { ...todo, ...fieldsToUpdats };
};

const todo1: Todo = {
title: 'be super',
description: 'power overwhelming',
};

const todo2 = updateTodo(todo1, { description: 'show me the money' });

console.log(todo2);

Pick

Pick.ts
1
2
3
4
5
6
7
type Todo = {
title: string;
description: string;
time: string;
};

type Todo2 = Pick<Todo, 'title' | 'time'>;

참고

setTimeout typescript

1
2
class Dice {
sto: ReturnType<typeof setTimeout>;
  • typescript로 웹 스크립트를 짜고 있다
  • clearTimeout을 사용하기 위해 멤버 변수 sto를 넣었다
  • 근데 setTimeout의 타입이 뭘까?
  • 에디터에서 NodeJS.Timeout라고 알려주긴 하는데..
  • 내 런타임을 노드가 아니라 브라우저다
  • ReturnType<fn>을 사용하면 브라우저든 SSR이든 걱정 없다고 한다

참고

내가 타입스크립트를 쓰는 이유

타입스크립트 입문 전

  • C, C++, JAVA를 학교 수업으로 들었다
  • 3,4 학년 때는 웹 프로그래밍을 많이 하면서 백엔드는 nodejs, 프론트는 ejs를 했었다
  • nodejs 위에서 js를 쓰면서 이것저것 쓰면서 익숙해지고 있었다
  • 자바스크립트는 공부해서 했기보다는 그냥 막히는 부분마다 검색해서 해결했었다
  • for문도 그냥 array api(foreach, map, reduce) 안 쓰고 for(;;)로 다 짜고..
  • 그당시 내가 느끼기로 자바스크립트는 C나 JAVA에 없는 괴랄한 문법이 많이 있었다
  • 그런거에 흥미를 가지면서 for(;;) 쓰는거 그만하고 js스러운 코드를 짜기 시작했었던 같다
  • 또 js는 여태껏 배워온 C나 JAVA와 다르게 타입에 전혀 얽매이지 않고, 웬만하면 에러없이 동작해서 엄청 편했다

타입스크립트 입문 동기

  • ts를 한번 쓰면 못 빠져나온다는 조언을 들음
  • (그만큼 좋다)

타입스크립트 첫인상

  • 기존에 배웠던 엄격한 언어들과는 다르게 js는 엄청 유연한? 언어였다
  • 나는 이런 특성이 편하게 다가왔다
  • 타입 때문에 골머리 아프지 않아도 돼서 뭔가 해방된 느낌이 들었기 때문이다
  • 그런데 타입스크립트라고 자바스크립트에서 굳이 타입을 붙여 써서 뭐가 좋아지는지
  • 왜 다시 역행하는지에 대해 약간 의문이 있었다
  • 실제로 시작해서도 그간 타입을 명시하지 않았던 편안함을 잃은 기분이었다
  • 타입스크립트를 쓰면…

1 + ‘1’
// ‘11’

  • 숫자+숫자로 예상했는데 실제론 숫자+문자열하는 일은 안 겪어되는 것부터 해서
  • 실행 전에 에러를 잡아 준다는데,,
  • 그거야 처음에 잘 짜면 되는 것을,, 이때는 공감하지 못했다

내가 생각하는 타입스크립트 장점

7개월 차 (20년 9월 - 21년 4월)

  • 타입스크립트는 짱이다
  • 위에서 말한 타입스크립트를 쓰는 일반적인 장점이 있지만,
  • 나는 이 장점 다 필요 없고 자동완성이 100% 보장된다는 점에서 타입스크립트를 좋아한다
  • 예를 들면 그냥 js를 쓸 때는 배열 변수에 . 찍어도 array api 자동완성이 안된다

  • 위가 js고 아래가 ts다
  • 위는 그냥 arr 변수가 배열이든 아니든 그냥 스니펫만 제공하는 반면
  • 아래 ts의 경우 배열 타입에 맞춰서 그에 맞는 array api를 자동완성해주는 모습이다
  • 이 정도까지는 그냥 코드 스니펫으로 해결할 수 있는 수준이지만
  • 이런 api 자동완성은 기본이고, 어떤 클래스나 객체를 생성해서 하위에 멤버 변수가 있을 때

  • .만 찍으면 전부 자동완성 해준다. 오타로 인해 삽질할 필요가 전혀없는거다
  • 나는 코드 쓸 때 쉬프트 누르는 것을 별로 안 좋아한다. 쉬프트를 누르면 순간 느려지고 오타도 생기기도 하고.. 답답해진다
  • c나 java를 할 때도 일단 소문자로 쓰고 나중에 rename 기능을 통해 카멜 케이스로 변경할 만큼..
  • ts를 쓰면 이런 고민이 필요 없는 게 최초 1회만 잘 작성해두면 ctrl space만으로 코드를 작성할 수 있다 ㅋㅋㅋ
  • 또 장점이라면 내가 잘못된 코드를 작성했을 때 실행도 시켜주지 않기 때문에 모르고 지나갈 수 없다
  • 오류가 생기면 어디서 오류가 생겼는지 확실히 알 수 있다!
  • 결론! 자동완성에 한번 빠지면 헤어 나올 수 없다
  • 아니 이것도 자동완성이 된다고? 하는 곳까지 진짜 다 된다
  • ts하다가 js가면 한숨이 나올 것이다

타입스크립트 더 고수가 되고 생각나면 추가해야지..

반응속도 테스트 클론코딩

기능

  • 반응속도 기록
  • 랜덤 간격
  • 눈 덜 아프게
  • 결과에 따라 다른 메시지
  • 예측 클릭하면 횟수 -1

느낀점

  • 기존 테스트가 색이 확 반전돼서
  • 집중은 해야 하는데 눈이 너무 아팠다
  • 그래서 배경색은 그대로에 초록점이 생기도록 했다
  • 컨텍스트 쓸까 고민하다가 어차피 깊이도 안 깊어서 그냥 prop으로 넘겨줬다

개선방향

공유 버튼 만들기

  • 결과 이미지 생성해서 클립보드 복사해주기 또는 이미지 파일로 저장

구린 css 바꾸기

  • 색을 좀 이쁘게 써보자

레포