함수의 타입을 만들고 싶을 때 사용한다.
const add = (a : number, b : number) => a + b
위와 같이 선언된 함수가 있다고 했을 때, a와 b의 타입을 모두 선언해주고 있다. 위와 같은 변수의 사용이 많다면 Call Signatures를 지정하고 불러와 사용할 수 있다.
type Add = (a : number, b : number) => number;
const add : Add = (a, b) => a + b
함수를 선언하기전 타입을 만들고 함수가 어떻게 작동하는지 지정해 둘 수 있게 되는것이다.
함수가 여러개의 Call signatures를 가지고 있을 때 발생시킨다.
type Add = {
(a : number, b : number) : number
(a : number, b : string) : number
}
const add : Add = (a, b) => a + b // 오류 발생
b의 type이 string | number이기 때문에 에러가 발생하게 된다.
다른 예시를 통해 조금 더 살펴보자면,
type Config = {
path : string,
state : object
}
type Push = {
(path : string) : void
(config : Config) : void
}
const push : Push = (config) => {
if(typeof config === "string"){
console.log(config) // config라는 타입이 string이라는걸 알고 있다.
} else {
console.log(config.path, config.state) // config라는 타입이 Config이라는걸 알고 있다.
}
}
type으로 선언해준 Config가 객체의 형태이기 때문에 config.path, config.state로 접근이 가능하다.
여러개의 argument를 가지고 있을 경우
type Add = {
(a: number, b: number) : number
(a: number, b: number, c: number) : number
}
const add : Add = (a, b, c) => {
return a + b
}
위와 같은 예제를 살펴보면, c라는 매개변수는 현재 옵션과 같은 것이다. 즉, Add를 부를 때, a와 b를 부를 수도 있고, 또는 a, b, c,를 부를 수 있다. 결국 c는 옵션이라는 것이다.
그렇다면 옵션이라는 값을 어떻게 지정해두면 될까?
type Add = {
(a: number, b: number) : number
(a: number, b: number, c: number) : number
}
const add : Add = (a, b, c? : number) => {
return a + b
}
앞에서 배웠듯 "?"를 사용하여 optional하게 만들어주면 되겠다.
type SuperPrint = {
(arr :number[]) : void
}
const superPrint : Superprint = (arr) => {
arr.forEach(i => console.log(i))
}
call signature를 작성할 때 여기 들어올 확실한 타입을 모를 때, generic을 사용한다.
위와 같은 예제가 있다고 했을 경우, 타입에 상관없이 함수가 출력될 수 있도록 하려면 어떻게 해야할까?
현재 arr에는 number만 들어가서 출력이 아무거나(void)로 출력이 될 수 있도록 설정해 놓은 것이다. arr을 number인지, boolean인지 string인지 하나하나 지정해서 입력하는게 아닌 void처럼 선언할 수 없을까?
⇒ generic형식을 사용하면 된다.
generic이란 타입의 placeholder같은 것이다. TypeScript가 어떤 타입인지 알게 유추하도록 하는 것이다.
generic을 사용한다고 TypeScript에 선언만 하면 된다.
type SuperPrint = {
<TypePlaceholder>(arr : TypePlaceholder[]) : void
}
const superPrint : Superprint = (arr) => {
arr.forEach(i => console.log(i))
}
console.log(superPrint([1, 2, 3, 4])) // const superPrint : <number>(arr: number[]) => void
console.log(superPrint([false, true, false, false])) // const superPrint : <boolean>(arr: boolean[]) => void
console.log(superPrint([1, 2, false, ture])) // const superPrint : <number|boolean>(arr: (number|boolean)[]) => void
console.log(superPrint(["1", "2", true, 1])) // const superPrint : <number|boolean|string>(arr: (number|boolean|string)[]) => void
현재 위의 예제에서는 아무것도 리턴되지 않고 console.log만 찍어내고 있을 뿐이다. 만약, return 하는 값이 있다면 그 때의 값을 어떻게 generic하게 설정해주면 될까?
type SuperPrint = {
<TypePlaceholder>(arr : TypePlaceholder[]) : TypePlaceholder
}
const superPrint : Superprint = (arr) => arr[0]
console.log(superPrint([1, 2, 3, 4])) // const superPrint : <number>(arr: number[]) => number
console.log(superPrint([false, true, false, false])) // const superPrint : <boolean>(arr: boolean[]) => boolean
console.log(superPrint([1, 2, false, ture])) // const superPrint : <number|boolean>(arr: (number|boolean)[]) => number|boolean
console.log(superPrint(["1", "2", true, 1])) // const superPrint : <number|boolean|string>(arr: (number|boolean|string)[]) => number|boolean|string
간단하다. void 선언 대신에, return하는 값의 type을 generic으로 바꿔주면 되겠다.
위와 같이 설정해준 generic을 한 가지 뿐만아닌 여러가지를 사용하고 싶을 때는 어떻게 하면 될까?
type SuperPrint = {
<T, M>(a: T[], b :M) => T
}
const superPrint : SuperPrint = (arr) => arr[0]
console.log(superPrint([1, 2, 3])) // 에러 발생 TypeScript는 2개의 변수가 들어가도록 지정되어 있는데, 1개만 들어가있기 때문에.
console.log(superPrint([1, 2, 3], "x"))
간단하다. generic의 선언에 하나의 generic을 추가하여 선언해주면 되겠다.