“扩展Array <object>”在打字稿中无法按预期工作

时间:2018-08-30 20:59:10

标签: typescript

我正在尝试创建用于规范化类的泛型类型,但是我对Array的使用没有达到我的预期。

 interface IBuilding {
  buildingID: number,
  name: string,
  construction: ("wood" | "concrete" | ""),
  website: string,
  address?: IAddress,
  apartments?: IApartment[]
}

type Normalized<T> = {
  [K in keyof T]:
  T[K] extends number ? number :
  T[K] extends string ? string :
  T[K] extends number[] ? number[] :
  T[K] extends string[] ? string[] :
  T[K] extends Function ? never :
  T[K] extends Array<Object> ? number[] :
  T[K] extends Object ? number :
  T[K]
};

let building: Normalized<IBuilding>;

我希望building.apartments类型为number [],但它是number。

预先感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我假设您正在使用strictNullChecks,因为这是我可以重现所描述行为的唯一方法。由于apartments的{​​{1}}字段是可选的,因此其有效类型为IBuilding,由于undefined | IApartment[],它的有效类型不扩展Array<Object>。但是,即使在调用undefined之前,条件类型Normalized也会简化为T[K] extends Object ? number : T[K],因为编译器会假定内部将任何东西都视为“类型变量”(包括未简化的查找类型)受空对象类型number约束,该对象类型可分配给{}。显然,如果Object最终包含T[K]null,则此假设是不正确的。我提交了an issue

要获得我想要的行为,可以使用distributive conditional type,它将破坏输入中的所有联合,包括涉及undefinednull的联合。我认为这对于您的用例来说应该可以接受。

undefined

如果不想分解所有联合,则可以使用非分配条件类型,而只需为带有type NormalizeOne<T> = T extends number ? number : T extends string ? string : T extends number[] ? number[] : T extends string[] ? string[] : T extends Function ? never : T extends Array<Object> ? number[] : T extends Object ? number : T; // not reached due to compiler issue type Normalized<T> = { [K in keyof T]: NormalizeOne<T[K]>; }; 的联合添加特定案例:

undefined

(可以通过定义辅助类型别名来删除其中一些重复项。)