제품 품질 저하 없이 개발팀을 확장하는 방법
개발팀을 확장하고 계신가요? 제품 품질을 저하시키지 않고 성장하는 방법을 알아보세요. 이 가이드에서는 확장할 시기의 징후, 팀 구조, 채용, 리더십 및 도구와 더불어 The Codest가 어떻게...
제네릭은 단일 유형이 아닌 여러 유형에서 작동하는 재사용 가능한 코드 조각을 제공합니다. 제네릭은 함수 매개변수와 유사하게 유형을 변수로 취급하고 사용 시 이를 지정하는 방법을 제공합니다.
제네릭은 함수(제네릭 함수 생성), 클래스(제네릭 클래스 생성) 및 인터페이스(제네릭 인터페이스 생성)와 함께 사용할 수 있습니다.
제네릭의 가장 일반적인 용도는 배열을 선언하는 것인데, 이 사실을 모르고도 과거에 제네릭을 사용해 본 적이 있을 것입니다:
const myArray: 문자열[];
언뜻 보기에는 그리 특별하지 않습니다. myArray
를 문자열 배열로 사용할 수 있지만 일반 선언과 동일합니다:
const myArray: 배열;
아주 간단한 예제부터 시작하겠습니다. 이 바닐라 JS 함수를 TypeScript로 어떻게 이식할 수 있을까요?
함수 getPrefiledArray(filler, length) {
반환 (새로운 배열(길이)).채우기(필러);
}
이 함수는 주어진 양으로 채워진 배열을 반환합니다. 필러
따라서 길이
는 숫자
를 반환하고 전체 함수는 필러
- 하지만 필러란 무엇인가요? 이 시점에서 필러는 무엇이든 될 수 있으므로 한 가지 옵션은 다음을 사용하는 것입니다. any
:
함수 getPrefiledArray(filler: any, length: number): any[] {
반환 (새로운 배열(길이)).채우기(필러);
}
사용 any
는 확실히 일반적입니다 - 말 그대로 무엇이든 전달할 수 있으므로 정의에서 "단일 유형이 아닌 여러 유형으로 작업"은 완전히 다루지만 필러
유형과 반환 유형을 지정할 수 있습니다. 이 경우 어떤 공통된 것을 반환하고 싶고, 이 공통된 것을 명시적으로 다음과 같이 정의할 수 있습니다. 유형 매개변수:
함수 getPrefiledArray(필러: T, 길이: 숫자): T[] {
반환 (새로운 배열(길이)).채우기(필러);
}
를 클릭하고 이렇게 사용하세요:
const prefilledArray = getPrefiledArray(0, 10);
좀 더 일반적인 다른 경우를 살펴보겠습니다. 실제로 함수에 타입을 사용하는 이유는 무엇일까요? 저에게는 함수에 전달되는 인수가 상호작용하고자 하는 일부 속성을 갖도록 하기 위해서입니다.
다시 한 번 간단한 바닐라 JS 함수를 TS로 포팅해 보겠습니다.
함수 getLength(thing) {
return thing.length;
}
사소하지 않은 수수께끼가 하나 있습니다. 길이
속성으로 설정하는 것이 가장 먼저 떠오를 수 있습니다:
함수 getLength(thing: typeof Array):number {
return thing.length;
}
는 문맥에 따라 맞을 수도 있고, 전반적으로 약간 일반적입니다. 여러 유형의 배열에서 작동하지만, 사물이 항상 배열이어야 하는지, 축구장인지 바나나 껍질인지 알 수 없는 경우에는 어떻게 해야 할까요? 이 경우 사물의 공통 속성을 객체의 속성을 정의할 수 있는 구조체, 즉 인터페이스로 수집해야 합니다:
인터페이스 IThingWithLength {
길이: 숫자
}
다음을 사용할 수 있습니다. IThingWithLength
인터페이스의 유형으로 thing
매개변수입니다:
함수 getLength(thing: IThingWithLength):number {
return thing.length;
}
이 간단한 예제에서는 솔직히 말해서 완벽하게 괜찮을 것이지만, 이 유형을 일반적으로 유지하고 첫 번째 예제에서 발생한 문제에 직면하지 않으려면 일반 제약 조건:
함수 getLength(thing: T):number {
return thing.length;
}
를 클릭하고 사용하세요:
인터페이스 IBananaPeel {
두께: 숫자
길이: 숫자
}
const bananaPeel: IBananaPeel = {두께: 0.2, 길이: 3.14};
getLength(바나나껍질);
사용 확장
은 다음을 보장합니다. T
에 정의된 속성을 포함하게 됩니다. IThingWithLength
.
지금까지는 제네릭 함수로 작업했지만, 제네릭이 빛을 발하는 곳은 여기뿐만이 아니니 클래스에 어떻게 접목할 수 있는지 살펴봅시다.
먼저 바나나 바구니에 바나나 다발을 보관해 보겠습니다:
바나나 클래스 {
생성자(
public length: 숫자
public color: 문자열
public ionizingRadiation: 숫자
) {}
}
class BananaBasket {
private bananas: Banana[] = [];
add(banana: 바나나): void {
this.bananas.push(banana);
}
}
const bananaBasket = new BananaBasket();
bananaBasket.add(new Banana(3.14, 'red', 10e-7));
이제 같은 유형의 다른 물건에 대한 범용 바구니를 만들어 보겠습니다:
클래스 Basket {
사적인 것들: T[] = [];
add(thing: T): void {
this.stuff.push(thing);
}
}
const bananaBasket = new Basket();
마지막으로, 바구니가 방사성 물질 용기이고 다음과 같은 물질만 보관할 수 있다고 가정해 보겠습니다. 이온화방사선
속성입니다:
인터페이스 IRadioactive {
이온화 방사: 숫자;
}
RadioactiveContainer 클래스 {
비공개입니다: T[] = [];
add(thing: T): void {
this.stuff.push(thing);
}
}
마지막으로 일반 인터페이스를 사용하여 모든 지식을 모아 방사능 제국을 건설해 보겠습니다:
// 컨테이너에 대한 공통 속성 정의
인터페이스 IRadioactive {
이온화 방사: 숫자;
}
// 방사성 물질을 정의합니다.
인터페이스 IBanana extends IRadioactive {
길이: 숫자;
color: 문자열
}
// 방사능이 아닌 것을 정의합니다.
인터페이스 IDog {
weight: 숫자
}
// 방사성 물질만 담을 수 있는 컨테이너의 인터페이스를 정의합니다.
인터페이스 IRadioactiveContainer {
add(thing: T): void;
getRadioactivity():number;
}
// 방사성 컨테이너 인터페이스를 구현하는 클래스를 정의합니다.
class RadioactiveContainer 구현 IRadioactiveContainer {
비공개 물건: T[] = [];
add(thing: T): void {
this.stuff.push(thing);
}
getRadioactivity(): number {}
return this.stuff.reduce((a, b) => a + b.ionizingRadiation, 0)
}
}
// 오류! 'IDog' 유형이 'IRadioactive' 제약 조건을 만족하지 않습니다.
// 그리고 방사능 컨테이너 안에 개를 보관하는 것은 좀 잔인합니다.
const dogsContainer = 새로운 방사성 컨테이너();
// 모두 좋은 가족!
const radioactiveContainer = new RadioactiveContainer();
// 방사성 폐기물을 분류하는 것을 잊지 마세요 - 바나나만을 위한 별도의 빈을 만드세요.
const bananasContainer = new RadioactiveContainer();
여기까지입니다!