개인공부/typescript

타입스크립트 : 제네릭 문법(함수, 클래스, 인터페이스)

minseokiim 2023. 9. 5. 19:20

* 제네릭 문법 - 함수

interface Obj{
 x:number
}
type Arr=[number, number]

//오버로딩
function toArray(a: string, b: string): string[]
function toArray(a: number, b: number): number[]
function toArray(a: boolean, b: boolean): boolean[]
function toArray(a: Obj, b: Obj): Obj[]
function toArray(a: Arr, b: Arr): Arr[]
function toArray(a: any, b: any){
 return [a,b]
}


console.log(
 toArray("k","kk"),
 toArray(1,2),
 toArray(true,false),
 toArray({x:1},{x:2}),
 toArray([1,2],[3,4])
)

-> 제네릭 문법으로 바꾸기

interface Obj{
 x:number
} //객체 데이터
type Arr=[number, number]

function toArray<T>(a: T, b: T){
 return [a,b]
}

console.log( 
 toArray("k","kk"),          //k가 들어가면서 a는 string타입이 됨, b도 string이 되어야 함 -> 타입 추론
 toArray<string>("k","kk"),  //명시적
 toArray(1,2),               //같은 맥락, a는 number타입이 됨, b도 number가 되어야 함
 toArray(true,false),
 toArray({x:1},{x:2}),       //Obj는 x속성만 가지고 있으므로 x만 들어올 수 있음
 toArray([1,2],[3,4,5])      //에러 안나는 이유, 따로 제네릭 타입 명시 안해서 첫번째 기준으로 타입추론하는데 튜플이 아닌 일반 배열로 인식함=>number[]
 toArray<Arr>([1,2],[3,4])   //이렇게 명시적으로 해줘야 위와 같이 쓰면 에러 남
)


 


* 제네릭 문법 - 클래스

class User{
 public payload
 constructor(payload){
  this.payload=payload      // 오류 해결하기, 매개변수 이름과 속성에서 사용하는 매개변수가 같고, 할당으로 시작하면 단순화 가능(매개변수에서 바로 초기화 가능)
 }
 getPayload(){
  return this.payload      
 }
}

-> 오류 해결

class User<P>{       //타입 변수 지정
 public payload:P
 constructor(payload:P){
  this.payload=payload     
 }
 getPayload(){
  return this.payload      
 }
}


-> 클래스에서 제네릭 문법 사용하기(매개변수에서 바로 속성을 지정하는 경우)

class User<P>{   //User 클래스가 생성자 함수로 호출 될때, 특정한 타입을 받아서 
 constructor(public payload:P){}  //그것을 payload라는 매개변수의 타입으로 지정, payload는 매개변수이면서 내부속성임
 getPayload(){
  return this.payload      
 }
}


interface UserAType{
 name: string
 age:number
 isValid:boolean
}

interface UserBType{
 name: string
 age:number
 emails:string[]
}

const min=new User<UserAType>({  //P가 UserAType의 인터페이스를 받음, 타입 제공
 name:"min",
 age:25,
 isValid:true
})

const kim=new User<UserBType>({
 name:"kim",
 AGE:20,
 emails:['@naver.com']
})

 



* 제네릭 문법 - 인터페이스, 제약 조건

ex 1.
interface MyData<T> {
 name:string
 value:T
}

const dataA: MyData<string>={    //MyData라는 인터페이스 타입, string타입 지정-> value로 들어감
 name:"data A", 
 value:"hello"
}

const dataB: MyData<number>={
 name:"data B",
 value:1234
}

const dataC: MyData<boolean>={
 name:"data C",
 value:true
}

const dataD: MyData<number[]>={
 name:"data D",
 value:[1,2,3,4]
}


ex 2. 제약 조건

interface MyData<T extends string | number> {   //타입 제약
 name:string
 value:T
}

const dataB: MyData<number>={
 name:"data B",
 value:1234
}

const dataC: MyData<boolean>={   //에러 남
 name:"data C",
 value:true
}