In 这段 TypeScript 代码,也在下面重复,有一个映射类型
type DRYObjectModelMap = {
[PlanetaryBodyClass in keyof FieldNameWithValueMap]: ObjectModel<PlanetaryBodyClass>
}
where keyof FieldNameWithValueMap = 'Moon' | 'Planet'
但映射类型不会产生预期的等价物:
type ObjectModelMap = { //This requires more hard-coded repetition
Moon: ObjectModel<'Moon'>;
Planet: ObjectModel<'Planet'>;
}
使用这个预期的版本,甚至通过在映射类型中映射到它(将ObjectModelMap[PlanetaryBodyClass]
冒号右侧)导致下面的错误消失,但也使代码更难维护,需要脆弱的重复。映射类型似乎旨在帮助避免这种重复的需要,但在本例中实际上并没有达到这一目的。
A 单独的问题解决了为什么在代码中添加带有多余条件的包装类型可能会意外地导致错误消失。
这可能是由于 TypeScript 中的一个错误造成的,尽管我在问题/PR 列表- 或者也许我只是不太了解这里发生的事情,无法使用正确的术语进行搜索或报告。 (如果您认为适当且不重复,请随时在那里提交新的错误报告)。
代码位于游乐场链接 is:
import BN from "bn.js";
//Simplified version of externally fixed model; many fields omitted for simpler example
type FieldNameWithValueMap = {
Moon: [fieldName: "visibleStarsCount", fieldValue: BN] | [fieldName: "hostStar", fieldValue: string];
Planet: [fieldName: "visibleStarsCount", fieldValue: BN] | [fieldName: "hostPlanet", fieldValue: string];
}
//type PlanetaryBodyName = keyof FieldNameWithValueMap; //'Moon' | 'Planet'; not used for simpler example
type TupleToObject<T extends [string, any]> = { [key in T[0]]: Extract<T, [key, any]>[1] };
type ObjectModel<T extends keyof FieldNameWithValueMap> = TupleToObject<FieldNameWithValueMap[T]>;
//Hovering over these two examples, the types are as expected; they need to be derived from imported types.
type MoonObject2 = ObjectModel<'Moon'>; //{visibleStarsCount: BN; hostPlanet: string;}
type PlanetObject2 = ObjectModel<'Planet'>; //{visibleStarsCount: BN; hostStar: string;}
type DRYObjectModelMap = {
[PlanetaryBodyClass in keyof FieldNameWithValueMap]: ObjectModel<PlanetaryBodyClass>
//The below works, but not the above, and requires the undesired hard-coded repetition
//[PlanetaryBodyClass in keyof FieldNameWithValueMap]: ObjectModelMap[PlanetaryBodyClass]
}
type ObjectModelMap = { //This works in place of using DRYObjectModelMap, but requires more hard-coded repetition
Moon: ObjectModel<'Moon'>;
Planet: ObjectModel<'Planet'>;
}
type PickedAttributeSimpler<T extends 'Moon'> = DRYObjectModelMap[T]['visibleStarsCount'];
function genericFunction<
T extends 'Moon', //union type that includes | 'Planet' omitted for simpler example.
//Omitting the generic type parameter and hard-coding it into each usage below fixes the error,
//but the real version of the function not oversimplified for the example needs to be generic.
>(
PlanetaryBodyClass: T,
) : PickedAttributeSimpler<T> { //Same if using DRYObjectModelMap[T]['visibleStarsCount']
return new BN(42); //ERROR TS(2322): Type 'BN' is not assignable to type 'PickedAttributeSimpler<T>'.
}
type ExamplePickedAttribute = PickedAttributeSimpler<'Moon'>; //This is type 'BN' as expected
type ExampleGenericPickedAttribute<T extends 'Moon'> = PickedAttributeSimpler<T>; //This is DRYObjectModelMap[T]['visibleStarsCount']
type ExampleGenericInstanceOfPickedAttribute = ExampleGenericPickedAttribute<'Moon'>; //This is BN as expected
type HoverToSeeHowTypeShouldResolve<T extends 'Moon'> = DRYObjectModelMap[T]['visibleStarsCount'];
type HoverToSeeHowTypeShouldResolveInstance = HoverToSeeHowTypeShouldResolve<'Moon'>; //This is BN as expected