2

have a question about ensure function, somehow it doesn't make null safe after check in either block. What I am doing wrong, or is there a better way to ensure that value is not null except of using !! here is my code

 suspend fun checkCanConnectDirectChat(
    senderId: Int?,
    receiverId: Int?,
    chatRoomId: Int?
  ) = either {
    ensure(chatRoomId != null && receiverId != null) {
      BadRequestExceptionResponse(message = ErrorConstants.INVALID_PAYLOAD)
    }

    val isSenderInChat = isUserInChat(chatRoomId, senderId).bind()
    val isReceiverInChat = isUserInChat(chatRoomId, receiverId).bind()
    ensure(isSenderInChat && isReceiverInChat){
      BadRequestExceptionResponse(message = ErrorConstants.INVALID_PAYLOAD)
    }
  }

after the ensure I still see that they are nullable enter image description here

Victor Orlyk
  • 1,454
  • 2
  • 15
  • 27

2 Answers2

1

Unfortunately the compiler is not "clever enough" to know that if the check inside ensure talks about null-ness, then within the block that holds. The best solution is to use the *NotNull family of functions, some of them available at Arrow, some of them available in the standard library.

serras
  • 2,165
  • 2
  • 13
  • 11
1

In this case you would use ensureNotNull, which smart-casts the value to be not nullable.

suspend fun checkCanConnectDirectChat(
    senderId: Int?,
    receiverId: Int?,
    chatRoomId: Int?
  ) = either {
    ensureNotNull(chatRoomId) {
     BadRequestExceptionResponse(message = ErrorConstants.INVALID_PAYLOAD)
    }

    ensureNotNull(receiverId) {
     BadRequestExceptionResponse(message = ErrorConstants.INVALID_PAYLOAD)
    }
    val isSenderInChat = isUserInChat(chatRoomId, senderId).bind()
    val isReceiverInChat = isUserInChat(chatRoomId, receiverId).bind()
    ensure(isSenderInChat && isReceiverInChat){
      BadRequestExceptionResponse(message = ErrorConstants.INVALID_PAYLOAD)
    }
  }