我正在尝试创建用于规范化类的泛型类型,但是我对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。
预先感谢您的帮助!
答案 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,它将破坏输入中的所有联合,包括涉及undefined
和null
的联合。我认为这对于您的用例来说应该可以接受。
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
(可以通过定义辅助类型别名来删除其中一些重复项。)