[TS] TypeScript - 개요 & 타입

JH Cho·2022년 12월 12일
0

TypeScript

목록 보기
5/6

1. TS를 왜 사용할까?

  • JS는 동적 언어(dynamic language)이기 때문에 타입 지정을 하지 않아 안정성이 떨어진다.

  • TS는 타입 시스템을 제공하여 버그를 감소시키고 런타임 에러를 예방하며 생산성을 증가시킬 수 있다.

  • JS / TS 안정성 예시

1.console.log([1,2,3,4] + false) // 결과: 1,2,3,4false

2. function divide(a,b){
console.log(a/b);
}
divide('xxxx') // NaN
// JS는 인자가 하나만 들어가도 실행을 막지 않음.(안정성 감소)
// TS는 런타임 전에 미리 에러를 띄워서 실행을 막음(안정성 증가)

// 런타임 에러
const nico = { name : "nico"}

nico.hello() // Uncaugt TypeError : ~~ is not a function

// JS는 nico.hello()가 에러가 날 것을 예상못해서 그냥 실행시켰고 런타임 에러가 발생함.
// TS는 실행하기 전에 알려줌.

2. TS 개요

TS 작동 방식

  • TS는 강언어(Strongly type Language)이다.
  • TS언는 코드를 완료하고 나면 자바스크립트 파일로 컴파일(변환)된다.

그렇다면 결굴 JS파일로 변환되는데 어떻게 에러를 줄여서 개발자를 보호한다는 거지?

  • 브라우저는 TS를 읽지 못한다. 하지만 Node.js는 TS와 JS를 읽을 수 있다.
  • 그래서 TS가 제공하는 보호장치는 TS가 JS로 컴파일 되기 전에 작동할 수 있고
  • 보호장치는 TS 코드가 에러가 있는지 컴파일 전에 확인하여 에러가 없어야만 컴파일을 한다.
const nico = {
    nickname: "nick",
}

nico.hello();
// Error : 'hello' 프로퍼티는 nico 객체에 없다.

----------

[1,2,3,4] + false;
// Error : 연산자 + 는 배열과 불린 타입에는  적용불가

const nico = {
    nickname: "nick",
}

nico.hello();
// Error : 'hello' 프로퍼티는 nico 객체에 없다.

[1,2,3,4] + false;
// Error : 연산자 + 는 배열과 불린 타입에는  적용불가

TS는 개발자가 타입 지정을 하지 않아도 타입을 추론하여 타입 지정을 해준다.(JS는 위 코드처럼 짜도 에러 안띄움)

2.1_ Implicit Types vs Explicit Types

  • ts는 데이터와 변수의 타입을 명시적으로 정의할 수도, JS처럼 변수만 생성해도 된다. TS가 타입을 추론(infer)해주기 때문이다.
1. 타입을 추론하는 방법 Implicit(함축적인)
let a = "hello";
a= 'bye';
a = 1;

//Error in code : Type 'number' is not assignable to type 'string'.
JS에서는 위처럼 에러를 잡아내지 못한다.

2. 타입을 명시적으로 정의  Explicit(명시적인)
let b : boolean = "x"
//Type 'string' is not assignable to type 'boolean'.


let c = [1,2,3];
c.push("1");
//Argument of type 'string' is not assignable to parameter of type 'number'.

=> let c : number[] = []
명시적 표현은 TS가 타입추론을 하지 못할 때만 최소한으로 사용하는 것을 권장한다.

let c = []  => any 아무거나 집어 넣을 수 있음.

2.2_ Types of TS(기본)

기본 타입(primitive types)

let a : number = 1;
let b : string[] = "i1" // Error
let c :boolean[] = [true]

-----

const player: {
  name: string;
  age: number;
} = {
  name: 'nico',
};
/*Erro : Property 'age' is missing in type '{ name: string; }' 
but required in type '{ name: string; age: number; }'.*/

age?: number; 타입에 옵셔널 연산자를 추가해주면
age 프로퍼티가 있을 때 타입 체크를 하게 됨.

-------
 
 if(player.age < 10){}
// player.age is possibly 'undefined'

-> if(player.age && player.age < 10) {}
// 에러 해결

Union Type(타입 2개 이상 유동적으로 지정)

// Union 타입 - 타입 두개를 합친다.
let 회원: number | string |boolean= 123; // 타입 넘버
회원 = 'string'; // 타입 스트링
회원 = false;

