아이템 19. 추론 가능한 타입을 사용해 장황한 코드 방지하기

아이템 19. 추론 가능한 타입을 사용해 장황한 코드 방지하기

아이템 19. 추론 가능한 타입을 사용해 장황한 코드 방지하기 #

" 타입 구문을 생략하여, 방해되는 것들을 최소화하고 코드를 읽는 사람이 구현 로직에 집중할 수 있게 해주는 것이 좋습니다. “

대부분의 경우 타입스크립트에서 타입 구문은 불필요하다.

타입을 선언하는 것은 ‘비생상적’, ‘형편없는 스타일’로 여겨진다.

let x: number = 12;

// vs //

x: number = 12;

(코드를 보면서) 타입을 확신하지 못한다면 편집기(IDE)를 통해 체크할 수 있다.

ㄴ 이 문장은 ‘타입이 명시적으로 있는 게 좋지 않은가?’ 나의 질문에 대한 답변이 되었다.



타입스크립트는 우리가 예상한 것보다 더 정확하게 추론하기도 한다. #

const axis1: string = 'x';  // 타입: string
const axis2 = 'y';          // 타입 : "y"

axis2 변수를 string 으로 예상하기 쉽지만, “y"가 더 정확한 타입이다.


타입이 추론되면 리팩터링도 용이해진다. #

interface Product {
    id: number;
    name: string;
    price: number;
}

function logProduct(product: Product) {
    const id: number = product.id;
    const name: string = product.name;
    const price: number = product.price;

    console.log(id, name, price);
}

이후에 Product.idnumber 에서 string 으로 변경이 필요했을 때를 가정한다.

ㄴ 타입 추론으로 작성했다면 logProduct 와 같은 다른 곳에서 코드 변경(numberstring) 없이 사용할 수 있다.

다만, 이게 좋은 것일까?

개발자가 인지하지 못하면서, 자동으로 해주는 것은 이후에 사이드 이펙트로 연결되지 않나?

(프로젝트 내에서는 트랜스 파일, 테스트 코드 등이 다 잡아줄 것 같긴 해서) 예시를 찾기가 쉽지는 않다.

다른 프로젝트와 연계되었을 때를 생각해볼 수 있을 것 같다.

따라서, 인지를 잘 하고 쓰는게 좋을 것 같다.



비구조화 할당문을 사용할 수도 있다. #

위의 예시를 비구조화 할당문을 사용하여 작성할 수도 있다.

비구조화 할당문은 모든 지역 변수의 타입이 추론되도록 한다.

function logProduct(product: Product) {
    const {id, name, price} = product;

    console.log(id, name, price);
}



타입 선언이 꼭 필요한 경우도 있다. #

정보가 부족해서 타입스크립트가 스스로 타입을 판단하기 어려운 경우도 있다. 이럴 경우 타입을 선언해줘야 한다.

” 어떤 언어들은 매개변수의 최종 사용처까지 참고하여 타입을 추론하지만, 타입스크립트는 최종 사용처까지 고려하지 않습니다. “


이상적인 타입스크립트의 경우 아래와 같이 작성한다.

코드타입 구문 여부
함수/메서드 시그니처O

- 기본값이 설정되어 있는 경우, 생략 OK
- (타입 정보가 있는) 라이브러리, 콜백 함수의 시그니처, 생략 OK
함수 내에서 생성된 지역 변수X
// 예시 : 라이브러리, 콜백 함수의 시그니처, 생략 OK

app.get('/health', (request: express.Request, response: express.Response) => {
    response.send('OK');
})


app.get('/health', (request, response) => {
    response.send('OK');
})



타입 생략이 가능함에도, 타입을 명시하는 경우도 있다. #

1. 객체 리터럴

  • 타입 체크 ↑
  • 잉여 속성 체크
const elmo: Product = {
    name: '~',
    id: '~',
    price: 28.00,
};

2. 함수 반환

  • 타입 체크 ↑
  • 함수 이해도(입,출력 타입) ↑
  • 명명된 타입 사용 (= 직관적 표현)
function getQuote(ticker: string): Promise<number> {
    ...
}



no-inferrable-types #

이 옵션을 통해 작성된 모든 타입 구문이 정말로 필요한지 확인할 수 있다.



요약 & 정리 #

  1. 타입 추론이 가능하다면, 불필요한 타입 선언을 하지 않는 것을 권장한다.
  2. 타입 명시 비교 : 함수/메서드 시그니처 O <-> 지역변수 X
  3. 타입 명시 고려 대상 : 객체 리터럴, 함수 반환 O