[타입스크립트로 블록체인 만들기] #3. Functions

min5x5·2023년 9월 12일
post-thumbnail

#3.0 Call Signatures

Call Signature
우리가 타입스크립트에게 이 함수가 어떻게 호출되는지 설명해주는 부분이다.
parameter의 type는 무엇인지, function의 return type는 무엇인지 정의한다.

function add(a:number, b: number): number {
	return a+b;
}

const add = (a:number, b:number) => a+b;

type Add = (a:number, b:number) => number;
// 함수의 call signature 타입을 만든다.

const add:Add = (a, b) => a + b

#3.1 Overloading

overloading
'과적하다, 너무 많이 적재하다'라는 뜻이다.
메소드의 이름이 같고, 매겨변수 parameter의 개수나 타입이 다른 경우.
여러개의 call signatures가 있는 함수
함수가 여러개의 call signatures를 가지고 있을 때 발생시킨다.

// Bad Example, overloading 설명하기 위함.
type Add = {
	(a:number, b:number) : number
	(a:number, b:string) : number
}

const add:Add = (a, b) => {
	if(typeof b === 'string')	return a
    return a + b
}
// Example, Next.js에서 Router.push할 때 overloading 많이 발생함
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)
    } else {
    	console.log(config.path, config.state)
    }
}
// Example, parameter 갯수 다른 경우
type Add = {
	(a: number, b: number): number,
    (a: number, b: number, c: number): number,
}

const add: Add = (a, b, c?:number) => {
	if(c) return a + b + c
    return a + b
}

add(1, 2)
add(1, 2, 3)

3.2 Polymorphism

poly: many, several, many, multi
morphos: form, structure, shape
-> polymorphos: many diffrent structures/shapes

type SuperPrint = {
	(arr: number[]): void
    (arr: boolean[]): void
    (arr: string[]): void
}

const superPrint: SuperPrint = (arr) => {
	arr.forEach(i => console.log(i))
}

superPrint([1, 2, 3, 4])
superPrint([true, false, true])
superPrint(["a", "b", "c"])
superPrint([1, 2, true, false]) // 이건 안된다.

concrete type
string, number, void, object 등
generic type
타입스크립트에게 타입을 유추하도록 알려준다.
타입의 placeholder 같은거다.
call signature를 작성할 때, 함수에 들어올 확실한 타입을 모를 때 generic을 사용한다.<T>를 보통 사용한다.
타입스크립트는 placeholder에서 알아낸 타입으로 대체해준다.

// 함수의 call signature를 입력할 때, placeholder를 사용했다.
// 이게 polymorphism이다. superPrint는 다양한 shape를 가지고 있다.
type SuperPrint = {
	<TypePlaceholder>(arr: TypePlaceholder[]): TypePlaceholder
}
// 보통 <T>를 사용해 '<T>(arr: T[]): T'로 표현한다.
const superPrint: SuperPrint = (arr) => arr[0]

superPrint([1, 2, true, false])

3.3 Generics Recap

any를 사용하면 되는 거 아닌가?
아님. generic을 사용할 때, 타입스크립트가 이 함수의 call signature를 만들어주기 때문이다. generic은 내가 요구한대로 signature를 생성해줄 수 있는 도구이다.

generic을 하나 더 추가 하고 싶다면?

//ts는 generic을 처음 인식했을 때와 generic의 순서를 기반으로 generic의 type를 알게 된다.
type SuperPrint = {
	<T, M>(a: T[], b: M): T
}
const superPrint: SuperPrint = (arr) => arr[0]

superPrint([1, 2, true, false], "x")

3.4 Conclusions

generic을 사용해서 직접 call signature를 만들일은 거의 없다. 라이브러리를 만들거나, 다른 개발자가 사용할 기능을 개발하는 경우에는 유용하다.
nextJs, nestJS, reactJS를 사용하면, generic을 사용하게 될 거고, ts에게 generic을 보내게 될 거다. generic을 사용하는 call signature를 작성하게 될 거다.

function superPrint<V>(a: V[]){
	return a[0]
}
const a = superPrint<number>([1,2,3,4])

generic을 사용해서 타입의 재사용을 할 수 있다.

type Player<E> = {
	name: string
    extraInfo: E
}
type NicoExtra = {
	favFood: string
}
type NicoPlayer = Player<NicoExtra>

const nico: NicoPlayer = {
	name: 'nico',
    extraInfo: {
    	favFood: 'kimchi'
    }
}

const lynn: Player<null> = {
	name: "lynn",
    extraInfo: null
}

generics는 다양하게 많이 쓰인다.

const arr: Array<number> = [1,2,3,4]
useState<number()
profile
삶에 변화를 만드는 개발자

0개의 댓글