let 회원들: (number | string)[] = [1, '2', 3];
let 오브젝트: {
  a: number | string;
} = { a: '123' };
오브젝트.a = 1;

퀴즈

  • 1번
let user = 'kim';
let age = undefined;
let married = false; 
let 철수 = [user, age, married];
  • 2번
let 학교 = {
    score : [100, 97, 84],
    teacher : 'Phil',
    friend : 'John'
}
학교.score[4] = false;
학교.friend = ['Lee' , 학교.teacher]

let user: string = 'kim';
let age: undefined | number = undefined;
let married: boolean = false;
let 철수: (string | number | undefined | boolean)[] = [user, age, married];

let 학교: {
  score: (number | false)[];
  teacher: string;
  friend: string | string[];
} = {
  score: [100, 97, 84],
  teacher: 'Phil',
  friend: 'John',
};
학교.score[4] = false;
학교.friend = ['Lee', 학교.teacher];

Alias Type(타입 재사용 가능)

  • 새로운 타입을 생성할 수 있다.
  • 타입 별칭이라고도 하며 대충 변수 선언해주는 거랑 비슷하다고 보면 됨.
  • Alias는 재정의가 불가능하다.
// 기존 방식
const playerNico : {
    name : string,
    age ?: number, // age : number | undefined 와 같음
} = {
    name  : "nico"
}

// Alias 방식
type Player = {
    name : string,
    age ?: number,
// "?"(optional type)의 경우 객체에 age 프로퍼티가 없을 때 에러 띄우는 것을 해결해주고
// 해당 프로퍼티가 있을 때만 type 체크를 해준다.
}

const Lynn : Player ={
    name: 'lynn',
    age : 10
}

  -------
  type Animal = string | number | undefined;

let 동물: Animal;
--------
type Age = number;
type Name = string;

type Player = {
    name : Name,
    age ?: Age,
}
  
--------
  

// 이런식으로도 가능하지만 너무 과하게 사용하는거라
//  코드가 복잡해보이니 지양하도록.

객체의 프로퍼티를 변경하지 못하게?

  • 객체를 상수에 할당해도 프로퍼티는 변경 가능( 기본이지 )
  • JS는 이걸 못막지만 TS는 가능하다.
type Girlfriend = {
  readonly name: string;
};

const 여친: Girlfriend = {
  name: '엠버',
};

여친.name = '뽀로'; // 에러

alias는 합치기도 가능

type Name = string;
type Age = number;
type Person = Name | Age;

& 기호로 obj Extend

  • 단 합치는 타입의 프로퍼티 키가 중복되면 에러뜸.
type PositionX = { x: number };
type PositionY = { y: number };

// { x: number,  y: number } 이런 타입 만들고 싶다.

type NewType = PositionX & PositionY;

let position: NewType = { x: 10, y: 10 };

함수 타입 지정

일반 함수

  • TS 함수의 매개변수는 무조건 타입 지정을 해줘야 한다.
type Player = {
    name: string,
    age?:number
}

function 함수이름(매개변수:타입지정):리턴타입지정{
  return 리턴타입인 값;
}

function playerMaker1(name:string):Player{
    return {
        name
    }
}
const nico = playerMaker1("nico")
nico.age = 12
//{ name: 'nico', age: 12 }
  • 파라미터를 옵션으로 두고 싶다?
function 함수(x?:number):void{ // 옵셔널 타입 사용하면 된다.
}

x?:number === x: number|undefined
  • 퀴즈 // 유니온 타입은 새로운 타입.
function 함수(x: number | string) {
  console.log(x + 3);
  // + 연산자는 넘버나 스트링 타입만 허용, 유니온은 허용 X
}

function 내함수(x? :number) :number { 
  return x * 2 
}

위와 같은 문제를 해결하는 것이 narrowing이라는 문법임.

function 함수(x:number|string):void{
  if(typeof x === 'number'){
    console.log(x + 3);
  }//내가 미리 조건으로 검사해서 타입을 확실히 해주면 에러 안남.
}

😽❓ 응용해보기

Q) 이름 들어올 때만 이름을 불러주고 없으면 없다고 콘솔
function 함수(name?: string): void {
  if (name) {
    console.log(name);
  } else {
    console.log('이름이 없수');
  }
}
Q) 숫자가 넘버든 스트링이든 들어오면 길이를 반환해라
function 함수2(value: number | string): number {
  return value.toString().length;
}
Q) 월소득은 만원당 1, 집보유는 500, 매력점수는 "상"일 때만 100점
총 600점 이상이면 통과 아니면 아무것도 반환 X
function 함수3(월소득: number, 집보유: boolean, 매력점수: string): string {
  return 월소득 + (집보유 && 500) + (매력점수 === '상' && 100) >= 600
    ? '결혼가능'
    : undefined;
}

