이 게시물은 SW 마에스트로 연수생 간 진행한 Effective Typescript 스터디의 개인 정리 내용입니다
[ Item 26 ] 타입 추론에 문맥이 어떻게 사용되는지 이해하기
타입 추론에 문맥이 어떻게 사용되는지 이해하기
타입스크립트의 타입체커는 추론을 위해 값만 체크하는것이 아니라 해당 값이 존재하는 위치의 문맥도 파악합니다.
문맥을 통한 추론으로 더욱 정확한 결과가 나오는 경우가 있지만, 아마도 경험 하셨겠지만 가끔 반대로 엉뚱한 타입이 나오기도 합니다.
한번 그 “엉뚱한 타입” 의 예시를 확인해봅시다.
1
2
3
4
5
6
7
8
9
type Language = "JS"|"TS"|"Python"
function setLanguage(language:Language) {
return
}
setLanguage("JS")
let language = "JS"
setLanguage(language)
// language 의 타입이 string 으로 추론됨.
인라인 형태에서는 함수 선언 때문에 매개변수가 Language 타입이어야 하는 것을 알 수 있습니다. 그리고 그 타입에는 “JS” 라는 문자 리터럴이 할당 가능하기때문에 문제가 없었습니다.
하지만 이를 변수로 분리 해 낸다면 타입체커는 “할당” 시점에 타입을 추론합니다. 이번 경우는 string으로 추론되고 해당 타입은 Language 타입에 할당이 불가능하여 오류가 발생했던 것입니다.
그럼 어떻게 해결해야 할까요?
제안하는 방법은 두 가지 입니다.
타입 선언에서
language의 가능한 값을 제한하기1 2
let language:Language = "JS" setLanguage(language)
language를 상수로 만들기1 2
const language = "JS" setLanguage(language)
const 를 사용한다면 타입체커는
language를 문자열 리터럴로 추론해줍니다.
튜플에서의 문제점
문자열 리터럴에서와 비슷하게 튜플 타입에서도 문제가 발생합니다.
1
2
3
4
5
6
function panTo(where:[number,number]) {
return
}
panTo([10,20]) // 정상
const loc = [10,20]
panTo(loc) // loc 은 number[] 형식으로 추론됨.
number[] 타입과 [number, number] 타입의 큰 차이점은 앞선 number[] 타입은 길이를 알 수 없는 점입니다.
따라서 길이까지도 정해져있는 튜플타입엔 할당될 수 없기때문에 오류가 발생합니다.
그럼 어떻게 해결해야 할까요??
앞선 const 로 바꾼다는 옵션은 이미 불가능합니다.
하지만 타입을 선언해주는 방법은 유효하나 이번엔 또 다른 방법을 소개하려 합니다.
as const
일반적으로 사용하는 const 는 단지 값이 가리키는 참조가 변하지 않는 “얕은“ 상수인 반면 as const 는 값 내부까지 “깊이” 타입체커에게 알려줍니다
1
2
const loc = [10,20] as const
panTo(loc) // readonly [10,20] 형식이다!
결국 readonly 타입을 반환해서 즉시 사용은 불가능합니다. 이 경우엔 매개변수의 type 을 readonly 로 바꿔줘야 합니다.
1
2
3
4
5
6
function panTo(where: readonly [number,number]) {
return
}
panTo([10,20]) // 정상
const loc = [10,20] as const
panTo(loc) // 정상 !
as const 의 단점은 타입 정의에 실수가 있었다면, 오류가 타입 정의가 아닌 호출되는 곳에 발생하는 것 입니다. 일반적으로 타입 정의에 실수가 있었다면 타입 정의 부분에 오류 발생을 알려주기에 이러한 단점은 혼란을 가중시킬 수 있습니다.
결론
타입체커는 단순히 값에 따른 타입을 반환해주는것이 아니라 문맥에 따라서 타입을 반환해주기도 합니다.
변수 선언에서 오류가 발생한다면 타입 선언을, 변수가 정말 상수라면 as const 를 사용하라고 제안하긴 했지만, as const의 단점과 더불어 readonly 같은 문제도 있어서 지금까진 굳이 as const 사용할바엔 타입선언을 해주는게 더 낫지 않나 싶습니다.
[ Item 27 ] 함수형 기법과 라이브러리로 타입 흐름 유지하기
함수형 기법과 라이브러리로 타입 흐름 유지하기
태생이 가벼운 언어였던 JS 이기에 다른 언어들은 가지고 있는 표준 라이브러리들이 JS 에는 포함되어있지 않습니다.
그렇기에 현재 많은 라이브러리들이 만들어지고 사용되고 있기도 합니다.
순수 JS 만을 사용한다면 다른 라이브러리를 사용하는 것보다 코드가 길고 복잡해지며 타입오류도 발생하기 쉬워집니다. 물론 라이브러리들이 바닐라 JS 의 불편함을 해소하기 위해 만들어진 것이기 때문이기도하지만, 책에서는 로대시와 루프를 그 예시로 들고 있습니다.
결론 & 개인 의견
어쨌든 로대시를 사용하면 타입 흐름이나 타입 구문등 불필요한 코드낭비를 줄일 수 있다.. 어쩌구 저쩌구 하는데, 우리보다 잘하는 개발자들이 만든 라이브러리가 우리가 짠 코드보다 효율이 좋고 타입 오류를 발생하지 않는건 당연…하지 않나?
살짝 이번 아이템은 “로대시 정말 좋은 라이브러리니 꼭 한번 써보세요!” 같은 뭔가 광고물같은 아이템이었다.
[ Item 28 ] 유효한 상태만 표현하는 타입을 지향하기
유효한 상태만 표현하는 타입을 지향하기
제 4장 타입 설계의 첫번째 아이템 유효한 상태만 표현하는 타입을 지향하기 입니다.
타입을 잘 설계하면 코드를 더욱 직관적으로 작성할 수 있을테지만, 그 반대라면 코드 작성 과정부터 쉽지 않은 일이 됩니다.( 거의 제 얘기입니다 )
만약 제대로 설계되지 않은 타입을 사용한다면, 정보가 부족하거나 속성이 충돌하는 등 혼란을 야기할 수 있습니다.
웹앱을 만드는 예시에서 과거 타입에 태그를 다는 기법을 사용해서 유효한 상태를 나타내는 타입과 무효한 상태를 나타내는 타입을 분리해서 구현했습니다. 이렇게 타입을 신경써서 선언하고 분리해서 구현한다면 구현과정에서 겪을 불필요한 낭비들을 크게 줄일 수 있습니다.
결론 & 개인의견
사실상 대다수의 로직이 유효한 상태 혹은 무효한 상태 라는 조건문으로 구현되는 만큼 상태를 기준으로 타입을 구분하여 작성한다면 훨씬 더 좋은 코드를 작성할 수 있을 것 입니다.
바로 어제 개발바닥에 올라온 영상의 주제가 좋은 코드+구현 못함 vs 누더기코드+일단 구현 에 대한 부분이었습니다.
유효한 타입을 설계하고 좋은 코드를 작성을 지향하는것은 두 말 할것 없이 좋지만 아직 저희같은 경험이 부족한 개발자들이 클린코드를 신경쓰느라 구현에 뒤처지는건 더 안좋은 방향이 아닐까 싶었습니다.
[ Item 29 ] 사용할 땐 너그럽게, 생성할 땐 엄격하게
사용할 땐 너그럽게, 생성할 땐 엄격하게
TCP 구현체는 견고성의 일반적 원칙을 잘 따라야 한다. 당신의 작업은 엄격하게 하고,
다른사람의 작업은 너그럽게 받아들일 수 있어야 한다.
위 문장은 존 포스텔이 쓴 견고성의 원칙? 포스텔의 원칙? 이라고 합니다.
일반적으로 함수의 시그니처엔 다음과 같은 규칙을 적용합니다.
매개변수의 타입은 넓어도 되지만, 반환하는 결과의 타입은 더욱 구체적이어야 합니다.
결론 & 개인의견
좀 맛없는 아이템이었습니다.
사실상 건진 키워드는 함수를 작성할 때 매개변수의 타입은 더욱 느슨하게, 반환 결과의 타입은 더욱 좁게 설정해서 사용하기 편한 결과값을 예측하기 쉬운 함수를 작성하라~ 라는 내용입니다.
하지만 그 내용을 전달하기엔 크게 와닿지 않는 예제들이었고, 단순히 저 말만 적어둬도 “그게 맞지” 하고 넘어갔을만한 내용들인데 억지 설명을 하려고 억지 자료를 만든 느낌을 지울 수 없었습니다.
[ Item 30 ] 문서에 타입 정보를 쓰지 않기
문서에 타입 정보를 쓰지 않기
조금 놀랐습니다. 최근에 props 타입을 정의하면서 왜 이 props 타입을 받는지 주석으로 적어두었는데 그걸 하기가 무섭게 하지 말라는 아이템을 접하게 됐네요…
딱 구구절절 어떤어떤 정보를 받고 어떤 정보를 반환한다~ 라고 주석을 달아놨었는데 … ( 다른 개발자도 읽기 쉬운 코드가 좋은 코드다~ 라는 말을 접해서 나부터가 읽기 편하라고 적었는데 ㅜ )
결론 & 개인의견
너무 짧은 글이죠? 아이템 자체가 한페이지 조금 넘는 분량이라서 어쩔 수 없었습니다.
어쨌든 주석은 코드와 동기화 되지 않는다.
그리고 주석은 잘 적어도 본전인데 잘 못 적거나 업데이트를 그때그때 안해주면 오히려 마이너스다.
그리고 어지간해선 너보단 타입스크립트 만든 개발자들이 수십년의 경험을 가진 전문가다 (저자가 실제로 한 말)
그러니까 타입이나 잘 정의해라 라는게 결론인 것 같습니다.
누가 절 지켜보고있다가 이걸 읽게 한 느낌이라 살짝 창피하네요 ㅜ
