我得到了以下类,这是简单的pubsub实现:
interface IAction<N, T> {
name: N,
data: T
}
export class Communicator<A extends IAction<any, any>> {
public subscribe(
subscriber: { name: A['name']; handler: (data: A['data']) => void; }
) {}
public emit(name: A['name'], data: A['data']): void {
}
}
然后我像这样使用它:
enum ActionName {
name1 = 'name1',
name2 = 'name2'
}
type ExampleActions
= { name: ActionName.name1, data: string }
| { name: ActionName.name2, data: number };
const communicator = new Communicator<ExampleActions>();
let a = '';
communicator.subscribe({
name: ActionName.name1,
/* Expected no error, but get
TS2345: Type 'number' is not assignable to type 'string'.*/
handler: data => a = data
});
/* Expected error Type 'string' is not assignable to type 'number',
but got no error*/
communicator.emit(ActionName.name2, 'string');
看起来打字稿可以通过具体的枚举推断出一种具体的动作,但不是。这是一个错误,或者我应该做些不同的事情吗?
答案 0 :(得分:1)
问题是A
是一个联合类型,因此A['data']
将是string | number
(联合中的所有可能性)。此外,没有推断确定基于A['name']
的{{1}}类型应该不同的类型,两者之间没有任何关系它们是一个字段的所有可能类型工会。
如果您在typescript 2.8中使用条件类型(在撰写本文时尚未发布,但您在data
上获得,并且将在3月发布),则可以获得所需的结果。
npm install -g typescript@next
答案 1 :(得分:0)
原因是a
只能是一个字符串,它永远不应该是data
之类的数字。
您可以编写下一个代码:
handler: data => a = data as string
或
handler: data => a = <string>data