【问题标题】:Checking whether a string is a key in a type, in Typescript在 Typescript 中检查字符串是否是类型中的键
【发布时间】:2020-08-28 00:56:21
【问题描述】:

我的状态有一个类型,还有一个消息处理程序(thunk)的对象,它被显式键入为Record<string, (val: any) => AppThunk>

我收到的传入消息是对象,它们的键可以与消息处理程序对象的键匹配,在这种情况下,我想调用消息处理程序,或者它们的键可以与 DataState 的键匹配,在这种情况下,我只想将它们发送到updateState

下面的代码可以正常工作。

type DataState = {
  startRequestCounter: -1,
  startResponseCounter: -1,
  stopRequestCounter: -1,
  stopResponseCounter: -1,
  robotMode: RobotMode.Idle as RobotMode,
}

const messageHandlers: Record<string, (val: any) => AppThunk> = {  
  startRequestCounter: () => async (dispatch, getState) => // do stuff,  
  startResponseCounter: (counter: number) => dispatch  => // do stuff,
  stopResponseCounter: (counter: number) => dispatch  => // do stuff
}

export const handleMessage = (message: MessagePayload): AppThunk => (dispatch, getState) => {
  Object.entries(message).forEach(([snakeKey, value]) => {
    const key = camelCase(snakeKey)
    
    // call the message handler for this message, if there is one
    if (messageHandlers[key]) {
      dispatch(messageHandlers[key](value))
    }
    // if not, update the state if we have a state for this message
    else if (Object.keys(getState().data).includes(key)) {  // <~~~~ HERE!!!!
      dispatch(updateState({ [key]: value }))
    }
  })
}

不过,我觉得结尾的else if 可以写得更简洁一些。

else if (getState().data[key]) 有效(如果我忽略它),但 TypeScript 抱怨:

元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“{ startRequestCounter: number; startResponseCounter:数字; stopRequestCounter:数字; stopResponseCounter:数字; cuvettesCount:数量; pipettesCount:数量;机器人模式:机器人模式; }'。

我进行了一些搜索,看起来 keyof 可能是我要查找的内容,但在我输入时甚至找不到 keyof

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这是因为 key 不能保证是您的DataState 中列出的密钥之一。

    你可以告诉 TypeScript 它将使用keyof

    if (getState().data[key]) { 
        // Error Here
    }
    if (getState().data[key as keyof DataState]) {  
        // Not Here
    }
    

    【讨论】:

    • 这是否意味着我可以说if (key is keyof DataState)
    • 不,你不能那样做。 as 只是告诉 TypeScript 你想假设变量是这种类型的一种方式,即使你无法证明它。当它被编译回 JavaScript 时,它会被删除,因为它实际上并没有做任何事情。
    • 您可以创建一个可以做到这一点的 TypeGuard,但您仍然在该方法中编写相同的逻辑。 typescriptlang.org/docs/handbook/…
    • 您必须意识到 Typescript 类型实际上并不存在。他们只是帮助你编码。因此,您不能根据某物是否为“类型”来做任何事情。
    【解决方案2】:

    托德的回答很好,但我想出一个基本上和我想要的一样简洁的答案:

    else if (key in getState().data)
    

    【讨论】:

      猜你喜欢
      • 2021-12-25
      • 1970-01-01
      • 2020-02-23
      • 2022-01-19
      • 2012-09-28
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      相关资源
      最近更新 更多