class Department {
name: string // 필드의 타입 지정
private employees: string[] = [] // 외부에서 접근할 수 없도록 지정
constructor(n: string) { // 생성자 함수에도 마찬가지로 타입 지정
this.name = n
}
describe(this: Department) { // this로 무엇을 참조할지 매개변수에 넣음
console.log('Department : ', this.name) //메서드 생성
}
addEmplyee(employee: string) {
this.employees.push(employee)
}
}
// 클래스로 객체 생성
const accounting = new Department('accounting')
// 메서드 호출
accounting.describe()
// 해당 클래스 메서드 카피
const accountingCopy = { name: 'dummy', describe: accounting.describe } // 해당 메서드가 접근할 수 있게 this
accountingCopy.describe()
accounting.addEmplyee('max') // 메서드로 추가한다.
accounting.addEmplyee('manu')
accounting.employees[2] = 'anna' // private를 걸었으므로 외부에서 접근할 수 없다.
class Department {
// name: string // 필드의 타입 지정
// private employees: string[] = [] // 외부에서 접근할 수 없도록 지정
// 매개변수에 private, public을 활용하여 약식 초기화
constructor(private id: string, public name: string) {
// this.name = n
}
describe(this: Department) { // this로 무엇을 참조할지 매개변수에 넣음
console.log('Department : ', this.name) //메서드 생성
}
addEmplyee(employee: string) {
this.employees.push(employee)
}
}
const promise: Promise<string> = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('this is done')
}, 2000)
})
promise.then((res) => {console.log(res)}).catch((err) => console.log(err))
const merge = (objA: object, objB: object) => {
return Object.assign(objA, objB)
}
const mergedObj = merge({name: 'max'}, {age: 30})
// 객체로 저장한다 할지라도 해당 객체의 속성 값의 타입을 알지 못하기 때문에 불러오지 못한다.
console.log(mergedObj.name, mergedObj.age)
위와 같은 문제를 해결하기 위해 제네릭을 사용한다.
// 정확히 어떤 타입이 될지 모른다는 정보를 일단 함수를 정의할 때 타입스크립트에게 알려준다.
// 우선 제네릭을 입력하고 해당 파라미터가 제네릭이라고 선언해야한다.
function merge<T, U>(objA: T, objB: U) {
return Object.assign(objA, objB)
}
// 그리고 함수를 호출할 때 정확한 타입을 입력해준다.
const mergedObj = merge<{name: string, hobby: Array<string>}, {age: number}>({name: 'max', hobby: ['coding']}, {age: 30})
위의 경우 객체를 합치는 함수이나 객체가 아닌 다른 타입(문자열 또는 넘버 등등)이 와도 타입 에러 또는 js에러가 일어나지 않기 때문에 이를 방지하는 용도로 제네릭에 타입 제약을 걸어준다.
// 타입 제약을 걸어 제네릭의 타입에 제약을 걸어준다.
function merge<T extends object, U extends object>(objA: T, objB:U) {
return Object.assign(objA, objB)
}
// 객체에 해당하는 key가 있는지 보장할 수 없기 때문에 에러가 뜬다.
// 제네릭에 keyof 제약조건을 걸어준다.
function extractAndConvert<T extends object, U extends keyof T>(obj: T, key: U) {
return obj[key]
}
extractAndConvert({name: 'Max'}, 'name')
제네릭으로 클래스의 타입을 정의할 수 있다.
클래스로 작업을 수행할 때 한가지 타입으로만 국한되지 않도록 할 수 있으며 동시에 다음 타입들과 다른 타입이 들어오지 못하도록 할 수 있다.
class DataStorage<T extends string | number | boolean> {
private data: T[] = []
addItem(item: T) {
this.data.push(item)
}
removeItem(item: T) {
this.data.splice(this.data.indexOf(item), 1)
}
}
const stringDataStorage = new DataStorage<string>()
stringDataStorage.addItem('max')
stringDataStorage.removeItem('max')
const numberDataStorage = new DataStorage<number>()
numberDataStorage.addItem(20)
numberDataStorage.removeItem(20)