관리 메뉴

Jerry

[TIL] [타임어택9기][리뉴얼] 타입스크립트 올인원 : Part2. lib.es5.d.ts 분석- (11) : forEach, map 제네릭 분석 본문

Front/Typescript

[TIL] [타임어택9기][리뉴얼] 타입스크립트 올인원 : Part2. lib.es5.d.ts 분석- (11) : forEach, map 제네릭 분석

juicyjerry 2024. 2. 29. 01:11
반응형
forEach, map 제네릭 분석

 

 

 

 

 

어떻게 타입스크립트가 타입을 파악할 수 있을까? 프로그래밍에는 마법이 없다, 제네릭 덕분이다.

 

 

 

 

 

forEach

interface Array<T> {
    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
}
// type A<T> = 
// class A<T> {}

[1, 2, 3].forEach((item) => { console.log(item); }); // 1, 2, 3
['1', '2', '3'].forEach((item) => { console.log(item); }); // 1, 2, 3
[true, false, true].forEach((item) => { console.log(item); }); // 1, 2, 3

 

 

 

위치를 잘 파악해야한다
    callbackfn: (value: T, index: number, array: T[]) => void가 (item) => { console.log(item); }와 같고
    item이 value이다.
    <T>가 매개변수 value의 T와 일치하니 "1, 2, 3"와 item이 같을 수 밖에 없다

 

 

 

 

 value에 커서를 올려 추론된 value의 타입을 확인해보면, 입력한 값의 타입별 내용을 확인할 수 있다.

interface Array<T> {
    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
}
// type A<T> = 
// class A<T> {}

// interface에서 선언할 때는 모른다(<T>), 실행할 때 알 수 있다 -> <number> 라는 것으로 타입을 알 수 있다 -> 그러므로 제네릭으로 미리 엮어 놓는다.
// const a: number[] = [1, 2, 3];
const a: Array<number> = [1, 2, 3];
a.forEach((value) => { console.log(value); }); // 1, 2, 3

const b: Array<string> = [1, 2, 3];
['1', '2', '3'].forEach((value) => { console.log(value); }); // 1, 2, 3

const c: Array<boolean> = [1, 2, 3];
[true, false, true].forEach((value) => { console.log(value); }); // 1, 2, 3

const d: Array<boolean> = [1, 2, 3];
['123', 123, true].forEach((value) => { console.log(value); }); // 1, 2, 3

function add<T>(x: T, y: T) { return x; } // good
add<number>(1, 2); // 타입스크립트가 멍청해서 추론을 제대로 못 해줄 때, 직접 명시해주기도 한다
add('1', '2');
add(true, false);

// function add<T>(x: T, y: T) { return x; }에서 <T>: 제네릭, add<number>(1, 2);에서 <number>: 타입 파라미터, <number>add(1, 2);에서 <number>: 강제 변환 (위치 조심)
// 제네릭도 변환하면 사라짐


interface Array<T> {
    every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[];
}

 

-> S extends T : S는 T 타입에 속할 수 있어야 한다, T타입에 부분집합이여야 한다

 

 

 

 

 

map

interface Array<T> {
    // map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
    map<U>(callbackfn, thisArg): string[]; // 줄였을 경우, 중간에 매개변수 타입핑이 들어거 헷갈려 보이는 것이다
}

const strings = [1, 2, 3].map((item) => item.toString()); // ['1', '2', '3'] string[]

 

 

직접 타입을 넣어봐서 어떻게 추론되는지 확인할 수 있다
interface Array<number> {
    map<string>(callbackfn: (value: number, index: number, array: number[]) => string, thisArg?: any): string[];
}

 

 

 

 

반응형