언제 제네릭 타입이 한정되는가? 제네릭 타입의 선언 위치에 따라 타입의 범위뿐 아니라 TypeScript가 제네릭 타입을 언제 구체 타입으로 한정하는지도 결정됩니다. type Filter = (array: T[], f: (item: T) => boolean) => T[] let filter: Filter = (array, f) => { const result = [] for(let i = 0; i < array.length; i++){ const item = array[i] if(f(item)) { result.push(item) } } return result } 위의 예시에서 를 호출 시그니처의 일부로 선언했으므로 TypeScript는 Filter 타입의 함수를 실제 호출할 때 구체 타입을 T로 한정..
다형성 모든 타입은 구체 타입(concrete type)입니다. boolean string Date[] {a: number} | {b: string} (numbers: number[]) => number 기대하는 타입을 정확하게 알고 있고, 실제 이 타입이 전달되었는지 확인할 때는 구체 타입이 유용합니다. 하지만 때론 어떤 타입을 사용할지 미리 알 수 없는 상황이 있는데, 이런 상황에선 함수를 특정 타입으로 제한하기 어렵습니다. JavaScript로 filter를 이용하여 배열을 반복하면서 정제하는 코드를 아래처럼 구현할 수 있습니다. function filter(array, f){ let result = [] for(let i = 0; i < array.length; i++) { let item = a..
오버로드된 함수 타입 호출 시그니처에서 사용한 함수 타입 문법(type Fn = (...) => ...)은 단축형 호출 시그니처(shorthand call signature)입니다. 해당 호출 시그니처를 더욱 명확하게 표현할 수 있습니다. 다시 Log를 예로 살펴보겠습니다. // 단축형 호출 시그니처 type Log1 = (message: string, userName?: string) => void // 전체 호출 시그니처 type Log2 = { (message: string, userName?: string): void } 위의 두 코드는 문법만 조금 다를 뿐 모든 면에서 같습니다. 위의 Log 함수처럼 간단한 상황이라면 단축형을 활용하되 더 복잡한 함수라면 전체 시그니처를 사용하는 것이 좋을 때도..
문맥적 타입화(contextual typing) // 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로 지정했으므로 TypeScript가 message의 타입을 string으로 추론할 수 있기 때문입니다. 이는..