TypeScript无法返回与通用参数具有相同基数的对象

时间:2018-06-29 17:55:35

标签: typescript

我有一个工厂,该工厂基于扩展BaseEntity的实体返回配置值。但是,我收到一个类型错误,指出无法从函数返回具有与通用参数相同签名的类型,特别是类型Collection<A> is not assignable to type Collection<T>和那个Type A is not assignable to type T。但是,在此示例中,AT的定义不相同吗?

type BaseTypes = 'a';

interface Base {
  type: BaseTypes;
  id: number;
}

interface A extends Base {
  type: 'a';
  name: string;
}

interface Collection<T extends Base> {
  items: T[];
}

function getCollection<T extends Base>(obj: T): Collection<T> | null {
  switch (obj.type) {
    case 'a':
      return getACollection(); // Type Collection<A> is not assignable to type Collection<T>
    default:
      return null;
  }
}

function getACollection(): Collection<A> {
  return { items: [] };
}

1 个答案:

答案 0 :(得分:1)

Typescript需要一个联合类型才能使用类型防护,Base是派生接口的基本类型,但不是联合,因此编译器不会缩小联合。

第二个问题是,即使扩展了联合,Typescript也不会缩小泛型类型(尽管我相信在将来的发行版中这会改变,如果找到它,我会发布github问题。编辑 This是问题所在,但显然没有实现它的计划。但是,即使要缩小参数的类型,也只会缩小参数的范围,类型保护不会影响函数的返回类型。类型防护在影响方面非常狭窄。

最简单的解决方案是为函数提供两个不同的签名:一个带有通用参数的公共签名,一个不带通用参数的私有签名,它们使用Base并返回Collection<Base>。这不是一个完全类型安全的解决方案,因为该实现可以接受Base的一个派生并返回不同派生的collectionsl,但这是我们目前能做的最好的事情。

function getCollection<T extends Base>(obj: T): Collection<T> | null
function getCollection(obj: Base): Collection<Base> | null {
    switch (obj.type) {
        case 'a':
            return getACollection(); 
        default:
            return null;
    }
}