在 Typescript 中检查字符串是否是类型中的键

Jon*_*man 7 typescript

我有一个状态类型,以及一个消息处理程序(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 }))
    }
  })
}
Run Code Online (Sandbox Code Playgroud)

不过我觉得else if最后可以写得更简洁一些。

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

元素隐式具有“any”类型,因为“string”类型的表达式不能用于索引类型“{ startRequestCounter: number;” 启动响应计数器:数字;停止请求计数器:数字;停止响应计数器:数字;比色杯计数:数量;移液器计数:数量;机器人模式:机器人模式;}'。

我做了一些搜索,看起来可能keyof就是我要找的东西,但当keyof我输入它时却找不到。

Tod*_*ton 3

这是因为 key 不能保证是您的DataState.

您可以告诉 TypeScript 它将使用keyof.

if (getState().data[key]) { 
    // Error Here
}
if (getState().data[key as keyof DataState]) {  
    // Not Here
}
Run Code Online (Sandbox Code Playgroud)