화살표 함수


const fonc = (name:string) : Player  =>{
    return {
        name:name,
    }
}

const naco = fonc(1) // error

2.3_ Types of TS(2)

readonly

  • readonly는 최초 선언하면서 불변성(Immutability)를 부여한다.
  • TS에서 JS로 변환되지 않는다.
type Player = {
    readonly name:string,
    age?:number
}

const playerMaker = (name: string): Player => ({name})

const nico = playerMaker("nico")
🚫 nico.name = "aa"
//Cannot assign to 'name' because it is a read-only property.

--------
const numbers: readonly number[] = [1, 2, 3, 4]
🚫 numbers.push(1)

Tuple

  • array를 생성할 수 있게 함
    • 조건1. 최소한의 길이 가지기
    • 조건2. 특정 위치에 특정 타입이 있어야 함.
const playe = [string, number, boolean]
= ["Cho", 12, false];
player[0] = 1 // Error

  • readonly와 혼용 가능.
const player: readonly [string, number, boolean] = ["nico", 12, false];

any(default type)

  • TS의 보호장치를 가동시키고 싶지 않을 때
    (신중하게 사용하라)
const a: any[] = [1,2,3]
const b : any = true

a + b // 에러 발생 X

2.3 Types of TS(3)

unknown

  • any와 마찬가지로 모든 자료형 허용해줌 But any보다 안전하다.
let 이름: unknown = 'kim';
이름 = 123;
이름 = undefined;
이름 = [];

-------
 let 이름: unknown;

let 변수1: string = 이름;
let 변수2: boolean = 이름;
let 변수3: number = 이름;
// 다른 타입 변수에 할당하면 error 남.

  • 하지만 any 타입은 할당하는 변수의 TS 보호장치도 꺼버림

  • 타입 스크립트는 엄격!

  • 간단한 수학연산도 타입이 맞아야 하며, unknown은 number 타입이 아님.

let 이름: unknown;
이름 -1 // error

❓ 아래의 경우 왜 안되나

let 나이: string | number;
나이 + 1;
// + 연산자는 넘버나 스트링만 허용하는 것이기 때문
// 위와 같은 유니온 타입은 새로운 타입을 하나 만든 것이라서
// TS는 허용하지 않음.

let 나이: string;
나이 + 1; // 가능. -는 불가.
  • if - 연산자는? -는 넘버에만 가능. 따라서 TS에서도 넘버에만 허용


let a: unknown;

//예시1)
let b = a + 1; //에러

if (typeof a === 'number') {
  let b = a + 1; //해결
}

//예시2)
let b = a.toUpperCase();//에러

//해결
if (typeof a === 'string') {
  a.toUpperCase();
}

void

  • 아무것도 리턴하지 않는 함수 타입
  • TS는 함수가 아무것도 리턴하지 않으면 기본 타입으로
    void를 지정
function add(x:number):void{
  1 + 1;
  return; // 리턴 쓰면 에러 뜸.
}
-----------
function hello(){
    console.log('x')
} // hello 에 마우스 갖다대보면 hello() : void 라고 뜬다.

hello().toUpperCase() // return 값이 없으니 작동할리 없지.

never

function 함수():never{}
  • 함수에 붙이는 리턴 타입으로 사용 가능
    • 조건1) 절대 return을 하지 않아야 함
    • 조건2) 함수 실행이 끝나지 않아야 함.(endpoint가 없어야 함)
function 함수():never{
  while(true){
    console.log(123)
  }
}
  • 위와 같은 무한히 실행되는 코드를 가진
    함수에 붙일 수 있다.
function 함수():never{
  throw new Error('에러메시지')
}
  • 강제로 에러 띄우면 전체 코드 실행이 중단되니
    2번 조건을 나름 충족하는 것이라 사용가능.

  • 조건 1,2를 충족하는 함수를 만들고 싶을 때 never타입을 지정함

  • 근데 거의 쓸 일이 없다.

  • 걍 return 안하고 싶으면 void 쓰면 됨

  • 하지만 가끔 코드를 이상하게 짜면 자동으로 등장하기에

  • 이럴 때 never가 무엇을 의미하는지 이해만 하면 됨.

