我现在正在玩TypeScript,并正在使用Playground页面进行研讨,着眼于将现有项目转换为TypeScript .

我解决了我正在处理的问题,但在这个过程中我遇到了一些我不太了解的问题 . 它考虑了最简单的通用队列类,这里部分显示 .

class Queue<T> {
  private store: T[] = [];
  public enqueue(item: T) {
    this.store.push(item);
  }
}

const queue = new Queue<number>();
queue.enqueue(5);       // works
queue.enqueue('six')    // properly errors

当然,这很好用 . 如果将后备存储类型作为两个类型变量的并集类型,它也可以正常工作 .

class Queue<T, U> {
  private store: (T | U)[] = [];
  public enqueue(item: T | U) {
    this.store.push(item);
  }
}

const queue = new Queue<number, boolean>();
queue.enqueue(5);       // works
queue.enqueue(true);    // works
queue.enqueue('six')    // properly errors

但是,当我使存储成为类型变量的联合类型和已存在的具体类型时,类型检查对 enqueue 不起作用 . ( Empty 是一个单例类,用于通过返回特定的 EMPTY 对象来模拟我指示空队列的旧方法;我'm not sure what the best way to do that is but that' s用于另一个问题 . )

class Empty {
  // implementation of singleton class
}

const EMPTY = Empty.instance;

class Queue<T> {
  private store: (T | Empty)[] = [];
  public enqueue(item: T | Empty) {
    this.store.push(item);
  }
}

const queue = new Queue<number>();
queue.enqueue(5);       // works
queue.enqueue(EMPTY);   // works
queue.enqueue('six')    // also works, but it shouldn't

不出所料,为 T | Empty 引入类型别名并没有帮助 .

现在实际上,这对我来说不是问题,因为我的队列实现只存储类型 T . 只有我的 dequeue 在其签名中有一个联合类型,因为如果商店是空的,它会返回 EMPTY (并且工作正常) . 但我当然可以看到一个带有类型参数和具体类型的联合类型数组的位置,并且没有深入挖掘它,它似乎应该是可能的 .

这是我不了解语言的东西,我做错了,还是仅仅是编译器限制?