-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TypeScript & Module Typing] 병민(윤병인) 미션 제출합니다. #7
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
병민 안녕하세요! 하리입니다.
정말 실존하는 라이브러리처럼 깔끔하게 잘 작성해주셨네요... 보면서 많이 배우고 감탄했습니다 👏
공유해주신 사항에 대해 먼저 얘기해볼게요!
🚀 타입 테스트 & TDD
TDD를 엄밀히 할때 유용하다고 느꼈습니다.
사용을 먼저 -> 구현을 나중에 하는 방식을 택하니, 길을 잃지 않고 코드를 작성하게 되는 효과를 느꼈습니다. 유틸함수 개발이나 비지니스 로직은 TDD로 하는것이 좋다는것을 느꼈습니다. 다만 컴포넌트는 변경이 잦아서 초반에 TDD하기는 어려울것 같고 어느정도 컴포넌트의 모양이나 기능이 자리잡혔을때 테스트를 추가하고 후에 TDD를 하는것이 좋을것 같다고 생각했습니다.
TDD의 효용성에 대해서는 저도 공감합니다! 코드를 작성하다보면 가끔 길을 잃는 경우도 있었는데, 확실히 원하는 테스트를 먼저 작성하고 그에 따른 구현 코드를 작성하면 길을 잃지 않고 원하는 결과를 도출할 수 있더라고요.
저는 타입 테스트가 TDD랑 같이 할 때도 좋지만, 유틸 타입 내부에서 ts 문법이 복잡하게 적용된 경우, 기대되는 결과를 테스트하는 부분에서도 유용하다고 생각했습니다 😊
🚀 Jest
저도 Jest 문법의 경우에는 바로 생각나지 않을 때가 많아 그럴 때는 공식의 API를 참고하곤 하는데요. Jest는 공식에서 사용할 수 있는 문법을 잘 정리해놓아 오히려 구글에 검색하는 것보다 찾기 수월하다고 느꼈습니다. 그치만 역시 아직 저도 어려워서 꾸준히 사용해보고 익숙해지는 게 좋을 것 같아요.
🚀 질문
fetch는 어떻게 구현하면 좋을까요?
하리가 node에 일가견이 있다는것을 알고 있습니다. node 18버전부터 native fetch를 지원한다고 해서 사용하긴 했는데, 그 이하버전에서는 어떻게 지원해줘야 할지 모르겠습니다.
제가 node에 일가견이 있다니... 어디에서 그런 이상한 소문이 퍼진거죠? 🤣
우선 짐작으로는 webpack에서 polyfill을 해주면 되지 않을까 싶은데요. 찾아보니까 webpack.ProvidePlugin
을 사용하면 Promise, fetch 등 최신 문법 polyfill이 가능하다네요!
module.exports = {
plugins: [
new webpack.ProvidePlugin({
'Promise': 'es6-promise',
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})
]
};
(위 코드는 예시로 여기에서 가져오기는 했는데, 실제로 테스트해보진 않아서 제대로 동작하는지 확신은 못하겠네요ㅠ.ㅠ)
아무튼! 저는 일단 이 정도만 알고 있는데, 병민이 원하던 답이 맞을진 모르겠네요 하하
🚀 타입스크립트 빌드와 컴파일 전략
저희 팀에서는 tsc와 vs-code 내장 ts server를 활용합니다. 매번 PR 올리기 전에 주기적으로 확인하고 있습니다! 아직 자동화는 하지 않았지만 타입 체킹을 주기적으로 하고 있기 때문에 ts-loader가 필요하지 않다고 생각했습니다. ts-loader를 사용하면 빌드 속도가 좀 더 느려지기도 하고요!
ts-loader도 내부적으로 tsc를 사용한다고 알고 있는데, 그래서 ts-loader 대신 tsc를 사용해주시는 걸까요?.?
그럼 빌드할 때 무슨 로더를 사용하시나요? (저희 팀에서는 예기치 못한 타입 에러 발생 시 빌드가 취소되는 로더를 원해서 ts-loader를 개발 모드에서 사용하고 있거든요!) 모아모아의 경우도 궁금하네요!
@@ -0,0 +1,6 @@ | |||
module.exports = { | |||
presets: [ | |||
["@babel/preset-env", { targets: { node: "current" } }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
보니까 babel과 tsconfig에서 모두 버전에 대한 옵션을 지정해주셨던데, 둘의 차이가 무엇인지 설명해주실 수 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
babel로 컴파일하면 babel의 target을 사용할것이고
tsconfig의 target은 타입스크립트로 컴파일할때 사용합니다!
babel는 typescript파일을 jest로 테스트할때 필요해서 설정했습니다 :D
jest 설정
}); | ||
}; | ||
|
||
[Symbol.iterator]() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
와...
@@ -0,0 +1,6 @@ | |||
{ | |||
"types": "./dummy.d.ts", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 저도 tsd를 실행하는데 types를 넣어야한다고 떠서 저는 빌드된 d.ts 파일을 넣어주었는데, 이렇게 빈 d.ts 파일을 넣어주는 방법도 있군요! 배워갑니다 📝
src/clickOutside.ts
Outdated
const handler = (event: MouseEvent) => { | ||
const path = event.composedPath(); | ||
const hasElementClicked = path.some((p) => p === element); | ||
!hasElementClicked && callback(); | ||
}; | ||
window.addEventListener("click", (event: MouseEvent) => { | ||
const path = event.composedPath(); | ||
const hasElementClicked = path.some((p) => p === element); | ||
!hasElementClicked && callback(); | ||
}); | ||
|
||
return () => window.removeEventListener("click", handler); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 경우에 handler가 removeEventListener에만 있고 addEventListener에는 익명 함수로 등록되어 있어 removeEventListener가 제대로 동작하지 않을 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정했습니다 :D
src/isFunction.ts
Outdated
if (typeof val === "function") { | ||
return true; | ||
} | ||
return false; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분은 return typeof val === "function"
으로 축약하셔도 되겠네요..!
isNumber도 마찬가지로 축약 가능할 것 같습니다 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
맞네요 :D
src/memoize.ts
Outdated
@@ -0,0 +1,48 @@ | |||
type Key = string | number; | |||
|
|||
let cache: Record<Key, any> | any = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이러면 결국 cache의 타입은 any가 될 것 같아요! (any는 모든 타입을 포함하는데 그걸 Record에 Union으로 연결해주니까 그렇겠죠?.?)
무언가 캐시에 들어가는 타입을 확실하게 명시해주거나 아니면 병민의 의도 상으로 any여야한다면 Record는 제외해도 좋을 것 같습니다 ㅎㅅㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
캐쉬에 정말 이것저것 다 들어갈수 있다고 생각해서 any로 수정하였습니다!
src/memoize.ts
Outdated
} | ||
}; | ||
|
||
const memoize = (valFn: () => any, deps?: Array<string | number>) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deps의 타입은 위에서 만들어주신 다른 함수들의 path 타입과 같으니 Array<Key>
로 해주셔도 되겠네요 :) 타입에서도 단일 출처 유지!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정했습니다 :D
): Omit<Obj, Key> => { | ||
const result = { ...obj }; | ||
keys.forEach((key) => { | ||
if (!obj[key]) throw new Error("객체의 key 배열이 아닙니다."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 타입에서 1차 걸러주고 코드에서 2차 걸러주어 컴파일과 런타임 시점을 모두 신경써 작성한 멋진 코드네요! 역시 병민 👏👏👏
tsconfig.json
Outdated
@@ -0,0 +1,20 @@ | |||
{ | |||
"compilerOptions": { | |||
"sourceMap": true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 소스맵을 true로 하신 이유가 있나요~?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
엇!
build할것이 아니라서 소스맵이 필요 없습니다.
이외에도 불필요한 속성은 삭제했어요 :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굿굿 병민 수고하셨어요~! 역시 갓병민 찬양하라 🥳
많이 배웠습니다 :)
🔥 팀 미션 적용 결과
본 미션을 수행하며 경험, 영감, 학습한 내용을 팀 미션에 전파해주세요.
✅ 요구사항 구현 확인
DOM 유틸
유틸
🧐 공유
/_ 작업하면서 든 생각, 질문, 새롭게 학습하거나 시도해본 내용 등등 공유할 사항이 있다면 자유롭게 적어주세요 _/
타입 테스트
TDD를 엄밀히 할때 유용하다고 느꼈습니다.
TDD의 효용성
사용을 먼저 -> 구현을 나중에 하는 방식을 택하니, 길을 잃지 않고 코드를 작성하게 되는 효과를 느꼈습니다.
유틸함수 개발이나 비지니스 로직은 TDD로 하는것이 좋다는것을 느꼈습니다. 다만 컴포넌트는 변경이 잦아서 초반에 TDD하기는 어려울것 같고 어느정도 컴포넌트의 모양이나 기능이 자리잡혔을때 테스트를 추가하고 후에 TDD를 하는것이 좋을것 같다고 생각했습니다.
참고
react-hook-form을 많이 참고했습니다.
tsd와 관련 설정들이 잘 되어 있어서 많은 도움이 되었습니다.
Jest
jest사용이 저에게는 어려웠습니다. 일반적인 로직은 할만 했는데, 타이머를 돌리거나 이벤트 리스너를 감지하는? 그런 것들은 어려웠습니다.
앞으로 공부가 많이 필요하다고 느꼈습니다.
질문
fetch는 어떻게 구현하면 좋을까요?
하리가 node에 일가견이 있다는것을 알고 있습니다.
node 18버전부터 native fetch를 지원한다고 해서 사용하긴 했는데,
그 이하버전에서는 어떻게 지원해줘야 할지 모르겠습니다.
help me!
/모아모아에서 타입스크립트 사용 방법/
타입스크립트 빌드와 컴파일 전략
저희 팀에서는 tsc와 vs-code 내장 ts server를 활용합니다. 매번 PR 올리기 전에 주기적으로 확인하고 있습니다! 아직 자동화는 하지 않았지만 타입 체킹을 주기적으로 하고 있기 때문에 ts-loader가 필요하지 않다고 생각했습니다. ts-loader를 사용하면 빌드 속도가 좀 더 느려지기도 하고요!
타입스크립트
interface를 사용하지 않고 type만 사용해서 타입 선언
Api 관련 타입은 Api = {get: {...}, ...} 규칙을 따름
함수 컴포넌트 타입
리뷰 잘 부탁드려요 하리!