❓ 언제 등장함?

  • 파라미터가 never타입이 되는 경우
function 함수(parameter: string) {
  if ( typeof parameter === "string"){
    parameter + 1;
  } else {
    parameter;
  }
}
  • narrowing을 이용하여 파라미터의 타입이 string이면 무언가 해달라고 해놨음.
  • else를 써놨는데 string말고는 매개변수로 못들어 오는데 ...?
  • 이렇게 narrowing이 잘못 사용되면 파라미터 타입이 never로 변함.
  • never뜨면 코드 수정을 하면 됨
  • 자동으로 타입을 가지는 경우
function 함수(){
  throw new Error()
} // 함수 선언문
-
let 함수2 = function (){
  throw new Error()
} // 함수 표현식
  • 둘 다 아무것도 return 하고 있지 않음
  • 이 때 자동으로 return 타입이 선언문은 void, 표현식은 never가 지정됨.

🧨🙀 또한 tscoinfig.json 에서 strict 옵션을 켜두면
함부로 any 타입을 지정하지 못하게 한다.
이 때 array 등을 타입지정하지 않고 생성하면
원래는 any[] 이런식으로 되는데 any를 금지시켜놔서
never[] 로 지정이 되버림.

  • 결론 : 쓸 일이 별로 없으니 등장하면 뭔 일인가 잘 이해하세요.

  • 원시 타입
let 이름 :string = 'kim';
let 나이 :number = 20;
let 결혼했니 :boolean = false;
  • 배열 & 객체
let 회원들 :string[] = ["kim", "park"];

let 내정보 : { age : number } = { age : 20 }
  • 타입 변경을 잘못한다면?
let 이름 :string = 'kim';
이름 = 30;
//Type 'number' is not assignable to type 'string'.(2322)

😽 이런 에러는 TS 파일에서만 발생하고 변환된 js파일에서는 이상 없이 작동함.

  • 꿀 팁
let 이름 = 'kim';
let 나이 = 20;

이렇게 타입을 수동으로 지정하지 않아도 TS가 알아서 타입을 추론해서 지정해준다.

간단한 변수 타입들은 생략해도 됨.

추가 예시

var 좋아하는거 :{ song :string, singer :string } 
= { song : '사랑하기때문에', singer : '유재하' }


let project :{
  member : string[],
  days : number,
  started : boolean,
} = {
  member : ['kim', 'park'],
  days : 30,
  started : true,
}

타입확정(Narrrowing & Assertion)

  • Type이 하나로 확정되지 않았을 때 Narrowing을 사용한다

대표적 방법 typeof

  • 예시1)
    function 내함수(x: number | string) {
    	 if (typeof x === 'number') return x + 1;
    	 else return x;
    	}
  • 예시2)
    function 내함수(x: number | string) {
    	let array: number[] = [];
    	if (typeof x === 'number') array[0] = x;
     }
  • else 문도 넣어주면 더 안정적.
  • 인스턴스 instanceof 부모 / 속성명 in obj 등의 문법을 사용해도 됨.
  • Q) 적용 예시 배열 내 스트링을 숫자로 바꾸기.
    function convert(array: (number | string)[]): number[] {
     return array.map((v: number | string) => +v);
    }
    console.log(convert([1, '2', 3]));
  • Q2) 한 과목이면 그거 여러 과목이면 마지막 과목 없으면 없다
let 철수쌤 = { subject: 'math' };
let 영희쌤 = { subject: ['science', 'english'] };
let 민수쌤 = { subject: ['science', 'art', 'korean'] };
let 사짜 = { hello: 'hi' };
function lecture(x: { subject: string | string[] }): string {
  if (typeof x.subject === 'string') {
    return x.subject;
  } else if (Array.isArray(x.subject)) {
    return x.subject[x.subject.length - 1];
  } else {
    return '없다';
  }
}

console.log(lecture(사짜));


