호출 시그니처
아래 코드의 sum은 함수이므로 sum은 Function 타입이라고 말할 수 있습니다.
function sum(a: number, b: number): number{
return a + b
}
Function은 사람들이 즐겨 사용하는 타입은 아닙니다.
object로 모든 객체를 가리킬 수 있는 것처럼 Function은 모든 함수의 타입을 뜻할 뿐이며 이것이 가리키는 특정 함수와 타입과 관련된 정보는 아무것도 알려주지 않습니다.
sum은 number를 인수로 받아 한 개의 number를 반환하는 함수입니다.
TypeScript에선 다음과 같이 표현할 수 있습니다.
(a: number, b: number) => number
이 코드는 타입스크립트의 함수 타입 문법으로, 호출 시그니처(call signature) 또는 타입 시그니처(type signature)라고 부릅니다.
이 문법은 화살표 함수와 아주 비슷하다는 점을 알 수 있는데, 이는 의도된 것이라고 합니다.
함수에 함수를 인수로 전달하거나 함수에서 다른 함수를 반환하는 경우, 이 문법으로 인수나 반환 함수의 타입을 지정할 수 있습니다.
a와 b라는 매개변수 명은 문서화 용도일 뿐 함수 타입과 할당 동작엔 아무런 영향을 주지 않습니다.
함수 호출 시그니처는 타입 수준 코드 즉, 값이 아닌 타입 정보만 포함합니다.
그래서 함수 호출 시그니처로 매개변수 타입, this 타입, 반환 타입, 나머지 타입, 조건부 타입을 표현할 순 있지만, 기본값은 표현할 수 없습니다.
함수 호출 시그니처는 바디를 포함하지 않아 TypeScript가 타입을 추론할 수 없으므로 반드시 반환 타입을 명시해야 합니다.
타입 수준 코드와 값 수준 코드
정적 타입 프로그래밍에서 사람들은 '타입 수준', '값 수준'이라는 용어를 자주 사용하는데, 이들은 공통 어휘입니다.
타입 수준 코드는 타입과 타입 연산자를 포함하는 코드를 의미하는 반면, 값 수준 코드는 그 밖의 모든 것을 가리킵니다.
어떠한 코드가 유효한 JavaScript 코드라면 값 수준이고, 유효한 JavaScript 코드는 아니지만 유효한 TypeScript 코드라면 타입 수준으로 쉽게 구분할 수 있습니다.
아래의 코드의 굵은 글씨는 타입 수준이고 나머지는 값 수준입니다.
타입 어노테이션과 유니온 타입 연산자(|)는 타입 수준이므로 굵게 표시했고 나머지는 모두 값 수준 용어입니다.
독립 호출 시그니처
다음으로 타입 별칭으로 한정할 수 있는 독립 호출 시그니처를 추출해 보겠습니다.
// say(name: string) 함수
type say = (name: string) => string
// log(message: string, userName?: string) 함수
type Log = (message: string, userName?: string) => void
// sumVariadicSafe(...numbers: number[]): number 함수
type sumVariadicSafe = (...numbers: number[]) => number
함수의 호출 시그니처는 구현 코드와 거의 같습니다.
언어 설계상 의도한 결정으로, 이렇게 함으로써 호출 시그니처를 쉽게 추론할 수 있습니다.
호출 시그니처가 주어졌을 때, 그 시그니처를 만족하는 함수는 간단하게 호출 시그니처와 함수 표현식을 합쳐서 구현할 수 있습니다.
// log(message: string, userName?: string) 함수
type Log = (message: string, userName?: string) => void
let log: Log = ( // ①
message, // ②
userName = '로그인 안했는데염...' // ③
) => { // ④
let time = new Date().toISOString()
console.log(time, message, userName)
}
① 함수 표현식 log를 선언하면서 Log 타입임을 명시했습니다.
② Log에서 message의 타입을 string으로 이미 명시했으므로 다시 지정할 필요는 없습니다. TypeScript가 Log를 통해 타입을 추론합니다.
③ userName에 기본값을 지정합니다. 호출 시그니처는 값을 포함할 수 없으므로 Log에선 userName의 타입은 지정할 수 있지만 기본값은 지정할 수 없기 때문입니다.
④ Log 타입에서 반환 타입을 void로 이미 지정했으므로 반환 타입은 다시 지정할 필요 없습니다.
'👶 TypeScript' 카테고리의 다른 글
오버로드된 함수 타입 (0) | 2023.01.12 |
---|---|
문맥적 타입화 (0) | 2023.01.12 |
반복자 (0) | 2023.01.11 |
제너레이터 함수 (0) | 2023.01.11 |
TypeScript 실행 (0) | 2023.01.11 |