Q1. 다음 함수를 제네릭을 사용하여 바꾸고 제네릭을 사용하여 좋은 점을 기술하시오.

function changetype(x : string) : string {
	return x;
}
function changetype(x : number) : number {
	return x;
}
function changetype(x : boolean) : boolean {
	return x;
}

<aside> 💡 정답

function changetype <T>(x : T) : T {
	return x;
}

함수 changetype 뒤에 <T>를 선언하고, 파라미터 x와 반환값을 T로 지정하여 어떤 타입이든 들어올 수 있도록 하였다. 제네릭을 사용하여 좋은 점은 위와 같이 changetype로 같은 함수인데 여러가지 타입을 사용해야할 때, 제네릭을 사용하면 타입을 변수처럼 사용할 수 있게 하여 범용적인 사용을 가능하게 해준다. 또한 함수와 컴포넌트의 재사용성을 증가할 수 있다.

</aside>

Q2. 제네릭 타입 코드 중에서 오류가 있는 것을 고르시오.

[1번]
interface GenericOutput1<T>{
    (input: T): T;
}
function output <T>(input: T): T{
    return input;
}

const myout1: GenericOutput1 = output;

[2번]
interface Robot<T> {
	name : string;
	property : T; 
}

const robot1 : Robot<{ skills : string}> = {
	name : '꼼꼼이',
	property : { skills : '청소하기' }, // 유연한 할당
};

[3번]
function SumArr<T>(arr: T): Number {
	let result = 0;
	for (let i = 0; i < arr.length; i++) {
		result += Number(arr[i]);
	}

	return result;
}

[4번]
class Bread<T> {
	name!: T;
	price!: T;
	getDiscountedPrice!: (price: T) => number;
}

let custardCream = new Bread<string>();
custardCream.name = "소보로빵";
custardCream.price = "5,000 원";
custardCream.getDiscountedPrice = (price) => parseInt(price) * 0.5;

<aside> 💡 정답

[1번]
interface GenericOutput1<T>{
    (input: T): T;
}
function output <T>(input: T): T{
    return input;
}

const myout1: GenericOutput1<number> = output;

[3번]
function SumArr<T>(arr: T[]): Number {
	let result = 0;
	for (let i = 0; i < arr.length; i++) {
		result += Number(arr[i]);
	}

	return result;
}

</aside>

Q3. 다음 코드에 대한 설명으로 옳은 설명을 고르시오.

//1번 코드 
<number> animal (a, b);

//2번 코드 
animal <number> (a, b);

// 보기
[1] 두 코드에는 차이가 없다. 
[2] 1번 코드의 형태는 제네릭, 2번 코드의 형태는 타입 단언이다. 
[3] 1번 코드는 타입을 강제로 지정한다. 

<aside> 💡 정답

<aside> 💡 제네릭 사용 시 타입 파라미터의 위치에 주의하여야 한다.

</aside>

정답은 3번이다. 타입 파라미터의 위치에 따라서 타입 단언, 제네릭이 될 수 있다.

코드 1번의 경우 타입을 강제 지정하는 타입 단언이고, 코드 2번의 경우 제네릭이다.

</aside>

Q4. 제네릭 함수에 대한 설명으로 옳지 않은 것을 고르시오.

// 보기
[1] 제네릭 함수에 매개변수가 주어진다면 
    굳이 타입을 명시하지 않아도 매개변수의 타입을 활용해 자동으로 유추된다. 
[2] '.tsx'란 JSX를 포함하고 있는 타입스크립트 파일이다. 
[3] 	function MoneyInput<T>(item: T) {
					return item.price + " 원";
			}
		위 코드의 경우 T에 price라는 프로퍼티가 있으므로 정상동작한다. 

<aside> 💡 정답

function MoneyInput<T>(item: T) {
					return item.price + " 원";
			}

정답은 3번이다. Tprice 라는 프로퍼티가 있는지 여부는 알 수 없다. 따라서 오류가 발생한다. 이 경우에는 extends 키워드를 사용해 해결할 수 있다. 타입 변수 T 를 확장하여price 프로퍼티를 가지고 있음을 명시한다.

function getPrice<T extends { price: number }>(item: T) {
	return item.price + " 원";
}

이렇게 해야 오류가 발생하지 않는다.

</aside>