프론트엔드 첫걸음

[기본 문법 배우기] lib.es5.d.ts 분석 본문

강의 노트/타입스크립트 올인원 : Part1. 기본 문법편

[기본 문법 배우기] lib.es5.d.ts 분석

차정 2025. 8. 11. 08:01

forEach, map 제네릭 분석

TypeScript의 Array<T>는 제네릭을 활용해 각 메서드의 매개변수 타입을 배열 요소 타입과 연결합니다.

interface Array<T> {
  forEach(callbackfn: (value: T, index: number, array: T[]) => void): void;

  map<U>(callbackfn: (value: T, index: number, array: T[]) => U): U[];
}
  • T : 배열 요소 타입
  • U : map 실행 결과 요소 타입 (콜백 반환값 타입)

예시:

[1, 2, 3].forEach((v) => console.log(v)); // v: number
const lengths = ["a", "bb"].map(s => s.length); // lengths: number[]

 

filter 제네릭 분석

filter는 타입 가드를 활용해 결과 배열의 타입을 좁힐 수 있습니다.

filter(
  predicate: (value: T, index: number, array: T[]) => value is S,
  thisArg?: any
): S[];
  • value is S → 타입 가드: 필터링 후 S[]로 결과 타입 변경

예시:

const arr = [1, "two", 3, "four"];

const numbers = arr.filter((x): x is number => typeof x === "number");
// numbers: number[]

 

forEach 타입 직접 만들기

내장 타입 안 쓰고 직접 정의:

type MyForEach = <T>(arr: T[], callback: (value: T, index: number, array: T[]) => void) => void;

const myForEach: MyForEach = (arr, callback) => {
  for (let i = 0; i < arr.length; i++) {
    callback(arr[i], i, arr);
  }
};

 

map 타입 직접 만들기

type MyMap = <T, U>(arr: T[], callback: (value: T, index: number, array: T[]) => U) => U[];

const myMap: MyMap = (arr, callback) => {
  const result: U[] = []; // Error → 제네릭 위치상 여기선 선언 불가, 함수 안에선 타입 추론 안 됨
  return arr.map(callback);
};

제네릭 <T, U>로 입력과 출력 타입을 연결.

 

filter 타입 직접 만들기

타입 가드 지원 버전:

type MyFilter = {
  <T>(arr: T[], callback: (value: T, index: number, array: T[]) => boolean): T[];
  <T, S extends T>(arr: T[], callback: (value: T, index: number, array: T[]) => value is S): S[];
};

const myFilter: MyFilter = (arr, callback) => {
  const result = [];
  for (let i = 0; i < arr.length; i++) {
    if (callback(arr[i], i, arr)) result.push(arr[i]);
  }
  return result;
};

 

공변성과 반공변성

  • 공변성(Covariance): 하위 타입을 상위 타입 자리에 넣는 게 허용됨 (예: 배열 요소)
  • 반공변성(Contravariance): 상위 타입을 하위 타입 자리에 넣는 게 허용됨 (예: 함수 매개변수)

예시:

type Animal = { name: string };
type Dog = { name: string; bark: () => void };

let animals: Animal[] = [];
let dogs: Dog[] = [];

animals = dogs; // 공변성 O
// dogs = animals; // Error

 

하나에는 걸리겠지 (오버로딩)

하나의 함수에 여러 타입 시그니처를 제공:

function getValue(x: number): string;
function getValue(x: string): number;
function getValue(x: any): any {
  return typeof x === "number" ? x.toString() : x.length;
}

getValue(10);    // string
getValue("hi");  // number

 

타입스크립트는 건망증이 심하다 (+에러 처리법)

TS는 런타임 값을 타입으로 기억하지 않음 → 변수 값은 변경 가능하므로 타입은 넓어짐.

let v = "hello"; // 타입: string (리터럴 "hello" 아님)

해결:

  • const 사용
  • as const로 리터럴 고정
  • 제네릭으로 값 타입을 캡처

예시:

const fixed = "hello"; // 타입: "hello"
const arr = [10, 20] as const; // 타입: readonly [10, 20]