(선언 시, 타입 파라미터만 적고) 생성 시점에 사용할 타입을 결정
<T>
기입해주지 않아도 TS는 전달되는 매개변수로 타입 파악함.
T
보통 T
사용 (다른 문자 무관)
어떤 타입을 전달받아서 해당 함수 등 에서 사용 가능하게 함.
사용하는 쪽에서 타입 결정
특정 타입으로 강제하고 싶을 경우 : <string | number>
사용 가능
매개 변수의 타입
ex) T[]
클래스나 함수, 인터페이스를 다양한 타입으로 재사용 가능
매개변수의 타입이 바뀌었는데 동일한 함수를 재사용하려면
→ 함수 오버로드 or 유니온 타입 사용 가능.
→ 다른 타입들을 배열로 만들어 전달할 때마다 계속 적어줘야 함.
이럴 때 제네릭이 효과적.
function getSize(arr: number[] | string[] | boolean[] | object[]): number { // 👈 파라미터 길어질 것
return arr.length;
}
const arr1 = [1,2,3];
getSize(arr1); // 3
const arr2 = ["a", "b", "c"]
getSize(arr2) // 3
const arr3 = [true, false, true]
getSize(arr3);
const arr4 = [{}, {}, { name: "Tim" }]
getSize(arr4);
function getSize<T>(arr: T[]): number { // 👈 타입 파라미터 & 매개 변수의 타입
return arr.length;
}
const arr1 = [1,2,3];
getSize<number>(arr1); // 3
// [T 부분 모두 number] function getSize<number>(arr: number[]): number
const arr2 = ["a", "b", "c"]
getSize<string | number>(arr2) // 3
// [특정 타입으로 강제]
const arr3 = [true, false, true]
getSize(arr3);
// [타입 파라미터 없어도 타입 파악] function getSize<boolean>(arr: boolean[]): number
const arr4 = [{}, {}, { name: "Tim" }]
getSize(arr4);
제네릭을 활용해서 하나의
interface
를 선언 후, 다양한 객체들 제작 가능
사용 가능한 모든 타입을 적는 것 → 비효율적
interface Mobile {
name: string;
price: number;
option: any;
}
// option에 어떤 데이터가 들어올지 모르는 상태. -> 이럴 때 제네릭 사용 가능
interface Mobile<T> {
name: string;
price: number;
option: T;
}
const m1: Mobile<{color: string; coupon: boolean}> = {
name: "s21",
price: 1000,
option: {
color: "red",
coupon: false,
}
}
/*
타입 파라미터
- <object>도 가능 (객체로 이루어져있기 때문)
- option 객체의 모습이 정해져있다면 위와 같이 사용 가능 */
const m2: Mobile<string> = {
name: "s20",
price: 900,
option: "good"
}
/*
타입 파라미터
- 없으면 에러
- option의 타입이 string이니까 string 사용 */
interface User {
name: string;
age: number;
}
interface Car {
name: string;
color: string;
}
interface Book {
price: number;
}
const user: User = {name: "a", age: 20};
const car: Car = {name: "bmw", color: "red"};
const book: Book = {price: 1000}; // 👈 name 無
function showName(data): string { // 👈 [에러 발생] 매개변수(data) 타입이 any.
return data.name; // 👈 book에 name 없어서 사용 불가.
}
showName(user);
showName(car);
showName(book);
(...생략)
function showName<T>(data: T): string { // 👈
return data.name;
/*
👆 name 에러 발생
이유: T에는 name이 없다.
(현재 전달되는 것(user나 car. name 有)만 보고
모든 매개변수에 name이 있다고 장담 불가. -> 에러 발생.) */
}
(...생략)
(...생략)
function showName<T extends {name: string}>(data: T): string { // 👈
return data.name;
}
showName(user);
showName(car);
showName(book); // 👈 book 에러 발생 (이유: name 없음)
<T extends {name: string}>(data: T)
의미
어떤 T 타입이 올건데 그 타입은 name
이 string
인 객체를 확장한 형태이다.
효과
다양한 객체가 와도 항상 name
은 string
을 가짐.
name
이 없거나 string
이 아니라면 → 에러 표시 (ex. showName(book)
에러)
name
의 타입이 다를 경우
interface User {
name: string;
age: number;
}
interface Car {
name: boolean; // 👈 boolean으로 바꿈
color: string;
}
interface Book {
price: number;
}
const user: User = {name: "a", age: 20};
const car: Car = {name: true, color: "red"}; // 👈 true로 바꿈
const book: Book = {price: 1000};
function showName<T extends {name: string}>(data: T): string {
return data.name;
}
showName(user);
showName(car); // 👈 car 에러 발생. 이유: string이 와야 함.
// showName(book);
참고