Home > Back-end >  Inferring the type of the return of a function from one of the inputs to that function
Inferring the type of the return of a function from one of the inputs to that function

Time:02-01

In our app we have an enum defined that covers all the back end endpoints that can be hit by the app...

enum Route {
  case todo(TodoRoute)
  case event(EventRoute)
  case userDetails

  enum TodoRoute {
    case create
    case delete(Todo)
  }

  case EventRoute {
    case list
    case edit(Event)
  }
}

These get translated into the individual endpoints and parameters and so on.

So we have a couple of functions on our ApiClient like this that eventually make the network call...

public func request<A: Decodable>(
    _ route: Route,
    as: A.Type
) async throws -> A {
    let (data, _) = try await self.request(route)
    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        return try decoder.decode(A.self, from: data)
    } catch {
        throw error
    }
}

public func request<A: Decodable>(
    _ route: Route
) async throws -> A {
    let (data, _) = try await self.request(route)
    do {
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601
        return try decoder.decode(A.self, from: data)
    } catch {
        throw error
    }
}

As you can see, these decode the returned data into a particular generic type.

So at the call site it looks like one of these...

// 1. 
let result = try await apiClient.request(.userDetails, as: UserDetails.self)

// 2.
let result: EventList = try await apiClient.request(.event(.list))

These work but I'm trying to find a way to embed the type to be decoded into the function call itself.

Each endpoint we call will only return one type of JSON so there is a 1:1 mapping between our Route cases and the type returned by the function. So rather than having to explicitly define both the route AND the type in the function it should be possible to only provide the route and have the type inferred. Something like this...

let result = try await apiClient.request(.event(.list))

And have the type of result inferred from the Route passed into the function.

Perhaps this just isn't possible?

I was thinking of having a function on the route like route.resourceType or something? So the function can infer what T is from that? Or something?

Hmm... as I type I'm thinking that isn't possible?

Is it possible to make such and type inference work?

CodePudding user response:

Just to make it clear this is answered.

As @RobNapier pointed out. Inferring a type based on a value is not something that is a feature within Swift. Although it does exist in other languages. It’s not one to wait for in Swift.

https://en.wikipedia.org/wiki/Dependent_type

  • Related