일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 인터섹션
- recoil
- SSR
- 투포인터
- RTK Query
- tailwind
- React
- 이분 검색
- async/await
- map
- CORS
- Cypress
- 태그된 유니온
- 공변성
- Promise
- 결정 알고리즘
- webpack
- Jest
- app router
- TS
- useAppDispatch
- ESlint
- autosize
- 반공변성
- 타입 좁히기
- 호이스팅
- 무한 스크롤
- 리터럴 타입
- dfs
- CI/CD
- Today
- Total
목록TS/이펙티브 타입스크립트 (17)
짧은코딩
string 타입의 범위는 매우 넓다. string을 타입으로 선언하려면 더 좁은 타입이 있는지 확인해봐야 한다. string을 남발한 설계 interface Album { artist: string title: string releaseDate: string // YYYY-MM-DD recordingType: string // E.g., "live" or "studio" } 이 코드처럼 모두 string으로 선언하면 엉뚱한 값을 넣어도 타입 체커를 통과한다. 이렇게 string 타입이 남용된 코드는 문자열을 남발(stringly typed)했다고 한다. 더 좋은 타입 모델링을 하기 위해서는 타입의 범위를 좁혀서 선언해야 한다. 타입을 좁힌 설계 type RecordingType = 'studio' | ..
유니온의 인터페이스보다는 인터페이스의 유니온을 지향하는 것이 좋다. 사실 앞 문장만 딱 보면 좀 헷갈릴 수 있다. 하지만 막상 코드를 보면 익숙할 것이다. 백터를 그리는 프로그램 작성 예제 유니온의 인터페이스 interface Layer { layout: FillLayout | LineLayout | PointLayout; paint: FillPaint | LinePaint | PointPaint; } 이 코드는 유니온의 인터페이스이다. layout은 모양이 그려지는 방법, 위치를 제어하고, paint는 선의 스타일을 제어한다. 두 속성은 Fill, Line, Point 3개 중 하나를 통일해서 가져야 한다. 하지만 layout은 FillLayout, paint는 LinePaint로 하면 에러가 나게 될..
타입만으로 어떤 변수가 null이 될 수 있는지 없는지를 표현하기는 어렵다. B에서 A의 값이 나오는 거면 A가 null이 될 수 없을 때 B도 null이 될 수 없다. 반대로 A가 null이 될 수 있으면 B도 null이 될 수 있다. 값이 전부 null이거나 전부 null이 아닌 경우로 구분해야 모델링하기 쉽다. 최댓값, 최솟값 예시 잘못된 코드 function extent(nums: number[]) { let min, max for (const num of nums) { if (!min) { min = num max = num } else { min = Math.min(min, num) max = Math.max(max, num) // ~~~ Argument of type 'number | und..
타입을 잘 설계하면 코드를 직관적으로 작성할 수 있다. 타입을 잘 설계하기 위해서는 유효한 상태만 표현할 수 있는 타입을 만들어야한다. 웹 애플리케이션 예시 문제점이 있는 코드 -페이지를 렌더링 해주는 함수 interface State { pageText: string isLoading: boolean error?: string } declare let currentPage: string function renderPage(state: State) { if (state.error) { return `Error! Unable to load ${currentPage}: ${state.error}` } else if (state.isLoading) { return `Loading ${currentPage}....
타입스크립트는 단순히 값만 가지고 타입 추론을 하지 않고 문맥까지 본다. 하지만 문맥까지 고려하면 추론이 이상해질 수도 있다. 이상한 에러 -에러 코드 type Language = 'JavaScript' | 'TypeScript' | 'Python' function setLanguage(language: Language) { /* ... */ } setLanguage('JavaScript') // OK let language = 'JavaScript' setLanguage(language) // ~~~~~~~~ Argument of type 'string' is not assignable // to parameter of type 'Language' 여기서 language의 타입 추론은 string으로 ..
비동기와 async 과거에는 비동기를 하기 위해 콜백 지옥을 겪었다. 이후에 "Promise"와 "async와 await"이 등장해 콜백 지옥을 해결했다. await는 각 Promise가 처리(resolve)될 때까지 기다려준다. try/catch를 이용해 예외 처리도 가능하다. 타입스크립트 컴파일러는 async와 await이 동작하도록 정교한 변환을 수행한다. 즉, TS는 런타임에 상관없이 async/await을 사용할 수 있다. 콜백보다 프로미스를 사용해야 하는 이유 1. 콜백보다 프로미스가 코드를 작성하기 쉽다. 2. 프로미스가 타입 추론에 유리하다. -Promise 예시 async function fetchPages() { const [response1, response2, response3] =..
타입스크립트의 타입은 일반적으로 변하지 않는다. 타입스크립트에서 객체를 생성할 때는 여러 속성을 한 번에 생성하는 것이 타입 추론에 유리하다. 잘못된 타입 할당 const pt: Point = {} // ~~ Type '{}' is missing the following properties from type 'Point': x, y pt.x = 3 pt.y = 4 이 코드는 pt가 맨 처음 값을 기준으로 타입이 추론되어 에러가 난다. 좋은 타입 할당 -객체를 한번에 정의 const pt = { x: 3, y: 4, } // OK 이렇게 한번에 정의하면 타입 문제를 해결할 수 있다. -타입 단언문(as) 사용 interface Point { x: number y: number } const pt = {} ..
타입 넓히기 런타임 시 모든 변수는 유일한 값을 가진다. 하지만 타입스크립에서는 코드를 정적 분석하는 시점에서 변수는 가능한 값들의 집합인 타입을 가진다. 즉 타입을 명시하지 않으면 타입 체커는 할당 가능한 값들의 집합을 유추한다. 이러한 과정을 타입 넓히기(widening)이라고 부른다. 타입 넓히기의 문제점 -실행은 되지만 에디터에 오류가 나는 코드 interface Vector3 { x: number y: number z: number } function getComponent(vector: Vector3, axis: 'x' | 'y' | 'z') { return vector[axis] } let x = 'x' let vec = { x: 10, y: 20, z: 30 } getComponent(ve..
타입 반복 개발자라면 코드의 반복을 줄이려고 노력한 적이 분명 있을 것이다. 이런 것을 DRY(don't repeat yourself)라고 한다. 이것을 타입에도 적용하여 타입 반복 또한 줄여야 한다. 이 글은 두고두고 많이 봐야 한다고 생각한다. 왜냐하면 평소에 코드 중복을 굉장히 많이 하여 개발했기 때문이다. 그렇기에 개발을 할 때마다 이 글은 자주 챙겨보면서 타입 중복을 피하여 코딩해야겠다. 타입 반복 예시 -문제 코드 interface Person { firstName: string lastName: string } interface PersonWithBirthDate { firstName: string lastName: string birth: Date } 나도 평소에 이렇게 타입이 겹치는 것이..
타입스크립트에서 명명된 타입(named type)을 정의하는 방법은 type과 interface 2가지가 있다. 대부분의 경우 type과 interface 둘 중 아무거나 사용해도 문제가 없다. 하지만 둘 중 하나로 통일해야 하는 상황이 있다. 이 글에서는 type과 interface의 공통점과 차이점에 대해서 알아보도록 하자. 그 전에 이 글에서 interface는 IState, type는 TState로 표기하는 일이 있을텐데 이 방법은 좋은 방법은 아니라서 지양하는 것이 좋다. 예시 코드에는 저 방식을 사용하여서 불가피하게 저 방식을 예시로 사용하겠다. type과 interface의 공통점 1. 인덱스 시그니처와 함수 타입 인덱스 시그니처와 함수 타입은 type과 interface에서 모두 사용된다...