diff --git a/packages/cdktf/lib/tfExpression.ts b/packages/cdktf/lib/tfExpression.ts index 327b20c5bb..4b1338576a 100644 --- a/packages/cdktf/lib/tfExpression.ts +++ b/packages/cdktf/lib/tfExpression.ts @@ -36,7 +36,13 @@ class TFExpression extends Intrinsic implements IResolvable { const resolvedArg = context.resolve(arg); if (typeof arg === "string") { - return this.resolveString(arg, resolvedArg); + const str = this.resolveString(arg, resolvedArg); + // When Token.asString() is used on an object, str will be the object and needs to be resolved differently + // This happens for example in MapTerraformIterator#_getForEachExpression and can cause issues like #3540 + if (typeof str !== "string") { + return this.resolveExpressionPart(context, str); + } + return str; } return this.resolveExpressionPart(context, arg); diff --git a/packages/cdktf/test/tfExpression.test.ts b/packages/cdktf/test/tfExpression.test.ts index e1843bc509..c84db653a2 100644 --- a/packages/cdktf/test/tfExpression.test.ts +++ b/packages/cdktf/test/tfExpression.test.ts @@ -270,3 +270,10 @@ test("nesting can undo the wrapping", () => { `"\${x(docker_container.foo.bar, "this is the ref: \${y("my ref: \${docker_container.foo.bar}", docker_container.foo.bar)}")}"` ); }); + +test("expressions correctly resolve string wrapped objects", () => { + const expr = call("keys", [Token.asString({ a: "b" })]); + expect(resolveExpression(expr)).toMatchInlineSnapshot( + `"\${keys({"a" = "b"})}"` + ); +});