[swift] Type of expression is ambiguous without more context Swift

I am getting a 'Type of expression is ambiguous without more context ' on this part of code from a project I am trying to upgrade to latest Swift version. I can't seem to figure it out. I tried different things but can't get it to work.

The problem is on the syntax of this line

let imageToDeleteParameters  = imagesToDelete.map { ["id": $0.id, "url": $0.url.absoluteString, "_destroy": true] }

Full code:

extension TutorialCreationRequest: WebserviceParametrable {
    func toParameters() -> [String: AnyObject] {
        let imageParameters = images.map { ["url": $0] }
        let imageToDeleteParameters  = imagesToDelete.map { ["id": $0.id, "url": $0.url.absoluteString, "_destroy": true] }
        return [
            "title": title,
            "is_draft": isDraft,
            "difficulty": difficulty,
            "duration": duration,
            "cost": cost,
            "user_id": userId,
            "description": description,
            "to_sell": toSell,
            "images": [imageParameters, imageToDeleteParameters].flatMap { $0 }
        ]
    }
}

This question is related to swift swift3

The answer is


The compiler can't figure out what type to make the Dictionary, because it's not homogenous. You have values of different types. The only way to get around this is to make it a [String: Any], which will make everything clunky as all hell.

return [
    "title": title,
    "is_draft": isDraft,
    "difficulty": difficulty,
    "duration": duration,
    "cost": cost,
    "user_id": userId,
    "description": description,
    "to_sell": toSell,
    "images": [imageParameters, imageToDeleteParameters].flatMap { $0 }
] as [String: Any]

This is a job for a struct. It'll vastly simplify working with this data structure.


This can happen if any part of your highlighted method or property is attempting to access a property or method with the incorrect type.

Here is a troubleshooting checklist:

  • Make sure the type of arguments match in the call site and implementation.
  • Make sure the argument names match in the call site and implementation.
  • Make sure the method name matches in the call site and implementation.
  • Make sure the returned value of a property or method matches in the usage and implementation (ie: enumerated())
  • Make sure you don't have a duplicated method with potentially ambiguous types such as with protocols or generics.
  • Make sure the compiler can infer the correct type when using type inference.

A Strategy

  • Try breaking apart your method into a greater number of simpler method/implementations.

For example, lets say you are running compactMap on an array of custom Types. In the closure you are passing to the compactMap method, you initialize and return another custom struct. When you get this error, it is difficult to tell which part of your code is offending.

  • For debugging purposes, you can use a for loop instead of compactMap.
  • instead of passing the arguments, directly, you can assign them to constants in the for loop.

By this point, you may come to a realization, such as, instead of the property you thought you wanted to assign actually had a property on it that had the actual value you wanted to pass.


In my case, this error message shown when I don't added optional property to constructor.

struct Event: Identifiable, Codable {

    var id: String
    var summary: String
    var description: String?
    // also has other props...

    init(id: String, summary: String, description: String?){
        self.id = id
        self.summary = summary
        self.description = description
    }
}

// skip pass description
// It show message "Type of expression is ambiguous without more context"
Event(
    id: "1",
    summary: "summary",
)

// pass description explicity pass nil to description
Event(
    id: "1",
    summary: "summary",
    description: nil
)

but it looks always not occured.

I test in my playground this code, it show warning about more concrete

var str = "Hello, playground"
struct User {
    var id: String
    var name: String?
    init(id: String, name: String?) {
        self.id = id
        self.name = name
    }
}

User(id: "hoge") // Missing argument for parameter 'name' in call

Not an answer to this question, but as I came here looking for the error others might find this also useful:

For me, I got this Swift error when I tried to use the for (index, object) loop on an array without adding the .enumerated() part ...


This might not be very applicable to others, but my problem was that the changes I made was NOT saved yet! Press CMD + S and save your work before building on top of it.


As theEye's answer it is not an answer to this question, but as I also came here looking for the error im posting my case as others might find this also useful:

I got this error message when I was by error trying to calculate a value of two different types.

In my case I was trying to divide a CGFloat by a Double


In my case it happened with NSFetchedResultsController and the reason was that I defined the NSFetchedResultsController for a different model than I created the request for the initialization (RemotePlaylist vs. Playlist):

  var fetchedPlaylistsController:NSFetchedResultsController<RemotePlaylist>!

but initiated it with a request for another Playlist:

let request = Playlist.createFetchRequest()
fetchedPlaylistsController = NSFetchedResultsController(fetchRequest: request, ...

This happens when you have a function with wrong argument names.

Example:

functionWithArguments(argumentNameWrong: , argumentName2: )

and You declared your function as:

functionWithArguments(argumentName1: , argumentName2: ){}

This usually happens when you changed the name of a Variable. Make sure you refactor when you do that.


I had this message when the type of a function parameter didn't fit. In my case it was a String instead of an URL.


For me the case was Type inference I have changed the function parameters from int To float but did not update the calling code, and the compiler did not warn me on wrong type passed to the function

Before

func myFunc(param:Int, parma2:Int) {}

After

func myFunc(param:Float, parma2:Float) {}

Calling code with error

var param1:Int16 = 1
var param2:Int16 = 2
myFunc(param:param1, parma2:param2)// error here: Type of expression is ambiguous without more context

To fix:

var param1:Float = 1.0f
var param2:Float = 2.0f
myFunc(param:param1, parma2:param2)// ok!

Explicitly declaring the inputs for that mapping function should do the trick:

let imageToDeleteParameters  = imagesToDelete.map {
    (whatever : WhateverClass) -> Dictionary<String, Any> in
    ["id": whatever.id, "url": whatever.url.absoluteString, "_destroy": true]
}

Substitute the real class of "$0" for "WhateverClass" in that code snippet, and it should work.


You have two " " before the =

let imageToDeleteParameters = imagesToDelete.map { ["id": $0.id, "url": $0.url.absoluteString, "_destroy": true] }

I got this error when I put a space before a comma in the parameters when calling a function.

eg, I used:

myfunction(parameter1: parameter1 , parameter2: parameter2)

Whereas it should have been:

myfunction(parameter1: parameter1, parameter2: parameter2)

Deleting the space got rid of the error message