#### 대체 방법 Assertion
- narrowing 할 때 사용
- 얘도 any랑 비슷하게 TS의 보호장치를 꺼버림.
```js
function 내함수(x: number | string) {
  let array: number[] = [];
  array[0] = x as number; // 최신문법
  
  // 옛날 문법
  <string>x + 1;
}
  • 언제 쓰면 좋을까?

    • 왜 타입 에러가 나는지 정말 모르겠을 때 임시방편
    • 내가 어떤 타입이 들어올지 정말 확실히 아는데 컴파일러 에러가 발생할 때
  • 하지만 대부분 Narrowing으로 해결 가능하다.

  • 추가) 이럴 때도 유용하다

type Person = {
    name : string
}
function 변환기<T>(data: string): T {
    return JSON.parse(data) as T;
}
const jake = 변환기<Person>('{"name":"kim"}');

3. Functions

3.0 Call Signatures

함수의 인자 타입과 리턴하는 타입을 지정해두는 것을 ‘Call Signature’라고 한다.

type Add = (a:number, b:number) => number //Call signature

const add:Add = (a, b) => a + b

아래처럼 블록을 씌우고 return을 안 넣어준다면?

const add:Add = (a, b) => {a + b}
 // Type 'void' is not assignable to type 'number'.

type Add는 number를 return하는 타입인데 아무것도 return 하지않는 ‘void’타입 꼴이 되어서

위와 같은 Error가 발생함. a+b 앞에 return 넣어주면 error 해결 됨.

3.1 Overloading

  • 함수 Overloading
    type Add = (a:number, b:number) => number
    // 이런 Call Signature을 길게 쓰는 방법은 아래 코드와 같다.
    
    type Add = {
      // 인자타입 : 리턴타입
        (a:number, b:number) : number
        }
    // 이 방식은 Overloading을 위한 것이다.
  • 오버로딩은 하나의 타입에 서로 다른 여러개의 콜 시그니쳐를 지정하는 것을 말한다.
  • 오버로딩은 함수가 다른 타입의 인자를 받아들일 때 사용하면 된다.(아래 예시들 참고)
    type Add = {
        (a:number, b:number) : number
        (a:number, b:string) : number
    
        }
    

// 매개변수 a는 number b는 number | string
// 이 때는 아래처럼 narrowing 문법 사용하면 됨.
const add:Add = (a,b) => {
if(typeof b === "string") return a
return a+b;
}

```
  • 실제 라이브러리들에서 많이 보이는 형식
    type Config = {
        path:string
        state: object
    }
    
    type Push = {
        (path:string):void
        (obj:Config):void
    }
    
    const push:Push = (config) =>{
        if(typeof config === "string") console.log(config) // string
        else{
            console.log(config.path, config.state) // string, object
            }
    }
  • 다른 개수의 파라미터를 가지는 오버로딩
    //이 경우 c는 옵션임을 나타내는 오버로딩이다.
    type Add = {
        (a:number, b:number): number
        (a:number, b:number, c:number): number
    }
    
    const add:Add = (a,b,c) =>{
        return a + b
    }
    ----------------------------
    
    //옵션이니 ? 옵셔널을 붙여줘서 c 파라미터가 들어오면 number임을 지정해줘야 함.
    const add:Add = (a,b,c?:number) =>{
    		if(c) return a + b + c;
        return a + b 
    }
    
    add(1,2) //3
    add(1,2,3) // 6

3.2 Polymorphism

  • 폴리몰피즘?
    poly(여러개)morhism(structures) - 다형성
    ```tsx
    type SuperPrint = {
        (arr:number[]):void
        (arr:boolean[]):void
    }
    
    const superPrint: SuperPrint = (arr) =>{
        arr.forEach(i=>console.log(i))
    }
    
    superPrint([1,2,3,4])
    superPrint([true, false, true])
    superPrint(["a","b","c"]) 
    // <= 스트링 배열이 들어가야 한다면 (arr:string[]):void를 추가해야하는 것이 아니다.
    ```
    
    ---
    
    ```tsx
    // concreate type - number, string, boolean, unknown... 
    // generic type - 타입의 placeholder 같은 것.
    generic으로 placeholder와 같은 것을 추가해서 그게 무엇인지 추론해서 함수를 사용한다.
    
    type SuperPrint = {
        (arr:number[]):void
        (arr:boolean[]):void
        (arr:string[]):void  // 콘크리트 타입.
    
        (arr:(number|boolean)[]):void
    
    }
    
    const superPrint: SuperPrint = (arr) =>{
        arr.forEach(i=>console.log(i))
    }
    
    superPrint([1,2,3,4])
    superPrint([true, false, true])
    
    superPrint([1,2,true,'hello'])
    // generic type은 콜 시그니쳐를 작성할 때 시그니쳐에 들어올 확실한 타입을 모를 때 사용한다.
    
    type SuperPrint = {
        <Generic>(arr: Generic[]):void
        // 라이브러리에서 T, V를 많이 씀 아무거나 넣어도 ㄱㅊ
    }
    
    superPrint([1,2,true,'hello']) 함수에 커서 올려보면 TS가 타입 추론한 것 볼 수 있음.
    //const superPrint: <string | number | boolean>(arr: (string | number | boolean)[]) => void
    // 일일이 콜 시그니쳐를 추가하던 것을 TS가 대신 유추해준다는 것이다.
    ```
    
    ---
    
    ```tsx
    // Q) superPrint의 리턴 타입을 바꾸고 싶다면?
    type SuperPrint = {
        // (arr: number[]):number // X
        <TypePlaceholder>(arr: TypePlaceholder[]):TypePlaceholder // O
    }
    
    const superPrint: SuperPrint = (arr) => arr[0]
    
    const a = superPrint([1,2,3,4]) //const a: number
    const b =superPrint([true, false, true]) //const b: boolean
    
    const c = superPrint([1,2,true,'hello']) //const c: string | number | boolean
    ```
    
    👍🌼 `type SuperPrint = <t>(a: T[]) => T`  이렇게 쓰면 간단!!

