λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

typescript

TypeScript / μ œλ„€λ¦­

Generics(μ œλ„€λ¦­)

ν•¨μˆ˜, 클래슀, μΈν„°νŽ˜μ΄μŠ€ λ“± νƒ€μž…μ„ λ§€κ°œλ³€μˆ˜ 처럼 μ‚¬μš©ν•  수 있게 ν•œλ‹€.

λ‹€μ–‘ν•œ νƒ€μž…μ˜ 데이터λ₯Ό μ²˜λ¦¬ν•  수 μžˆλŠ” λ²”μš©μ μΈ νŒ¨ν„΄μ„ μ œκ³΅ν•΄ μœ μ‚¬ν•œ κΈ°λŠ₯을 ν•˜λŠ” ν•¨μˆ˜, 클래슀 등을 ν•˜λ‚˜λ‘œ 톡합할 수 μžˆλ‹€.

 

  • μž₯점 : μ½”λ“œ μž¬μ‚¬μš©μ„± • μœ μ—°μ„± • ν™•μž₯μ„± 증가 (라이브러리, 툴 개발 μ‹œ λ”μš± 유용) , λͺ…μ‹œμ μΈ νƒ€μž… ν‘œν˜„
  • 단점 : λŸ¬λ‹ 컀브(μ΄ˆλ³΄μžμ—κ² 어렀움) , λ³΅μž‘μ„± • 컴파일 μ‹œκ°„ 증가
function genericFunction<T>(arg:T):T{
    return arg;
}

interface GenericInterface<T> {}
class GenericClass<T> {}

 

 

νƒ€μž… λ³€μˆ˜(Type Variable)

νƒ€μž… μžλ¦¬μ— λŒ€μ²΄λ  νƒ€μž…μ„ λ‚˜νƒ€λ‚΄λŠ” λ³€μˆ˜

μ‹€μ œ μ‚¬μš©μ‹œμ—λŠ” ꡬ체적인 νƒ€μž…μœΌλ‘œ λŒ€μ²΄λ¨

function ν•¨μˆ˜μ΄λ¦„<Type>(arg:Type):Type{}
// Typeμ΄λ‚˜ Tλ₯Ό 주둜 μ‚¬μš©ν•˜μ§€λ§Œ μ•„λ¬΄κ±°λ‚˜ 해도 μƒκ΄€μ—†μŒ

 

λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•  수 μžˆλ‹€.

let numbers: Array<number> = [1, 2, 3, 4, 5]
let strings: Array<string> = ['1', '2', '3', '4', '5']

let div = document.querySelector<HTMLDivElement>('#myDiv1')
let btn = document.querySelector<HTMLButtonElement>('#myBtn1')

// μ œλ„ˆλ¦­μœΌλ‘œ μ •μ˜ν•΄μ€¬κΈ° λ•Œλ¬Έμ— λ²„νŠΌμ˜ 속성에 μ ‘κ·Όν•  수 μžˆλ‹€
// btn에 였λ₯˜κ°€ 남 -> ν•΄λ‹Ή μš”μ†Œκ°€ μ—†μ–΄μ„œ μ—λŸ¬κ°€ λ‚˜λŠ” κ²ƒμ΄λ‹ˆ ?λ₯Ό λΆ™μ—¬ 쑰건뢀 νŒλ‹¨μ„ ν•΄μ€Œ 
btn?.click()

 

 

μ œλ„€λ¦­ ν•¨μˆ˜

μ‚¬μš©ν•˜μ§€ μ•Šμ€ 경우

function getFirstElement (arr:number[]) {
    if(!arr.length) {
        return undefined
    }
    return arr[0]
}

const firstNumber = getFirstElement(numbers)

function getFirstStringElement (arr:string[]) {
    if(!arr.length) {
        return undefined
    }
    return arr[0]
}

const firstString = getFirstStringElement(strings)

 

 

μ œλ„€λ¦­μ„ μ‚¬μš©ν•œ 경우

function getFirstElement<T>(arr: T[]): T | undefined {
    if (!arr.length) {
        return undefined
    }
    return arr[0]
}

const firstNumber = getFirstElement(numbers)
const firstString = getFirstElement(strings)

 

 

μ œλ„€λ¦­ μΈν„°νŽ˜μ΄μŠ€

μ‚¬μš©ν•˜μ§€ μ•Šμ€ 경우

interface strDict {
    [key: string]: string
}

let strObj: strDict = {
    name: "Elliot"
}

interface numDict {
    [key: string]: number
}

let numObj: numDict = {
    age: 23
}

 

 

μ œλ„€λ¦­μ„ μ‚¬μš©ν•œ 경우

interface Dict<T> {
    [key: string]: T
}

let strObj: Dict<string> = {
    name: "Elliot"
}

let numObj: Dict<number> = {
    age: 23
}

 

 

μ—¬λŸ¬ 개의 νƒ€μž… λ³€μˆ˜λ₯Ό μ§€μ •ν•  μˆ˜λ„ μžˆλ‹€.

