제네릭
제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것
function getText(text: any): any {
return text;
}
getText('hi'); // 'hi'
getText(10); // 10
getText(true); // true
getText() 함수는 text라는 parameter를 넘겨받아 그대로 text를 반환한다
그래서 sting number boolean 어떤 값이 들어가도 그대로 반환이 가능함
=> 반환된 값이 어떤 타입인지 확인할 때 사용하는 것이 제네릭!
function getText<T>(text: T): T { // 제네릭 기본 문법 적용
return text;
}
getText<string>('hi');
getText<number>(10);
getText<boolean>(true);
// getText<string>('hi') 을 호출하면 T -> string이 할당되면서 아래와 같이 바뀜
// getText('hi')와 같이 < >을 생략해도 'hi'가 string이라 T -> string을 넘겨주게 된다
// function getText<string>(text: string): string {
// return text;
// }
제네릭은 보통 프로젝트 전반에 쓰이고 여러 타입을 넣을 수 있는 공통함수에서 많이 쓰인다
추가 예시
function getItemArray(arr: any[], index: number): any {
return arr[index];
}
function pushItemArray(arr: any[], item: any): void {
arr.push(item);
}
const techStack = ['js', 'react'];
const nums = [1, 2, 3, 4];
getItemArray(techStack, 0); // 'js' // teckStack 배열의 0번째
pushItemArray(techStack, 'ts'); // ['js', 'react', 'ts']
getItemArray(nums, 0); // 1
pushItemArray(nums, 5); // [1, 2, 3, 4, 5];
제네릭으로 바꾸기 ↓
function getItemArray<T>(arr: T[], index: number): T {
return arr[index];
}
function pushItemArray<T>(arr: T[], item: T): void {
arr.push(item);
}
const techStack = ['js', 'react']; // string[]
const nums = [1, 2, 3, 4]; // number[]
getItemArray(techStack, 0); // 'js'
pushItemArray<string>(techStack, 'ts'); // ['js', 'react', 'ts']
// pushItemArray<number>(techStack, 123); // Error
getItemArray(nums, 0); // 1
pushItemArray(nums, 5); // [1, 2, 3, 4, 5];
제네릭 타입 변수
function printOut<T>(input: T): T {
console.log(input.length); // Error: T doesn't have .length
return input;
}
input에 number를 넣으면 오류가 날 걸 알 수 있지만 typescript 입장에서는 T에 어떤 타입이 들어올 지 알 수 없기 때문에 .length 에 오류를 띄운다. 이런 경우 제네릭에 타입을 줄 수 있음 : T -> T[ ]
function printOut<T>(input: T[]): T[] {
console.log(input.length);
return input;
}
printOut([1, 2, 3]);
인자의 값으로 배열 형태의 T를 받는다는 뜻!
제네릭 제약 조건
function printOut<T>(input: T): T {
console.log(input.length); // Error: T doesn't have .length
return input;
}
에러 해결을 제네릭 타입변수가 아닌 제네릭 제약조건으로 해결하기 : 인터페이스 확장
interface LengthWise {
length: number;
}
function printOut<T extends LengthWise>(input: T): T { // T가 LengthWise라는 인터페이스를 확장
console.log(input.length);
return input;
}
// printOut(10); // Error, 숫자 타입에는 `length`가 존재하지 않으므로 오류 발생
// printOut({ length: 0, value: 'hi' }); // `input.length` 코드는 객체의 속성 접근과 같이 동작하므로 오류 없음
타입 추론
정적 타입 언어를 사용할 때 단점은 타입을 정의하는 데 시간과 노력이 많이 들기 때문에 생산성이 저하된다
typescript의 경우엔 다양한 경우에 대해 타입 추론을 제공해 주기 때문에 필요한 경우에만 타입을 정의할 수 있음
기본 타입 추론
let a = 123;
let b = 'abc';
a = 'abc'; // Error
b = 123; // Error
// 타입을 명시하지 않아도 자동으로 타입을 넣어주는 것을 타입추론이라고 한다
const c1 = 123; // c1의 타입은 number 가 아닌 123
// 123 -> number (O)
// number -> 123 (X) // 타입스크립트는 number의 범위를 좁혀서 c1의 타입을 123이라고 추론한 것
const c2 = 'abc'; // c2의 타입은 string이 아닌 'abc'
const arr = [1, 2, 3]; // const arr: number[]
const [n1, n2, n3] = arr; // const n1: number, const n2:number, const n3:number
arr.push('a'); // const arr: number[]로 arr의 타입추론을 했기 때문에 'a' 에 Error 발생
const obj = { numId: 1, stringId: '1' };
// const obj = { numId: number, stringId: string }; 으로 타입추론
const { numId, stringId } = obj; // const numId: number, const stringId: string으로 타입추론
console.log(numId === stringId); // Error 발생
let으로 선언한 변수는 재할당이 가능해서 어느 정도 융통성 있게 타입 추론이 되는데, const는 재할당이 불가능하다

그래서 const c1 = 123; 에서 c1의 타입은 123이고, const c2 = 'abc'; 에서 c2의 타입은 'abc'
함수 타입 추론
// function1 함수는 parameter a와 b에 각각 default parameter를 사용
const func1 = (a = 'a', b = 1) => {
return `${a} ${b};`; // const func1 = (a?: string, b?: number) => string
};
func1(3, 6); // Error // a는 string이기 때문에 3이 들어갈 수 없음
// 템플릿리터럴을 반환하기 때문에 반환값도 string으로 추론
const v1: number = func1('a', 1); // Error
// func1 함수는 string을 반환하기 때문에 v1은 number가 될 수 없다
func1에 마우스를 올려 보면 const func1 = (a?: string, b?: number) => string
값이 안 들어올 경우를 대비해서 자동으로 string optional parameter, number optional parameter로 추론
만약 a에 number타입을 넣고 싶다면 ↓
const func1 = (a: number|string = 'a', b = 1) => {
return `${a} ${b};`;
}
조건에 따라 number 또는 string 을 반환하는 예시
const func2 = (value: number) => {
if (value < 10) {
return value;
} else {
return `${value} is big`;
}
};
func2에 마우스를 올려 보면 const func2: (value: number) => string | number
반환 값이 number 또는 string이라고 추론
+ 시도해 볼 것
타입스크립트로 todolist 작성해 보기!
'스파르타 개발일지' 카테고리의 다른 글
| 20230211~12 api에 담긴 steam screenshot 정보를 불러올 수 없는 문제가 발생.. (0) | 2023.02.13 |
|---|---|
| 20230209 steam api 연결하는데 CORS 문제 발생.. (0) | 2023.02.09 |
| 20230117 타입스크립트 02 (0) | 2023.01.17 |
| 20230116 타입스크립트 01 (0) | 2023.01.16 |
| 20221229 리액트 네이티브 시작! (0) | 2022.12.29 |