3.3 Generics Recap

  • any와 generic의 차이가 뭔가요?
    type SuperPrint = (a: any[]) => any
    
    const superPrint: SuperPrint = (arr) => arr[0]
    
    const a = superPrint([1,2,3,4]) 
    const b =superPrint([true, false, true])
    const c = superPrint([1,2,true,'hello']) 
    에러가 뜨진 않는다 하지만!!
    c.toUpperCase() // Cannot read properties of undefined (reading 'toUpperCase')
    c는 arr[0] === 1 number가 할당되어 있기 때문에 **"코드 실행** 시" Error 발생.
    generic을 적용하면 TS가 알아서 타입 유추를 해주기 때문에 코드가 실행되기 전에 보호장치가 발동!
    Property 'toUpperCase' does not exist on type 'number'. 에러 띄운다.
  • genric을 복수로 사용하고 싶다?
    type SuperPrint = <T, M>(a: T[], b:M) => T
    
    const superPrint: SuperPrint = (arr) => arr[0]
    
    const a = superPrint([1,2,3,4], "x")   // T는 숫자배열, M은 스타링임을 유추함.
    const b =superPrint([true, false, true]) //error 인자 하나가 부족함.
    
    const c = superPrint([1,2,true,'hello']) //error

3.4 Conclusions

  • 제네릭 정의 '제네릭은 선언 시점이 아니라 생성 시점에 타입을 명시하여 하나의 타입만이 아닌 다양한 타입을 사용할 수 있도록 하는 기법이다.’
  • 직접 generic을 생성할 일이 많이 없다.
    ⇒ 다른 패키지, 라이브러리를 사용하면 그것들이 제너릭을 생성하고 우린 갖다 사용만 하면 됨.
    직접 패키지나 라이브러리를 만들 것이 아니라면 직접 생성할 일이 거의 없을 것이다.
  • 일반 함수로도 사용 가능
function superPrint<T>(a: T[]){
    return a[0]
}
const a = superPrint([1,2,3,4])

-------- overwrite도 됨

const a = superPrint<boolean>([1,2,3,4]) // error : boolean타입이라고 덮어씀

--------- 보호 못 받는 any 쓰지 말고
type Player<E> = {
    name:string
    extraInfo:E
}
  • generic으로 type 재사용도 가능해진다.
    type Player<E> = {
        name:string
        extraInfo:E
    }
    
    const lynn:Player<null> = {
        name: "lynn",
        extraInfo:null
    }
    
    // generic을 사용하면 타입 재사용이 가능해진다
    type NicoExtra = {
        favFood : string
    }
    type NicoPlayer = Player<NicoExtra>
    
    const nico:NicoPlayer = {
        name:"nico",
        extraInfo:{
            favFood:"kimchi"
        }
    }
  • 대부분의 기본적 타입스크립트 타입은 제너릭으로 만들어져 있다!
    type A = Array<number>  // 기본 타입 Array에 number 덮어쓰기.
    
    let a:A = [1,2,3,4]
    
    function printAllNums(arr: Array<number>){}
  • Reactjs의 useState()
useState<number>() // 제네릭을 보내면 number 타입의 useState가 되는 것.
profile
주먹구구식은 버리고 Why & How를 고민하며 프로그래밍 하는 개발자가 되자!

0개의 댓글