diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index 9b8c1b28a..78a324337 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -276,8 +276,11 @@ class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], Mutab
         self.held_object.prepend(name, values, kwargs['separator'])
 
 
+_CONF_DATA_SET_KWS: KwargInfo[T.Optional[str]] = KwargInfo('description', (str, NoneType))
+
+
 class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
-    def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Any]] = None) -> None:
+    def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Union[str, int, bool]]] = None) -> None:
         self.used = False # These objects become immutable after use in configure_file.
         super().__init__(subproject=subproject)
         self.conf_data = build.ConfigurationData()
@@ -302,51 +305,28 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
     def mark_used(self) -> None:
         self.used = True
 
-    def validate_args(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Tuple[str, T.Union[str, int, bool], T.Optional[str]]:
-        if len(args) == 1 and isinstance(args[0], list) and len(args[0]) == 2:
-            mlog.deprecation('Passing a list as the single argument to '
-                             'configuration_data.set is deprecated. This will '
-                             'become a hard error in the future.',
-                             location=self.current_node)
-            args = args[0]
-
-        if len(args) != 2:
-            raise InterpreterException("Configuration set requires 2 arguments.")
+    def __check_used(self) -> None:
         if self.used:
             raise InterpreterException("Can not set values on configuration object that has been used.")
-        name, val = args
-        if not isinstance(val, (int, str)):
-            msg = f'Setting a configuration data value to {val!r} is invalid, ' \
-                  'and will fail at configure_file(). If you are using it ' \
-                  'just to store some values, please use a dict instead.'
-            mlog.deprecation(msg, location=self.current_node)
-        desc = kwargs.get('description', None)
-        if not isinstance(name, str):
-            raise InterpreterException("First argument to set must be a string.")
-        if desc is not None and not isinstance(desc, str):
-            raise InterpreterException('Description must be a string.')
-
-        # TODO: Remove the cast once we get rid of the deprecation
-        return name, T.cast(T.Union[str, bool, int], val), desc
 
-    @noArgsFlattening
-    def set_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
-        (name, val, desc) = self.validate_args(args, kwargs)
-        self.conf_data.values[name] = (val, desc)
-
-    def set_quoted_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
-        (name, val, desc) = self.validate_args(args, kwargs)
-        if not isinstance(val, str):
-            raise InterpreterException("Second argument to set_quoted must be a string.")
-        escaped_val = '\\"'.join(val.split('"'))
-        self.conf_data.values[name] = ('"' + escaped_val + '"', desc)
-
-    def set10_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
-        (name, val, desc) = self.validate_args(args, kwargs)
-        if val:
-            self.conf_data.values[name] = (1, desc)
-        else:
-            self.conf_data.values[name] = (0, desc)
+    @typed_pos_args('configuration_data.set', str, (str, int, bool))
+    @typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS)
+    def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
+        self.__check_used()
+        self.conf_data.values[args[0]] = (args[1], kwargs['description'])
+
+    @typed_pos_args('configuration_data.set_quoted', str, str)
+    @typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS)
+    def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None:
+        self.__check_used()
+        escaped_val = '\\"'.join(args[1].split('"'))
+        self.conf_data.values[args[0]] = (f'"{escaped_val}"', kwargs['description'])
+
+    @typed_pos_args('configuration_data.set10', str, (int, bool))
+    @typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS)
+    def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
+        self.__check_used()
+        self.conf_data.values[args[0]] = (int(args[1]), kwargs['description'])
 
     @typed_pos_args('configuration_data.has', (str, int, bool))
     @noKwargs
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index 8a8837507..777db129c 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -261,3 +261,8 @@ class DependencyGetVariable(TypedDict):
     internal: T.Optional[str]
     default_value: T.Optional[str]
     pkgconfig_define: T.List[str]
+
+
+class ConfigurationDataSet(TypedDict):
+
+    description: T.Optional[str]
diff --git a/test cases/common/14 configure file/meson.build b/test cases/common/14 configure file/meson.build
index 416dad7fa..91a56ff62 100644
--- a/test cases/common/14 configure file/meson.build	
+++ b/test cases/common/14 configure file/meson.build	
@@ -275,9 +275,6 @@ configure_file(
 
 test('configure-file', test_file)
 
-cdata = configuration_data()
-cdata.set('invalid_value', ['array'])
-
 # Dictionaries
 
 cdata = configuration_data({
diff --git a/test cases/common/187 args flattening/meson.build b/test cases/common/187 args flattening/meson.build
index 1dac2f912..61d77e452 100644
--- a/test cases/common/187 args flattening/meson.build	
+++ b/test cases/common/187 args flattening/meson.build	
@@ -6,13 +6,6 @@ assert(arr == ['bar', 'baz'], 'get_variable with array fallback is broken')
 set_variable('arr', ['bar', 'baz'])
 assert(arr == ['bar', 'baz'], 'set_variable(array) is broken')
 
-conf = configuration_data()
-conf.set('foo', ['bar', 'baz'])
-assert(conf.get('foo') == ['bar', 'baz'], 'configuration_data.set(array) is broken')
-
-arr = conf.get('does-not-exist', ['bar', 'baz'])
-assert(arr == ['bar', 'baz'], 'configuration_data.get with array fallback is broken')
-
 arr = meson.get_cross_property('does-not-exist', ['bar', 'baz'])
 assert(arr == ['bar', 'baz'], 'meson.get_cross_property with array fallback is broken')
 
@@ -27,5 +20,6 @@ assert(arr == ['bar', 'baz'], 'meson.get_external_property native:false with arr
 
 # Test deprecated behaviour
 
+conf = configuration_data()
 conf.set(['foo', 'bar'])
 message(conf.get('foo'))
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index e6c792227..51ca7a033 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -2306,7 +2306,6 @@ class AllPlatformTests(BasePlatformTests):
             self.assertEqual(f.read().strip(), b'/* #undef FOO_BAR */')
         with open(os.path.join(self.builddir, 'nosubst-nocopy2.txt'), 'rb') as f:
             self.assertEqual(f.read().strip(), b'')
-        self.assertRegex(out, r"DEPRECATION:.*\['array'\] is invalid.*dict")
 
     def test_dirs(self):
         with tempfile.TemporaryDirectory() as containing: