리팩터링 내성을 키우는 lint, explicit-function-return-type
https://typescript-eslint.io/rules/explicit-function-return-type/
해당 lint는 다음과 같은 케이스에서 모두 오류, 경고를 발생합니다
// 함수에서도 void를 선언해야함
function test() {
return;
}
// 변수에 할당하는 함수에도 number를 선언해야함
var fn = function () {
return 1;
};
// 애로우펑션에서도 string을 선언해야함
var arrowFn = () => 'test';
class Test {
// 클래스 메서드에서도 void를 선언해야함
method() {
return;
}
}
그야말로 모든 함수를 정의하는 곳에서는 리턴타입을 반드시 명시해야합니다
왜 그래야할까요?
typescript는 암묵적으로 리턴타입을 똑똑하게 계산합니다
그래서 귀찮다는 이유로 리턴타입을 적지 않는 경우가 종종 있습니다
하지만 리턴타입이 없다면 함수 내부 로직이 변경되었을때 리턴타입이 함께 변경되는 문제가 발생합니다
// number를 리턴함
function getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
number를 리턴하는 함수를 만들었습니다 암묵적으로 number 타입이 리턴되는것을 typescript는 눈치챌수 있습니다
// number | null 을 리턴함
function getRandomInt(max: number) {
if (max < 0) {
return null;
}
return Math.floor(Math.random() * max);
}
함수 내부의 로직이 변경되었습니다
함수 내부의 로직이 변경되었을 뿐인데 의도하였든 의도하지 않았든 리턴타입이 변경되어서
해당 함수를 사용하는 다른 모든 함수들이 null의 위험에 노출되었습니다
해당 코드의 테스트코드도 작성되었다면 테스트코드도 불안정해졌습니다
이는 리팩터링 내성을 해칩니다
우리는 리팩터링을 할때 우리가 안전하게 리팩터링을 했다는 것은 input, output이 같다는 테스트를 통해서 증명합니다
하지만 로직이 변경되었는데 output이 변경되었다는 것은 리팩터링이 아니라 변경을 시도했다는 것이고,
이는 다른 불안한 요소를 불러오게 됩니다
더 복잡한 함수의 경우 본인 스스로도 리턴타입을 바꾸었는지 눈치채지 못할수도 있습니다
만약 리턴타입이 명시적이었다면 본인이 함수 내부를 수정했을때 리턴타입이 달라진 경우 컴파일단에서라도 에러를 만났을것입니다
lint를 통해서 이 규약을 지킬수 있게 도와줍니다