제네릭(Generic) 함수 : 모든타입을 다 적용할 수 있는 범용적인 함수
function func<T>(value: T): T { // T 타입변수
return value;
}
let num = func(10); // type : number
let bool = func(true); // type : boolen
let str = func("string"); // type : string
// 타입 변수에 할당할 타입을 직접 명시 -> number[] 타입으로 자동 추론 되기 때문에
let arr = func<[number, number, number]>([1, 2, 3]); // 튜플 타입
타입변수 T 선언, 함수를 호출할때 인수에 따라 타입이 결정
제네릭 함수 활용 예제
- 타입 변수가 2개 인 경우
function swap<T, U>(a: T, b: U) { //a= string, b=number type이 할당 되기때문에 타입변수를 따로 선언
return [b, a];
}
const [a, b] = swap("1", 2);
- 다양한 배열 타입을 인수로 받는 경우
function returnFirstValue<T>(data: T[]) {
return data[0]; // 타입변수를 아직 unknown으로 추론 -> [] 배열로 인식
}
let num = returnFirstValue([0, 1, 2]);
let str = returnFirstValue(["hello", "myname"]);
// 반환값의 타입 = 배열의 첫번째 요소의 타입
function returnFirstValue<T>(data: [T, ...unknown[]]) {// 튜플타입 T=number, 나머지는 unknown[]
return data[0];
}
let str = returnFirstValue([1, "hello", "myname"]);
- 타입변수를 제한하는 경우 (인수 값의 범위 제한) -> 확장(extends) 이용
function getLength<T extends { length: number }>(data: T) {
return data.length;
}
let var1 = getLength([1, 2, 3]);
let var2 = getLength("1234");
let var3 = getLength({ length: 10 });
let var4 = getLength(10); // ❌
- Map 메서드의 타입
const arr = [1, 2, 3]; // arr에 number 타입이 할당
//const newArr = arr.map((it) => it * 2); // [2,4,6] => JavaScript
function map<T, U>(arr: T[], callback: (item: T) => U) {
let result = [];
for (let i = 0; i < arr.length; i++) {
result.push(callback(arr[i]));
}
return result;
}
map(arr, (it) => it * 2);
map(["hi", "hello"], (it) => it.toUpperCase());
map(["hi", "hello"], (it) => parseInt(it));
원본배열과 다른타입의 배열로도 변환 가능 -> 타입변수 U 추가
- forEach
// forEach
const arr2 = [1, 2, 3];
//arr2.forEach((it) => console.log(it));
function forEach<T>(arr: T[], callback: (item: T) => void) { // 반환값이 없는 메서드
for (let i = 0; i < arr.length; i++) {
callback(arr[i]);
}
}
forEach(arr2, (it) => {
console.log(it.toFixed()); // number
});
forEach(["123", "456"], (it) => {
it; // string
});
- 제네릭 인터페이스
interface KeyPair<K, V> {
key: K;
value: V;
}
let keyPair: KeyPair<string, number> = {
key: "key",
value: 0,
};
let keyPair2: KeyPair<boolean, string[]> = {
key: true,
value: ["1"],
};
// ex
interface Student { // 서로소 유니온 타입
type: "student"; // String Literal 타입
school: string;
}
interface Developer { // 서로소 유니온 타입
type: "developer"; //String Literal 타입
skill: string;
}
interface User<T> {
name: string;
profile: T;
}
function goToSchool(user: User<Student>) {
// User<Student> 학생 유저만 인수로 전달하도록 제한
const school = user.profile.school;
console.log(`${school}로 등교 완료`);
}
const developerUser: User<Developer> = {
name: "정재현",
profile: {
type: "developer",
skill: "TypeScipt",
},
};
const studentUser: User<Student> = {
name: "박지성",
profile: {
type: "student",
school: "Nct Dream",
},
};
- 인덱스 시그니처
interface Map<V> {
[key: string]: V;
}
let stringMap: Map<string> = {
key: "value",
};
let booleanMap: Map<boolean> = {
key: true,
};
- 제네릭 타입 별칭
type Map2<V> = {
[key: string]: V;
};
let stringMap2: Map2<string> = {
key: "hello",
};
- 제네릭 클래스
class List<T> {
constructor(private list: T[]) {}
// 추가
push(data: T) {
this.list.push(data);
}
// 제거
pop() {
return this.list.pop();
}
print() {
console.log(this.list);
}
}
const numberList = new List([1, 2, 3]); // T[] = number[] 타입
numberList.pop(); // 1,2
numberList.push(4); // 1,2,4
numberList.print();
const stringList = new List(["1", "2"]); // T[] = stirng[] 타입
stringList.push("hello");
생성자를 통해 변수의 타입을 추론 -> 생성자에 타입 할당 생략 가능
- Promise : 제네릭 클래스를 기반으로 타입 선언, 비동기 작업의 결과값 기본으로 unknown 타입으로 추론, reject 타입은 정할 수 ❌ (any)
const promise = new Promise<number>((resolve, reject) => {
setTimeout(() => {
//resolve(20); // 성공 시 결과값
reject("~때문에 실패"); // any 타입
}, 3000);
});
promise.then((response) => {
console.log(response * 10);
});
promise.catch((err) => {
if (typeof err === "string") { // reject는 any만 가능 -> 타입 좁히기
console.log(err);
}
});
// ex
interface Post {
id: number;
title: string;
content: string;
}
function fetchPost(): Promise<Post> { //반환값 타입을 직접 명시
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
id: 1,
title: "게시글 제목",
content: "게시글 컨텐츠",
});
}, 3000);
});
}
const postRequest = fetchPost();
postRequest.then((post) => {
post.id;
});
'Front > typescript' 카테고리의 다른 글
조건부 타입 (0) | 2023.09.01 |
---|---|
타입 조작 (0) | 2023.08.25 |
클래스 Classes (0) | 2023.08.23 |
인터페이스 (0) | 2023.08.23 |
함수 타입 (0) | 2023.08.22 |