TypeScript中的关联类型

时间:2016-04-03 18:01:09

标签: generics typescript

Swift中有associated types这样的概念。

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()
    }
}

这是一种通用接口,但相关类型的一个重要特征是可以从包含类型之外引用它们。

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

是否有可能在TypeScript中制作这样的东西?

2 个答案:

答案 0 :(得分:2)

目前,Typescript中的关联类型没有这种功能。

关联类型的替代

打字稿中没有像这样的东西吗?...

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

  add(other: T): Output;
}

有一些替代方法可以解决关联类型在不同程度上解决的一些问题。

推断通用

您可以像这样推断出传递给泛型的类型

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

您可以像这样使用这种类型。

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

您可以在Typescript游乐场here上使用它。

索引字段的字段

假设您有以下几种类型:

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

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

如果这些字段是公共的,则可以使用索引语法来获取它们的类型。

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

同样,您可以在Typescript游乐场here上查看一下。

答案 1 :(得分:1)

根据documentation,它可以是这样的:

abstract class Container<ItemType> {
    abstract append(item: ItemType): void;
    abstract count(): number;
    abstract subscript(i: number): ItemType;
}

class IntStack extends Container<number> {
    private items: Array<number> = [];

    append(item: number) {
        this.items.push(item);
    }
    count(): number {
        return this.items.length;
    }
    subscript(i: number): number {
        return this.items[i];
    }

    // Other functions
}

更新

通常,在运行时不可能获得泛型类型参数,因为这种“类型”仅由typescript编译器用于类型检查,并且不会编译成结果JavaScript代码中的任何工件。您可以在Typescript Playground

中查看

尽管如此,如果您在运行时具有真正的价值,您可以使用一些技巧,如Get type of generic parameter SO文章中所述。