const names: Array<string> = [];
const names2: string[] = [];
names[0].split(' ');
names2.split(' '); // => 에러
function merge<T extends object, U>(objA:T, objB:U) {
return Object.assign(objA, objB);
}
const mergeObj = merge({name: '헬창', hobbies: ['개발']}, 30);
extends 키워드로 T 타입이 어느 타입이 와도 되지만 반드시 object를 상속받는 타입이어야한다고 제약조건을 주는 것이다.
그래서 위 코드는 컴파일 과정에서 이상없이 작동하지만 분명 의도한 바와는 다르게 작동할 것이다.
따라서 extends로 제약을 주는 것이다.
type Length = {
length: number;
}
function countAndDescribe<T extends Length>(element:T):[T, string] {
let descriptionText = 'Got no value.';
if(element.length===1){
descriptionText = 'Get 1 element';
} else if(element.length > 1) {
descriptionText = 'got' + element.length +'elements';
}
return [element, descriptionText]
}
console.log(countAndDescribe(['hi there', 'hello']));
type Length = {
length: number;
}
function countAndDescribe<T extends Length|string|number|boolean>(element:T):[T, string] {
...
만약 우리가 obj와 그에 해당하는 키값을 받아서 obj의 key에 대한 value를 뽑아내고 싶을 때 사용한다.
하지만 아래와 같이 사용하면 TS는 argument로 받은 key가 obj에 존재하는지 전혀 모른다.
그래서 존재하는 키워드가 바로 keyof이다. 이름 그대로 꽤나 직관적인 기능을 갖고있다.
function extractAndConvert<T extends object, U extends keyof T>(obj:T, key:U) {
return 'Value: ' + obj[key];
}
extractAndConvert({name:'정우'}, 'name');
class DataStorage<T> {
private data: T[] = [];
addItem(item: T) {
this.data.push(item);
}
removeItem(item: T) {
this.data.splice(this.data.indexOf(item), 1);
}
getItems() {
return [...this.data];
}
}
const objStorage = new DataStorage<object>();
objStorage.addItem({name: '헬창'})
objStorage.addItem({name: '개발자'})
objStorage.removeItem({name: '헬창'})
console.log(objStorage.getItems());
분명히 코드에서 헬창을 지웠는데 헬창만 남은 상황이다. 왜일까?
문제는 바로 this.data.indexOf가 같은 메모리를 참조하지 않다. 왜? => objStoreage의 addItem의 객체와 removeItem의 객체가 서로 다른 객체이기 때문이다.
그래서 같은 메모리를 참조하는 객체를 찾지 못 하고 -1을 반환하기 때문에 제일 뒤에서 첫번째 배열을 지운 것이다.
이는 저렇게 객체를 따로 선언할 것이 아니라 어떠한 변수 하나에 담아서 해당 변수를 돌려써야한다는 것이다.
?
로 바꿔주는 utility 제네릭 타입이다.type CourseGoal = {
title: string;
description: string;
completeUntil: Date;
}
function createCourseGoal(title:string, description:string, date:Date):CourseGoal {
let courseGoal:Partial<CourseGoal> = {};
courseGoal.title = title;
courseGoal.description = description;
courseGoal.completeUntil = date;
return courseGoal as CourseGoal;
}