Typescript 完全扩展联合类型
假设以下示例代码:Typescript 完全扩展联合类型,typescript,Typescript,假设以下示例代码: type Action = "GET" | "POST" | "PUT"; type Handler<A extends Action> = (action: A) => void; const handlers: Partial<Record<Action, Handler<Action>>> = { }; function register<A extends Action>(action: A, ha
type Action = "GET" | "POST" | "PUT";
type Handler<A extends Action> = (action: A) => void;
const handlers: Partial<Record<Action, Handler<Action>>> = { };
function register<A extends Action>(action: A, handler: Handler<A>) {
/*
Error:
Type 'Handler<A>' is not assignable to type 'Partial<Record<Action, Handler<Action>>>[A]'.
Type 'Handler<A>' is not assignable to type 'Handler<Action>'.
Type 'Action' is not assignable to type 'A'.
'Action' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'Action'.
Type '"GET"' is not assignable to type 'A'.
'"GET"' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'Action'.
*/
handlers[action] = handler;
}
其中return语句给出与上述相同的错误。这揭示了实际的问题:
T
实际上可能比union小,因此您可能最终传入的函数处理的情况比预期的要少。一个好的解决方案将不存在,除非实现或强制转换它
扩展操作
不允许A
比操作
大。它不能是操作|“删除”
A扩展了B
意味着A
是B
的一个子类型,或者如果您有A
类型的值,那么它也必须是B
类型。Action |“DELETE”
类型的值不一定是Action
类型的值,因为它可能是“DELETE”
您可能希望将
handlers
定义为将键与值关联的映射类型:const handlers:{[K in Action]?:Handler}={}代码>
但是问题仍然存在,编译器无法看到处理程序[action]
和处理程序
是兼容的,原因如上面第一句所述。TypeScript中没有对类型的强大支持,而且这只会变得更糟,因为TS3.5通过索引访问获得了更多。一个好的解决方案将不存在,除非或者实现了,所以只需将它转换为A extensed Action
就不允许A
比Action
大。它不能是操作|“DELETE”
A扩展了B`意味着A
是B
的子类型,或者如果您有A
类型的值,那么它也必须是B
类型。类型为Action |“DELETE”
的值不一定是Action
类型的值,因为它可能是“DELETE”
。您可能希望将handlers
定义为将键与值关联的映射类型:const handlers:{[K in Action]?:Handler}={}
但问题仍然存在,编译器无法看到处理程序[操作]
和处理程序
是兼容的,原因是@Austraas提到的。TypeScript中对类型的支持不是很好,而且这只会变得更糟,因为TS3.5在索引访问方面得到了更多的支持。看看它试图完全解释这种消息的含义。让我知道它是否解决了你的问题。这是一个上传到问题下的上传评论的拷贝和粘贴。我在这里转发这些评论作为答案,以防这些评论被删除。
function foobar<T extends "foo" | "bar">(func: (arg: T) => void): (arg: "foo" | "bar") => void {
return func;
}