TypeScript版本: typescript@2.9.0-dev.20180420
搜索词: 区分,穷举,类型保护,缩小
代码
// Legal action types for ValidAction
enum ActionTypes {
INCREMENT = 'INCREMENT',
// DECREMENT = 'DECREMENT',
}
interface IIncrement {
payload: {};
type: ActionTypes.INCREMENT;
}
// interface IDecrement {
// payload: {};
// type: ActionTypes.DECREMENT;
// }
// Any string not present in T
type AnyStringExcept<T extends string> = { [P in T]: never; };
// ValidAction is an interface with a type in ActionTypes
type ValidAction = IIncrement;
// type ValidAction = IIncrement | IDecrement;
// UnhandledAction in an interface with a type that is not within ActionTypes
type UnhandledAction = { type: AnyStringExcept<ActionTypes>; };
// The set of all actions
type PossibleAction = ValidAction | UnhandledAction;
// Discriminates to ValidAction
function isUnhandled(x: PossibleAction): x is UnhandledAction {
return !(x.type in ActionTypes);
}
type CounterState = number;
const initialState: CounterState = 0;
function receiveAction(state = initialState, action: PossibleAction) {
// typeof action === PossibleAction
if (isUnhandled(action)) {
// typeof action === UnhandledAction
return state;
}
// typeof action === ValidAction
switch (action.type) {
case ActionTypes.INCREMENT:
// typeof action === IIncrement
return state + 1;
// case ActionTypes.DECREMENT:
// return state - 1;
}
// typeof action === IIncrement
// Since INCREMENT is handled above, this should be impossible,
// However the compiler will say that assertNever cannot receive an argument of type IIncrement
return assertNever(action);
}
function assertNever(x: UnhandledAction): never {
throw new Error(`Unhandled action type: ${x.type}`);
}
预期行为: 不会抛出错误,因为switch语句是穷举的。如果取消注解ActionTypes.DECREMENT部分(导致ActionTypes有两个可能的值),则不会出现错误。只有在ActionTypes只有一个值时才会出现错误。即使在默认情况下发生never
Assert,错误仍然会发生,这显然是从IIncrement不可达的。
实际行为: 尽管只有可能的值被显式处理,但仍然抛出错误。如果取消注解ActionTypes.DECREMENT,预期行为将出现。
Playground链接: (修复了链接)
错误
工作
相关问题:
5条答案
按热度按时间jvidinwx1#
这也是同样的情况,当你尝试为未来的联合类型准备代码,但目前只使用一种类型。
如果你取消注解所有与第二个接口(前3个注解块)相关的内容,一切都将按预期工作。
daolsyd02#
是的,这确实只是归结为"当对大小大于1的工会进行区分时,穷尽性检查才能起作用"。
o3imoua43#
我刚刚也遇到了这个bug。这里有一个简单的例子:
xtfmy6hx4#
我们今天也遇到了这个问题。这里有另一个代码示例,如果它能帮助的话
错误是
通过移除类型定义和switch中的
reason_2
的注解,错误消失了。moiiocjp5#
今天在尝试为扩展结构化一些代码时遇到了这个问题:
https://www.typescriptlang.org/play/?ssl=22&ssc=2&pln=1&pc=1#code/JYOwLgpgTgZghgYwgAgJIgM7TAFQgDzGQG8AoZC5MATwAcIAuZAclCyjAH1JDmBucpVpwwACyYgArgFsARtAGUqBMEwxgooAOYCAvqVI16yAPL0oI4AHsQyALxpM2PIQGkYkkAjDXbETJJQEACqIEGIonCyADYQABQAbnDRkozIIBAJ0AA0yNIQGBhwWhAA-Goa2gCUEpnQJIJiUFYA7ukQbQCiUM1QcfmFxSgAPsPIAAah4QiRMSgIVgAmKKLARC1roshJKSgAJMQAypUgWonJqVW641V6Bh5ePjbIcLS00dRmcVa0TGbQlhsNW2VmAiwaSgwGzAM2Q31oADojBAqiRkIIlBQEHAsCw2NhuCpmEwyJiycgFpgrLEEdErGcfkiVLcMeSKEEwIEQIpyfo2ct4JJoqpWWz-BhAiEwhAIlFYvCWUp9LogA