// 파라미터 두 개가 모두 Object 타입이니 함수 리턴값도 object일 거라 추론한다.
function merge(objA: object, objB: object) {
return Object.assign(objA, objB);
}
const mergedObj = merge({ name: "Max" }, { age: 30 });
// object 타입은 모든 타입을 할당할 수 있으므로 ts는 각 프로퍼티가 어떤 타입인지 알 수 없어 에러가 난다.
console.log(mergedObj.age);
▽▽▽
function merge<T, U>(objA: T, objB: U) { // return 타입은 T & U
return Object.assign(objA, objB);
}
// 함수를 호출할 때 구체적인 타입을 지정해줘도 된다.
const mergedObj = merge<{name: string}, {age:number}>({ name: "Max" }, { age: 30 });
console.log(mergedObj.age); // 에러 발생 X
/*----- 예시 1 -----*/
function merge<T extends object, U extends object>(objA: T, objB: U) {
return Object.assign(objA, objB); // 객체를 병합하는 메소드이기 때문에 최소한 둘다 객체여야한다.
}
const mergedObj = merge({ name: "Max" }, 30); // 30은 object 타입이 아니라고 에러 난다.
console.log(mergedObj);
/*----- 예시 2 -----*/
interface Lengthy {
length: number;
}
// length 속성을 가진 타입만 할당할 수 있다.
function countAndDescription<T extends Lengthy>(element: T): [T, string] {
let description = "Got no value";
if (element.length > 0) {
description = `Got ${element.length} value(s)`;
}
return [element, description];
}
console.log(countAndDescription("Hi!")); // ['Hi!', 'Got 3 value(s)']
console.log(countAndDescription([])); // [Array(0), 'Got no value']
// console.log(countAndDescription(100)); // length 속성이 없는 타입이므로 에러가 난다.
function extractAndConvert(obj: object, key: string){
return obj[key]; // object가 key값을 갖고있는지 아닌지 알 수 없다고 에러가 난다.
}
▽▽▽
function extractAndConvert<T extends object, U extends keyof T>(
obj: T,
key: U
) {
return obj[key];
}
// extractAndConvert({}, name); // 이제 함수 내 리턴이 아니라 여기서 에러가 난다.
console.log(extractAndConvert({ name: "Max" }, "name")); // Max
class DataStorage<T> {
private data: T[] = [];
addItem(item: T) {
this.data.push(item);
}
removeItem(item: T) {
this.data.splice(this.data.indexOf(item), 1);
}
getItem() {
return [...this.data];
}
}
const textStorage = new DataStorage<string>();
textStorage.addItem("Max");
textStorage.addItem("Anna");
textStorage.addItem("Sue");
textStorage.removeItem("Anna");
console.log(textStorage.getItem()); // ['Max', 'Sue']
class DataStorage<T> {
private data: T[] = [];
addItem(item: T) {
this.data.push(item);
}
removeItem(item: T) {
this.data.splice(this.data.indexOf(item), 1);
}
getItem() {
return [...this.data];
}
}
const textStorage = new DataStorage<object>();
textStorage.addItem({ name: "Max" });
textStorage.addItem({ name: "Anna" });
textStorage.addItem({ name: "Sue" });
textStorage.removeItem({ name: "Anna" });
console.log(textStorage.getItem()); // 0: {name: 'Max'}, 1: {name: 'Anna'}
// addItem의 Anna 객체와 removeItem의 Anna객체는 같아 보이지만 다른 주소를 갖고있는 다른 값이다.
// 따라서 indexOf() 메소드가 같은 값을 찾지 못하기 때문에 -1 값을 리턴하고 마지막 요소가 사라진 것이다.
▽▽▽
class DataStorage<T> {
private data: T[] = [];
addItem(item: T) {
this.data.push(item);
}
removeItem(item: T) {
this.data.splice(this.data.indexOf(item), 1);
}
getItem() {
return [...this.data];
}
}
const textStorage = new DataStorage<object>();
textStorage.addItem({ name: "Max" });
const AnnaObj = { name: "Anna" };
textStorage.addItem(AnnaObj); // 같은 주소를 인지할 수 있게끔 변수에 할당한다.
textStorage.addItem({ name: "Sue" });
textStorage.removeItem(AnnaObj);
console.log(textStorage.getItem()); // 0: {name: 'Max'}, 1: {name: 'Sue'}
: 제네릭 타입을 사용하는 내장 타입
생성된 타입의 모든 프로퍼티를 옵셔널로 만든다.
interface CourseGoal {
title: string;
description: string;
completeUntil: Date;
}
function createCourseGoal(
title: string,
description: string,
date: Date
): CourseGoal {
let courseGoal: CourseGoal = {}; // 있어야 할 프로퍼티가 없다고 에러난다.
courseGoal.title = title;
courseGoal.description = description;
courseGoal.completeUntil = date;
}
▽▽▽
interface 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;
// Partial<CourseGoal>과 CourseGoal은 다르므로 리턴 값은 CourseGoal로 지정해준다.
return courseGoal as CourseGoal;
}
const names: Readonly<string[]> = ["Max", "Anna"];
// names.push("Sue"); // readonly라고 에러가 난다.