2023 August TIL
in TIL / 2023
at least 30 minutes per day
8/7: Generics
계절학기 시험 끝나고 너무 헤이해졌다…클린코드 (Java 기반) 읽기 전 Generics에 대해 제대로 공부해야겠다 싶었는데 계속 미뤄져서 월요일인 오늘부터 다시 시작! 사실 타입스크립트로 모든 프로젝트를 하지만 너무 기본기 없이 시작한 탓에 잘 모르고 사용하는 것 같다. 제대로 공부해서 알고 써야지…
Generic이란?
클래스/함수에서 사용할 타입을 그 클래스/함수를 사용할 때 결정하는 프로그래밍 기법
- 정적 타입 언어들 (Java, C++, TS) 는 클래스/함수 선언 시점에서 IO 타입을 정의 \(\rightarrow\) 특정 타입을 위해 만들어졌기 떄문에 다른 타입을 위해 재사용 불가
- 하지만 Generics 사용 시 클래스/함수의 범용적인 사용 가능
- any와 다르게 type 정보가 동적으로 결정됨
- 이해를 돕기 위한 예시: Stack 자료구조 구현
class Stack { private data: any[] = []; contructor() {} push(item: any): void { this.data.push(item); } pop(): any { return this.data.pop(); } }
any
사용 \(\rightarrow\) 자료의 타입이 모두 같지 않으므로 런타임에서 항상 타입 검사 필요- 그렇다고
number
같은 타입 정의 시 범용성이 떨어짐 - 상속으로 처리 가능하지만 자료형 하나 추가 할때마다 중복 코드 작성해야 함 (번거로움)
- 타입 추론 역시 가능하나 명시적인 타입 인수 전달 필요할 때 Generics 사용
문법 <T>
CLASS
- Generic을 사용하겠따는 의미로 <꺽쇠> 안에 Type으로 사용되는 식별자 집어넣기 꺽쇠>
class Stack<T> { private data: T[] = []; constructor() {} push(item: T): void { this.data.push(item); } pop(): T { return this.data.pop(); } }
- T: Type의 약자, Type variable (식별자로 사용되는 것 다 가능)
const numberStack = new Stack<number>(); const stringStack = new Stack<string>(); numberStack.push(1); stringStack.push('a');
- 컴파일러가 return type 알 수 있음 && 에디터에서 자동완성 도와줌!
- BUT 컴파일 단계에서 검사하므로 런타임에서 막을 수 없다
numberStack.push('' as any)
- 컴파일 단계의
타입 체크 우회 함, 막기 불가능
- 컴파일 단계의
FUNCTION
- 배열의 첫번째 요소 출력하는 함수 :
function first(arr: any[]): any { return arr[0]; }
- Generic 사용:
function first<T>(arr: T[]): T { return arr[0] }
first<number>([1, 2, 3]) // 1
두개 이상의 타입 변수
- 두가지 변수를 받아 쌍으로 반환하는 함수:
function toPari<T, U>(a: T, b: U): [ T, U ] { return [a, b] }
toPair<string, number>('1', 1); // ['1', 1] toPair<number, number>(1, 2); // [1, 2]
T
다음으로는 알파벳 순서대로 사용하면 된다 (i
,j
처럼)- T, U, V, W…
- 상속된 타입 변수: 입력받을 변수 타입 제한 가능, 자동완성 가능
function getFirst<T extends Stack<U>, U>(container: T): U { const item = container.pop(); container.push(item); return item; }
getFirst<Stack<number>, number>(numberStack); // correct way
getFirst<number, number>(1); // Type 'number' does not satisfy the constraint 'Stack<number>'.
- 참고자료: (all from) HyunSeob Github