공부

타입스크립트(TS) (3)함수, 클래스, 제네릭

avocado8 2024. 1. 28. 16:58

 

함수

 

명시적 this

interface Whale {
  name: string
  age: number
}
const whale: Whale = {
  name: 'cado',
  age: 5
}
//명시적으로 this의 타입을 지정
function hello(this: Whale, message: string) {
  console.log(`Hello ${this.name}, ${message}`)
}
hello.call(whale, 'You are awesome')

this를 명시하지 않을 경우 암묵적으로 any 타입이 설정됨 (not good . . .)

 

 

오버로딩

각 타입별로 함수를 여러 개 만들지 않고도 타입 분기 가능

function add(a: string, b: string): string //add함수의 1번째 타입 선언
function add(a: number, b: number): number //add함수의 2번째 타입 선언
function add(a: any, b: any): any {
  return a + b
} //함수 구현 (타입선언X)
add('hello ', 'world') //'hello world'
add(1,2) //3
//add('hello ', 2)
//오류. a가 string이면 b도 string이어야 함

 


 

클래스

*접근 제어자(Access Modifiers)

속성, 메소드에서 사용가능

- public : 어디서나 자유롭게 접근 가능. 클래스 바디에서는 생략할 수 있음

- protected : 나와 파생된 후손 클래스 내에서 접근 가능

- private : 내 클래스에서만 접근 가능

class UserA {
  //this로 접근하는 속성 부분의 타입은
  //constructor함수 위쪽에 있는 body부분(중괄호 시작부터 끝까지)에
  //타입 명시 필요
  first: string = '' //초기화 가능
  last: string = ''
  age: number = 0
  constructor(first: string, last: string, age: number) {
    this.first = first
    this.last = last
    this.age = age
  }
  getAge() {
    return `${this.first} ${this.last} is ${this.age}`
  }
}
class UserA {
  //매개변수 부분에서 접근제어자를 명시하는 방법 (이때 public 생략은 불가)
  constructor(
    public first: string, 
    public last: string, 
    public age: number
  ) {
  }
  getAge() {
    return `${this.first} ${this.last} is ${this.age}`
  }
}

 


 

제네릭

1) 함수

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]
// }

//오버로딩 대신 제네릭 문법 사용
function toArray<T>(a: T, b: T) {
  return [a,b]
}

console.log (
  toArray('cado', 'avo'), //T는 string 타입
  toArray<string>('nana', 'khill'), //T를 직접 지정하는 것도 가능
  toArray(1, 2), //T는 number 타입
  toArray(true, false), //T는 boolean 타입
  toArray({ x: 1 }, { x: 2 }), //T는 Obj 타입
  toArray([1, 2], [3, 4]) //T는 Arr 타입
  toArray([1, 2], [3, 4, 5]) //T는 배열 타입 (number[]) (타입 추론)
)

 

 

2) 클래스

한 클래스를 사용할 때마다 다른 타입을 지정 가능

class User<P> {
  constructor (public payload: P) {}
  getPayload() {
    return this.payload
  }
}

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

const cado = new User<UserAType>({ //payload 타입이 UserAType
  name: 'Cado',
  age: 5,
  isValid: true
})
const nana = new User<UserBType>({ //payload 타입이 UserBType
  name: 'Nana',
  age: 4,
  emails: ['abc@gmail.com']
})

 

 

3) 인터페이스

interface MyData<T> {
  name: string
  value: T //value의 타입 지정 가능
}
const dataA: MyData<string> = {
  name: 'Data A',
  value: 'Hello world' //value는 string 타입
}
const dataB: MyData<number> = {
  name: 'Data B',
  value: 1234 //value는 number 타입
}

 

 

+) 제약 조건(Constraints)

제네릭 타입변수에 허용할 수 있는 타입을 제한 가능

interface MyData<T extends string | number> {
  name: string
  value: T //value의 타입은 string 또는 number만 가능
}
const dataC: MyData<boolean> = {
  name: 'Data C',
  value: false //허용되지 않음
}

 

 

 

+) tsconfig.json

{
  //컴파일러 옵션 지정
  "compilerOptions": {
    "target": "ES2015",
    "module": "ESNext",
    "moduleResolution": "Node",
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "strict": true,
  },
  //컴파일할 파일 경로 목록
  "include": [
    "src/**/*.ts"
  ],
  //컴파일에서 제외할 파일 경로 목록
  "exclude": [
    "node_modules"
  ]
}

 

compilerOptions

target : 컴파일될 ES(JS) 버전 명시

module : 모듈 시스템 지정 "CommonJS"(기본값) / "AMD" / "ESNext"(ESM방식)

moduleResolution : 모듈 해석 방식 지정 "Node"(기본값, index 이름 생략 가능)

esModuleInterop : ESM 모듈 방식 호환성 활성화 여부 false(기본값)

isolatedModules : 모든 파일을 모듈로 컴파일. false(기본값) true(import/export 키워드 필수)

baseUrl : 모듈 해석에 사용할 기준 경로 지정 "./"

typeRoots: 컴파일러가 참조할 타입선언(d.ts) 경로 지정. ["./node_modules/@types"]

lib: 컴파일에서 사용할 라이브러리 지정(배열). "ESNext", "DOM"

strict : 더 엄격한 타입 검사 활성화

strict true 사용시 아래 옵션도 true로 활성화됨

- noImplicitAny : 암시적 any 타입 검사 활성화

- noImplicitThis : 암시적 this 타입 검사 활성화

- strictNullChecks : 엄격한 Nullish 타입 검사 활성화

- strictFunctionTypes : 엄격한 함수의 매개변수 타입 검사 활성화

- strictPropertyInitialization : 엄격한 클래스의 속성 초기화 검사 활성화

- strictBindCallApply : 엄격한 bind, call, apply 메소드 인수검사 활성화