Make ``JoinedStr`` nodes ``Uninferable`` when the ``FormattedValue`` is ``Uninferable``. (#2944)

Ensure ``ast.JoinedStr`` nodes are ``Uninferable`` when the ``ast.FormattedValue`` is
``Uninferable``. This prevents ``unexpected-keyword-arg`` messages in Pylint
where the ``Uninferable`` string appeared in function arguments that were
constructed dynamically.

Closes pylint-dev/pylint#10822
diff --git a/ChangeLog b/ChangeLog
index 35f673d..37e4b91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,13 @@
 ============================
 Release date: TBA
 
+* Ensure ``ast.JoinedStr`` nodes are ``Uninferable`` when the ``ast.FormattedValue`` is
+  ``Uninferable``. This prevents ``unexpected-keyword-arg`` messages in Pylint
+  where the ``Uninferable`` string appeared in function arguments that were
+  constructed dynamically.
+
+  Closes pylint-dev/pylint#10822
+
 * Add support for type constraints (`isinstance(x, y)`) in inference.
 
   Closes pylint-dev/pylint#1162
diff --git a/astroid/nodes/node_classes.py b/astroid/nodes/node_classes.py
index 7f0887b..88e62fc 100644
--- a/astroid/nodes/node_classes.py
+++ b/astroid/nodes/node_classes.py
@@ -4740,6 +4740,9 @@
                     uninferable_already_generated = True
                 continue
             for value in self.value.infer(context, **kwargs):
+                if value is util.Uninferable:
+                    yield util.Uninferable
+                    return
                 value_to_format = value
                 if isinstance(value, Const):
                     value_to_format = value.value
diff --git a/tests/test_inference.py b/tests/test_inference.py
index 31a4f7d..5f6478a 100644
--- a/tests/test_inference.py
+++ b/tests/test_inference.py
@@ -7154,3 +7154,21 @@
         inferred[0].value.startswith(expected)
     else:
         assert inferred[0] is Uninferable
+
+
+def test_joined_str_uninferable() -> None:
+    """`thing` is not known, therefore the joinedstring should be
+    Uninferable
+    """
+    code = """
+        def hey(thing):
+            return thing
+
+        f"Hello {hey()}"
+    """
+    joined_str = extract_node(code)
+    constant_value, formatted_value = joined_str.values
+    assert constant_value.value == "Hello "
+    assert formatted_value.value.as_string() == "hey()"
+    inferred = next(joined_str.infer())
+    assert inferred is util.Uninferable