generikler - TypeScript'te ilişkili türler


Swift'te ilişkilendirilmiş türler gibi bir kavram vardır.

protocol Container {
    associatedtype ItemType // Here it is.
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

struct IntStack: Container {
    typealias ItemType = Int // Here again.
    mutating func append(item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }

    var items = [Int]()
    mutating func push(item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
}

Bu bir tür genel arayüzlerdir, ancak ilişkilendirilmiş türlerin önemli bir özelliği, bulundukları türün dışından referans verilebilmeleridir.

var x: IntStack.ItemType = someIntStack.pop()

TypeScript'te bunun gibi bir şey yapmak mümkün mü?

Cevap #1

Şu anda Typescript'te ilişkili tipler için böyle bir özellik yok.

İlişkili Türlere Alternatifler

Typescript'te bunun gibi bir şey olmasa da?...

// WILL NOT COMPILE
interface Add<T> {
  type Output;

  add(other: T): Output;
}

İlişkili tiplerin ele aldığı bazı sorunları farklı derecelerde çözebilecek alternatifler vardır.

Geneli çıkarsamak

Bir generiğe geçirilen türü şu şekilde çıkarabilirsiniz

type ArrayItem<T> = T extends Array<infer I> ? I : never;

Ve bu türü bu şekilde kullanabilirsiniz.

const number: ArrayItem<Array<number>> = 1;

Burada Typescript Playground'da onunla oynayabilirsiniz.

Bir alanın alanını indeksleme

Diyelim ki bunlar gibi bazı türlerin vardı:

type StorageStage<T> = 
  | { kind: 'initial' }
  | { kind: 'loading', promise: Promise<Array<T>> }
  | { kind: 'loaded', storage: Array<T> };

class AsyncStorage<T> {
  state: StorageStage<T> = { kind: 'initial' };
}

Bu alanlar genel (public) ise, türlerini almak için indeks sözdizimini kullanabilirsiniz.

const storageStage: AsyncStorage<number>["state"] = 
  { kind: 'loaded', storage: [1] }; 

Yine, bunu burada Typescript Playground'da kontrol ediyorsunuz.

İlgili makaleler