Typescript 使用具有强类型字段的对象设置泛型可选映射
我正在尝试编写代码来注册强类型数据加载程序,但是我在使用typescript来正确设置映射时遇到了问题。在下面的示例中,Typescript 使用具有强类型字段的对象设置泛型可选映射,typescript,typescript-generics,Typescript,Typescript Generics,我正在尝试编写代码来注册强类型数据加载程序,但是我在使用typescript来正确设置映射时遇到了问题。在下面的示例中,M是服务地图,k是字段类型为E的服务列表。但是,当我尝试将一个实例分配给映射时,会出现一个错误,表示我正在尝试将其分配给undefined。不知道从这里到哪里去 enum E { A = 'a', B = 'b', } interface I<T extends E> { type: T; } type J<T> = T extends
M
是服务地图,k
是字段类型为E
的服务列表。但是,当我尝试将一个实例分配给映射时,会出现一个错误,表示我正在尝试将其分配给undefined。不知道从这里到哪里去
enum E {
A = 'a',
B = 'b',
}
interface I<T extends E> {
type: T;
}
type J<T> = T extends E ? I<T> : never;
export type K = J<E>;
const M: { [T in E]?: I<T> } = {};
const k: K[] = [];
k.forEach(
<T extends E>(i: I<T>) => {
M[i.type] = i;
// ERROR
// Type 'I<T>' is not assignable to type '{ a?: I<E.A> | undefined; b?: I<E.B> | undefined; }[T]'.
// Type 'I<T>' is not assignable to type 'undefined'.
});
enum E{
A=‘A’,
B=‘B’,
}
接口I{
类型:T;
}
类型J=T扩展到E?I:从来没有;
出口类型K=J;
常数M:{[T in E]?:I}={};
常数k:k[]=[];
k、 弗雷奇(
(i:i)=>{
M[i.type]=i;
//错误
//类型“I”不可分配给类型“{a?:I |未定义;b?:I |未定义;}[T]”。
//类型“I”不可分配给类型“undefined”。
});
这是TypeScript编译器当前的一个限制,或者可能是多个此类限制的组合。我在这里看到的相关问题是:
- (支持
泛型约束)和(支持将泛型索引转换为非泛型映射类型,正是上面的用例): 目前,无法说约束到联合的类型参数(如上面的扩展\u oneof
)一次只能接受联合的单个元素。现在,T extends E
意味着T扩展E
可以用以下四种类型中的任何一种指定:T
、never
、E.A
、或E.B
(即E.A | E.B
)。如果可以告诉编译器,E
可能是T
,或者可能是E.A
,但不能是它们的并集,那么编译器可能会意识到您的赋值对其中每一个都有效,并同时接受它们 但事实并非如此E.B
可以用T
指定,因此E.A | E.B
必须适用于这种情况。因此,您的泛型回调函数也可以更改为其非泛型版本M[i.type]=i
您可以使用一些稍微不那么不安全的断言:k.forEach((i: I<E>) => { M[i.type] = i; }); // error! // --------------------> ~~~~~~~~~ // Type 'I<E>' is not assignable to type 'undefined'
这显然是多余的,而不是你想做的。但它确实表明编译器原则上可以理解k.forEach( <T extends E>(i: I<T>) => { M[i.type] = i as any as (typeof M)[T]; });
是安全的,前提是可以告诉编译器假装执行了这样的案例枚举(如microsoft/TypeScript#25051)M[i.type]=i
看起来像是另一位候选人;编译器无法验证这是否安全。根据我的经验,您可能只想使用一个类型断言,如,然后继续k.forEach( <T extends E>(i: I<T>) => { M[i.type] = i as any as (typeof M)[T]; });
k.forEach( <T extends E>(i: I<T>) => { (M as { [K in T]?: I<K> })[i.type] = i; });
k.forEach(i => i.type === E.A ? M[i.type] = i : M[i.type] = i )