개념공부를 하다가 타입스크립트의 void가 명확하게 이해가 되지 않아 정리해보았다.
1. void
1) 정의
void는 값을 반환하지 않는 함수의 반환 값을 의미한다. 함수에 return 문에 없거나, 명시적으로 값을 반환하지 않을 때, 추론되는 타입이다.
위 정의에서도 보았듯이 우리가 타입스크립트에서 함수를 작성하고 return을 하지 않는다면 알아서 void로 추론을 한다. 그리고 그러한 함수들의 반환 값은 undefined로 평가된다. 자바스크립트에서는 아무것도 반환하지 않는 함수는 암묵적으로 undefined 값을 반환한다. 하지만 타입스크립트에서 void와 undefined는 같은 것으로 간주되지 않는다.
그렇다면 실제로 해보자 타입스크립트에서 void함수를 undefined 타입으로 지정한 변수에 할당하면 어떻게 될까?
분명 반환된 값은 undefined인데 void 타입은 undefined에 할당할 수 없다고 한다. 그렇다면 void와 undefined는 차이가 있다는 소리다.
2. void vs undefined
1) void 타입의 표현식은 truthiness를 테스트할 수 없다.
void 함수의 결과값의 truthiness를 검증하는 경우 위의 에러 메시지가 출력된다.
undefined는 truthiness를 검증할 수 있다.
2) Substitutability
void를 반환하는 Contextual 함수 타이핑(식의 한변에만 타입을 지정하는것)은 함수에게 아무것도 반환하지 않을 것을 강제하지 않는다. 실제로도 아래 f1, f2, f3와 같이 값을 반환해도 아무런 타입 에러가 발생하지 않는다.
이는 참 신기하고 이해가 가지 않는 동작이다. 아래 코드를 보자.
전혀 오류가 발생하지 않는다. 그리고 정상적으로 동작한다 하지만 함수의 타입은 void로 여전하다. 변수에 할당해도 타입은 void로 유지된다.
여기서 조금 더 나아가보자
타입스크립트에서는 non-void를 return 함수를 void를 reutrn하는 함수에 할당할 수 있다.
엥??? 무슨소리인가 하겠지만 사실이다. (링크)
return 타입이 void일 때 contextual 타입화를 사용하면 함수가 반환값을 강제적으로 제거하지 않는다.
쉽게말해 타입스크립트가 아무런 제제를 하지 않고 그대로 void 타입이 아닌 값을 return 한다. (위 예제처럼 true를 return 함)
이렇게 return 타입이 void이지만 그것을 무시한다 할지라도 함수 구현은 유효하다.
따라서 return 타입이 void인 함수를 변수에 할당하면 여전히 그 변수는 타입이 void 이다.
이것은 타입스크립트 공식 문서에서도 의도된 설계라고 한다.
여기서 void일 때 에러가 나게 할려면 contextual만 해서는 안된다.
이렇게 오른쪽도 같이 void로 해줘야 오류가 발생하지 않는다.
조금 더 알아보자
Why are functions returning non-void assignable to function returning void?
아래 예제를 보자.
이런식으로 callMeMaybe 함수의 인수는 return 타입이 void인 함수만 받지만 자세히보면 'doSomething' 함수를 아무런 오류 없이 받고 있다. 이는 substitutability 원칙으로 이렇게 허용되는 것이다.
공식문서에서는 doSomething 함수의 반환 값인 숫자는 callMeMaybe 함수에서 요구하는 반환 값인 void보다 더 많은 정보를 가지고 있기 때문에 타입스크립트가 이러한 경우 타입 오류가 발생하지 않도록 처리한다고 한다.
신기한 것은 retrun callback()을 해도 여전히 오류없이 작동한다.
이 부분에 대해서는 더 공부가 필요하다.
3) Generic Return Type
반환값이나 인자에서 제네릭을 사용해 타이핑하는 경우 void는 아무 것도 반환하지 않거나 주어지지 않음을 나타낼 때 유용하다.
위 예제의 두 비동기 함수를 보면, promiseReturnsResponse은 정상작동을, promiseReturnsNothing은 void이기 때문에
retrun을 할려고 하는 경우 에러가 발생한다.
4) Interface Property Return
interface만 보더라도 어떤 함수가 반환값이 없는지 단 번에 알 수 있다.
setOpen 함수는 state를 변동만 시키고 어떠한 값도 return하지 않는 함수라는 것을 바로 알 수 있다.
결론
1. void 함수의 결과값의 truthiness가 불가능하다. (Substitutability가 적용되어도 타입은 void라서 retrun값이 있더라도 불가능하다)
2. void는 때론 코드를 이해하는 데 도움을 준다.
3. Substitutability 때문에 void 사용을 조심하자
source
https://www.typescriptlang.org/ko/docs/handbook/2/functions.html#void
https://betterprogramming.pub/what-is-void-in-typescript-2d21d4936537
'Typescript > 개념' 카테고리의 다른 글
[TypeScript] Classes (0) | 2023.02.16 |
---|---|
[TypeScript] generics (0) | 2023.02.15 |
[Typescript] 3. Polymorphism / generics (0) | 2023.01.19 |
[Typescript] declare (0) | 2022.12.28 |
[Typescript] 4. Class and Interfaces (1) | 2022.09.27 |