외거노비
외거노비 일지
외거노비

공지사항

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 분류 전체보기 (35)
    • 스파르타 프로젝트 (1)
      • 소개페이지(feat. 팀 외거노비) (1)
      • 프로젝트(미정)(feat. 팀 외래교란종) (0)
    • 스파르타 개발일지 (34)
hELLO · Designed By 정상우.
외거노비

외거노비 일지

20230118 타입스크립트 03
스파르타 개발일지

20230118 타입스크립트 03

2023. 1. 18. 21:15

제네릭

제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것

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
    '스파르타 개발일지' 카테고리의 다른 글
    • 20230211~12 api에 담긴 steam screenshot 정보를 불러올 수 없는 문제가 발생..
    • 20230209 steam api 연결하는데 CORS 문제 발생..
    • 20230117 타입스크립트 02
    • 20230116 타입스크립트 01

    티스토리툴바