简体   繁体   English

TypeScript 和联合类型

[英]TypeScript and Union Types

Given: Reducer accepts one of the four actions:鉴于:Reducer 接受以下四个动作之一:

interface ItemAction {
    type: 'ADD_TODO'|'DELETE_TODO'|'TOGGLE_TODO',
    id: number
}

interface QueryAction {
    type: 'SET_QUERY',
    query: string
}

I expect the code of the reducer contain something like:我希望减速器的代码包含以下内容:

if (action as ItemAction) {
   console.log(action.id); // typescript knows that "id" is available here
} else {
   console.log(action.query); // typescript knows that action is of type QueryAction and hence "query" is available here
}

How do I achieve that with TypeScript?我如何使用 TypeScript 实现这一目标?

The easiest solution is to use the in operator :最简单的解决方案是使用in运算符

let action: ItemAction | QueryAction = ...;
if ('id' in action) {
  // Type inferred as ItemAction
} else {
  // Type inferred as QueryAction
}

For more complex cases, you can use type guards .对于更复杂的情况,您可以使用类型保护

This can be handled with a user-defined typeguard.这可以通过用户定义的类型保护来处理。 For example例如

function isItemAction(someAction: any): someAction is ItemAction {
  if(someAction.id !== undefined and typeof someAction.id === 'number') {
    return true
  } else return false
}

if (if isItemAction(action)) {
  console.log(action.id); // typescript knows that "id" is available here
} 

A few things to know about typeguards: (1) they require the use of the type predicate "is" language;关于 typeguards 需要了解的一些事情:(1)它们需要使用类型谓词“is”语言; (2) they are conventionally named as I have named them, isX; (2) 它们的传统名称就像我给它们命名的一样,isX; (3) TS has no way of knowing that the evaluation logic in your function is accurate, that's up to you, in other words, a typeguard that always evaluates to true will be fine from TS's perspective. (3) TS 无法知道您函数中的评估逻辑是否准确,这取决于您,换句话说,从 TS 的角度来看,始终评估为 true 的类型保护就可以了。

See here for more info on writing user defined type guards.有关编写用户定义的类型保护的更多信息,请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM