[英]Invoking a function in type-safe way in TypeScript
I think an example is worth a thousand words, so below is what I am trying to do: 我认为一个例子值一千字,所以下面是我想做的事:
type Message = keyof MessageArguments;
type MessageArguments = {
'foo': []
'bar': {}
};
type MsgEvent<T extends Message> = {
data: {
type: T
arguments: MessageArguments[T]
}
};
type FunctionTypes = {
[K in Message]: (event: MsgEvent<K>) => void
}
const functions: FunctionTypes = {
'bar': (event) => {
console.log("invoked bar", event);
},
'foo': (event) => {
console.log("invoked foo", event);
}
};
function is<T extends Message>(e: MsgEvent<T>, type: T): e is MsgEvent<T> {
return e.data.type === type;
}
function invoke<T extends Message>(e: MsgEvent<T>, type: T): FunctionTypes[T] {
if (is(e, type)) {
return functions[e.data.type](e);
} else {
throw "failed to find function";
}
}
invoke({
data: {
type: 'foo',
arguments: []
}
}, 'foo');
If you input it into TypeScript playground or compiler you'll get an error: 如果将其输入到TypeScript游乐场或编译器中,则会出现错误:
Cannot invoke an expression whose type lacks a call signature. Type '((event: MsgEvent<"foo">) => void) | ((event: MsgEvent<"bar">) => void)' has no compatible call signatures.
(property) type: T extends "foo" | "bar"
But you can clearly tell from the code that only method (or none) can be invoked, and I think the type should be able to represent that, but I don't know how... It's almost like I need to tell the compiler that in function invoke<T extends Message>
, T
is an exclusive or - it can only be one of the values, not either. 但是您可以从代码中清楚地知道只能调用一个方法(或不调用任何方法),而且我认为类型应该可以表示该方法,但是我不知道如何...就像我需要告诉编译器一样在
function invoke<T extends Message>
, T
是互斥或-只能是值之一,而不能是两者之一。
Along the lines of what Titian Cernicova-Dragomir said, the compiler does not know that you aren't calling invoke
with T = "foo" | "bar"
按照Titian Cernicova-Dragomir所说的,编译器不知道您不是用
T = "foo" | "bar"
调用invoke
T = "foo" | "bar"
T = "foo" | "bar"
. T = "foo" | "bar"
。 Thus, it can only reason based on T
's constraint "foo" | "bar"
因此,它只能基于
T
的约束"foo" | "bar"
推理"foo" | "bar"
"foo" | "bar"
. "foo" | "bar"
。 Edit: I have just updated an existing suggestion of mine to cover constraining type variables singleton; 编辑:我刚刚更新了我的现有建议,以涵盖约束类型变量单例; I suggest you vote for it.
我建议你投票。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.