Search

6주차

34. 부정확한 타입보다는 미완성 타입을 사용하기

너무 과하게 타입을 지정하다보면 부정확한 타입지정으로 인해 사이드 이펙트가 발생해 정상적인 사용이 불가할 수 있습니다.
따라서 정확하게 모델링할 수 없다면, 차라리 any, unknown을 사용하는 편이 낫습니다.

35. 데이터가 아닌, API와 명세를 보고 타입 만들기

예시데이터가 아닌 명세서를 보고 만들어야만 정확한 타입을 지정할 수 있으니 주의합니다.

36. 해당 분야의 용어로 타입 이름 짓기

같은 의미의 다른 이름을 피하고, 최대한 해당 분야의 용어를 사용해야만 합니다.

37. 공싱 명칭에는 상표를 붙이기

구조적 타이핑으로인해 값을 세밀하게 구분할 수 없습니다. 따라서 세밀한 구분이 필요하다면 이를 명시해주는 것도 방법입니다.
type Meters = number & {_brand: 'meters'}; const meters = (m: number) => m as Meters; const oneKim = meters(1000); // Meters // 단 연산후 다시 number가 되기때문에 고려가 필요합니다. const tenKim = oneKim * 10; // number
JavaScript
복사

5장 any 다루기

점진적인 마이그레이션 시 any는 중요한 역할을 합니다. 장단점을 체크하도록 합니다.

38. any 타입은 가능한 한 좁은 범위에서만 사용하기

최대한 영향을 적게 끼치는 방향으로 사용해야합니다.
1번과 같은 상황은 반환타입이 있을 때 함수 바깥(사용하는 측)까지 영향을 미치기 때문에 피해야 합니다.
// 1. X function F1(){ const x: any = Foo(); process(x); return x; } // 2. 개선 function F1(){ const x = Foo(); process(x as any); return x; }
JavaScript
복사
객체의 경우 필요한 부분에만 any를 사용해줘야합니다.
// 1. X const config: Config = { a : 1, b: 2, c : { key: value } } as any; // 2. 개선 const config: Config = { a : 1, b: 2, c : { key: value as any } };
JavaScript
복사
강제적으로 타입 오류제거시 @ts-ignore 또한 고려해볼 수 있습니다.

39. any를 구체적으로 변형해서 사용하기

배열
any[]로 사용하기
객체
{[key: string]: any}, Object 사용하기
Object의 경우 객체 키를 열거할 수 있지만, 속성에 접근할 수 없습니다.
o[key] // error 발생
함수
type Fn0 = () ⇒ any;
type Fn1 = (arg: any) ⇒ any;
type FnN = (…args: any[]) ⇒ any; // Function 타입과 동일

40. 함수 안으로 타입 단언문 감추기

함수 내부가 너무 복잡하다면 외부로 드러나는 타입정의만 명시하는 것이 현실적인 해결책입니다.
function shallowObjectEqual<T extends object>(a: T, b: T): boolean { for(copnst [k, oval] of Object.entries(a)){ if(!(k in b) || aVal !== (b as any)[k]) { return false; } } return Object.keys(a).length === Object.keys(b).length; }
JavaScript
복사

41. any의 진화 이해하기

any로 선언된 변수등에 선언을 통해서 값이 진화할 수 있습니다.
function range(start: number, limit: number){ const out = []; for(let i = start; i < limit; i++){ out.push(i); } return out; // number[]로 추론됨 }
JavaScript
복사
값이 null인 경우에도 일어나는데 주로 try, catch에서 발생합니다.
let val = null; // type: any try { somethingDangerous(); val = 12; val // type: number } catch(e) { console.warn('e'); } val // type: number | null
JavaScript
복사
단 noImplicityAny가 설정된 암시적 any인 경우에만 발생합니다. 명시적일경우 any가 유지됩니다.
let val: any; // type: any try { somethingDangerous(); val = 12; val // type: any } catch(e) { console.warn('e'); } val // type: any
JavaScript
복사
암시적 any의 경우 할당 없이 읽을 시 오류가 발생하며, 함수호출을 거쳐도 진화하지 않기때문에 여전히 에러가 발생합니다.
function makeSquares(start: number, limit: number){ const out = []; range(start, limit).forEach(i => { out.push(i);}); return out; // any[] }
JavaScript
복사

42. 모르는 타입의 값에 any 대신 unknown을 사용하기

any가 위험한 이유는 아래와 같습니다.
어떠한 타입이든 any에 할당가능
any는 어디에든 할당가능
unknown과 never는 조금 다릅니다.
unknwon은 어떤 타입이든 할당가능하지만, unknown과 any에만 할당가능합니다.
never는 어떤 타입도 할당할 수 없지만, 어디에든 할당가능합니다.
만약 반환값을 모른다면 unknown을 반환하고, 단언문을 통해 사용자가 타입을 좁히도록하는 강제하는 것이 좋습니다.
{}는 undefined와 null을 제외한 모든 값을 포함하고, object는 모든 비기본형 타입으로 이루어졌습니다.

43. 몽키 패치보다는 안전한 타입을 사용하기

document.monkey와 같이 객체에 값을 추가해주는건 위험하기에, 추가적인 선언이 필요합니다.
interface의 보강기능을 활용해줍니다.
interface Document { monkey: string; } document.monkey = 'Tamarin';
JavaScript
복사
구체적인 타입 단언문을 사용해줍니다.
interface MonkeyDocument extends Document { monkey: string; } (document as MonkeyDocument).monkey = 'Macaque';
JavaScript
복사

44. 타입 커버리지를 추적하여 타입 안전성 유지하기

noImplicityAny가 있더라도, 라이브러리등에 any가 있을 수 잇습니다.
type-coverage 패키지를 통해 추적 및 점검 가능합니다.