μ΄λŸ°μ‹μœΌλ‘œ λ”•μ…”λ„ˆλ¦¬, λ§΅ ꡬ쑰 μ‚¬μš©μ‹œ νƒ€μž…μ— κ΄€ν•΄ μœ μ—°ν•˜κ²Œ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€.

interface Entry<K, V> {
    key: K;
    value: V;
}

let entry1: Entry<string, number> = {
    key: "age",
    value: 25
}

let entry2: Entry<number, string[]> = {
    key: 1,
    value: ['red', 'green', 'blue']
}

 

 


 

 

μ œλ„€λ¦­ 클래슀

클래슀λ₯Ό μ •μ˜ν•  λ•ŒλŠ” νƒ€μž…μ„ κ³ μ •ν•˜μ§€ μ•Šκ³ ,

ν΄λž˜μŠ€κ°€ μ‚¬μš©ν•  νƒ€μž…μ„ μΈμŠ€ν„΄μŠ€ν™” μ‹œμ μ—μ„œ μ§€μ •ν•  수 있게 ν•΄μ€€λ‹€.

 

예제 1

class Item<T> {
    #content: T | null;
    constructor() {
        this.#content = null;
    }

    setItem(value: T) {
        this.#content = value;
    }

    getItem(): T | null {
        return this.#content;
    }
}

const numberItem = new Item<number>();
numberItem.setItem(100);
numberItem.getItem(); // 100

const stringItem = new Item<string>();
stringItem.setItem("Hello");
stringItem.getItem(); // Hello λ°˜ν™˜

 

 

예제 2-1

interface User {
    id: number;
    name: string;
}

interface Store<T> {
    findById(id: number): T | undefined;
    save(item: T): void;
}

class UserRepository implements Store<User> {
    #users: User[] = []; // 빈 λ°°μ—΄λ‘œ μ΄ˆκΈ°ν™”
    findById(id: number): User | undefined {
        return this.#users.find(user => user.id === id);
    }
    save(user: User): void {
        this.#users.push(user)
    }
}

// μ‚¬μš©
const userRepo = new UserRepository();

userRepo.save({
    id: 1,
    name: "Java"
})

userRepo.save({
    id: 2,
    name: "C#"
})

console.log(userRepo.findById(2))

 

 

예제 2-2

μœ„μ—μ„œ μƒμ„±ν•œ Store μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•΄ μƒˆλ‘œμš΄ 클래슀λ₯Ό μƒμ„±ν–ˆλ‹€.

class ProductRepository implements Store<Product> {
    #products: Product[] = [];

    findById(id: number): Product | undefined {
        return this.#products.find(product => product.id === id)
    }

    save(product: Product): void {
        this.#products.push(product)
    }
}

// μ‚¬μš©
const productRepo = new ProductRepository();

productRepo.save({
    id: 10,
    price: 100,
    name: "keyboard"
})
productRepo.save({
    id: 12,
    price: 400,
    name: "mouse"
})

console.log(productRepo.findById(12))

 

 

μ œλ„€λ¦­μ˜ μ œμ•½μ‘°κ±΄

 

μœ„ μ˜ˆμ œλ“€μ„ 기반으둜 μƒˆλ‘œμš΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μΆ”κ°€ν–ˆλ‹€.

interface User {
    id: number; // id 값을 μ •μ˜ν•˜μ§€ μ•ŠμœΌλ©΄ Userλ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λž˜μŠ€μ—μ„œ id propertyλ₯Ό 찾을 수 μ—†λ‹€κ³  μ—λŸ¬κ°€ λ‚œλ‹€.
    name: string;
}

// μƒˆλ‘œ μΆ”κ°€!! 
interface WithId {
    id: number;
}

// extends ν‚€μ›Œλ“œλ‘œ μ œμ•½ 쑰건을 κ±Έμ–΄μ€Œ
interface Store<T extends WithId> {
    findById(id: number): T | undefined;
    save(item: T): void;
}

// User에 id값이 μ—†λ‹€λ©΄ μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ 됨
class UserRepository implements Store<User> {
    #users: User[] = []; // 빈 λ°°μ—΄λ‘œ μ΄ˆκΈ°ν™”
    findById(id: number): User | undefined {
        return this.#users.find(user => user.id === id);
    }
    save(user: User): void {
        this.#users.push(user)
    }
}

 

 

이런 μ‹μœΌλ‘œ μ œμ•½ 쑰건으둜 λΆ€μ—¬ν•΄ νƒ€μž…μ„ ꡬ체적으둜 μ •μ˜ν•  수 μžˆλ‹€.

'typescript' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

TypeScript / Webpack  (0) 2025.06.10
TypeScript / νƒ€μž… μ„ μ–Έ 파일  (4) 2025.06.10
TypeScript / 클래슀  (0) 2025.06.05
TypeScript / νƒ€μž… μΆ”λ‘ , νƒ€μž… 단언  (0) 2025.06.05
TypeScript / νƒ€μž…(2)  (0) 2025.06.04