为什么打字稿枚举对推断联合类型没有帮助

时间:2018-02-22 10:12:08

标签: typescript enums union type-inference

我得到了以下类,这是简单的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'); 

看起来打字稿可以通过具体的枚举推断出一种具体的动作,但不是。这是一个错误,或者我应该做些不同的事情吗?

2 个答案:

答案 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