diff --git a/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api b/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api
index c8b20d5a4..1973b4879 100644
--- a/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api
+++ b/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api
@@ -1182,8 +1182,7 @@ public abstract interface class net/mamoe/mirai/console/command/parse/CommandVal
 }
 
 public final class net/mamoe/mirai/console/command/parse/CommandValueArgumentKt {
-	public static final fun mapToType (Lnet/mamoe/mirai/console/command/parse/CommandValueArgument;Lkotlin/reflect/KType;)Ljava/lang/Object;
-	public static final fun mapToTypeOrNull (Lnet/mamoe/mirai/console/command/parse/CommandValueArgument;Lkotlin/reflect/KType;)Ljava/lang/Object;
+	public static final fun mapToTypeOrNull (Lnet/mamoe/mirai/console/command/parse/CommandValueArgument;Lkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
 	public static final fun mapValue (Lnet/mamoe/mirai/console/command/parse/CommandValueArgument;Lnet/mamoe/mirai/console/command/descriptor/TypeVariant;)Ljava/lang/Object;
 }
 
diff --git a/mirai-console/backend/mirai-console/src/command/descriptor/CommandParameter.kt b/mirai-console/backend/mirai-console/src/command/descriptor/CommandParameter.kt
index df3bbf6ee..be6c5dc83 100644
--- a/mirai-console/backend/mirai-console/src/command/descriptor/CommandParameter.kt
+++ b/mirai-console/backend/mirai-console/src/command/descriptor/CommandParameter.kt
@@ -175,6 +175,15 @@ public sealed class CommandReceiverParameter<T>(
 
 internal val ANY_TYPE = typeOf<Any>()
 internal val ARRAY_OUT_ANY_TYPE = typeOf<Array<out Any?>>()
+internal val BASE_ARRAY_TYPES = mapOf(
+    typeOf<ByteArray>() to typeOf<Byte>(),
+    typeOf<CharArray>() to typeOf<Char>(),
+    typeOf<ShortArray>() to typeOf<Short>(),
+    typeOf<IntArray>() to typeOf<Int>(),
+    typeOf<LongArray>() to typeOf<Long>(),
+    typeOf<FloatArray>() to typeOf<Float>(),
+    typeOf<DoubleArray>() to typeOf<Double>()
+)
 
 @ExperimentalCommandDescriptors
 public sealed class AbstractCommandValueParameter<T> : CommandValueParameter<T>, AbstractCommandParameter<T>() {
@@ -191,8 +200,9 @@ public sealed class AbstractCommandValueParameter<T> : CommandValueParameter<T>,
         commandArgumentContext: CommandArgumentContext?
     ): ArgumentAcceptance {
         if (isVararg) {
-            val arrayElementType = this.type.arguments.single() // Array<T>
-            return acceptingImpl(arrayElementType.type ?: ANY_TYPE, argument, commandArgumentContext)
+            // BaseArray or Array<T>
+            val arrayElementType = BASE_ARRAY_TYPES[this.type] ?: this.type.arguments.single().type
+            return acceptingImpl(arrayElementType ?: ANY_TYPE, argument, commandArgumentContext)
         }
 
         return acceptingImpl(this.type, argument, commandArgumentContext)
@@ -271,7 +281,7 @@ public sealed class AbstractCommandValueParameter<T> : CommandValueParameter<T>,
                 "type.classifier must be KClass."
             }
             if (isVararg)
-                check(type.isSubtypeOf(ARRAY_OUT_ANY_TYPE)) {
+                check(type.isSubtypeOf(ARRAY_OUT_ANY_TYPE) || type in BASE_ARRAY_TYPES) {
                     "type must be subtype of Array if vararg. Given $type."
                 }
         }
diff --git a/mirai-console/backend/mirai-console/src/command/parse/CommandValueArgument.kt b/mirai-console/backend/mirai-console/src/command/parse/CommandValueArgument.kt
index 267424ac7..64f1e09f8 100644
--- a/mirai-console/backend/mirai-console/src/command/parse/CommandValueArgument.kt
+++ b/mirai-console/backend/mirai-console/src/command/parse/CommandValueArgument.kt
@@ -72,42 +72,50 @@ public data class DefaultCommandValueArgument(
 public fun <T> CommandValueArgument.mapValue(typeVariant: TypeVariant<T>): T = typeVariant.mapValue(this.value)
 
 
-@OptIn(ExperimentalStdlibApi::class)
-@ExperimentalCommandDescriptors
-public inline fun <reified T> CommandValueArgument.mapToType(): T =
-    mapToTypeOrNull() ?: throw  NoValueArgumentMappingException(this, typeOf<T>())
-
-@OptIn(ExperimentalStdlibApi::class)
-@ExperimentalCommandDescriptors
-public fun <T> CommandValueArgument.mapToType(type: KType): T =
-    mapToTypeOrNull(type) ?: throw  NoValueArgumentMappingException(this, type)
+//@OptIn(ExperimentalStdlibApi::class)
+//@ExperimentalCommandDescriptors
+//public inline fun <reified T> CommandValueArgument.mapToType(): T =
+//    mapToTypeOrNull() ?: throw  NoValueArgumentMappingException(this, typeOf<T>())
+//
+//@OptIn(ExperimentalStdlibApi::class)
+//@ExperimentalCommandDescriptors
+//public fun <T> CommandValueArgument.mapToType(type: KType): T =
+//    mapToTypeOrNull(type) ?: throw  NoValueArgumentMappingException(this, type)
 
 @ExperimentalCommandDescriptors
-public fun <T> CommandValueArgument.mapToTypeOrNull(expectingType: KType): T? {
-    if (expectingType.isSubtypeOf(ARRAY_OUT_ANY_TYPE)) {
-        val arrayElementType = expectingType.arguments.single().type ?: ANY_TYPE
+public fun <T> CommandValueArgument.mapToTypeOrNull(expectingType: KType, context: (KType, Message) -> T?): T? {
+    if (expectingType.isSubtypeOf(ARRAY_OUT_ANY_TYPE) || expectingType in BASE_ARRAY_TYPES) {
+        val arrayElementType = BASE_ARRAY_TYPES[expectingType] ?: expectingType.arguments.single().type ?: ANY_TYPE
 
         val result = ArrayList<Any?>()
 
         when (val value = value) {
             is MessageChain -> {
                 for (message in value) {
-                    result.add(mapToTypeOrNullImpl(arrayElementType, message))
+                    result.add(mapToTypeOrNullImpl(arrayElementType, message) ?: context(arrayElementType, message))
                 }
             }
             else -> { // single
                 value.castOrInternalError<SingleMessage>()
-                result.add(mapToTypeOrNullImpl(arrayElementType, value))
+                result.add(mapToTypeOrNullImpl(arrayElementType, value) ?: context(arrayElementType, value))
             }
         }
 
-
         @Suppress("UNCHECKED_CAST")
-        return result.toArray(arrayElementType.createArray(result.size)) as T
+        return when (expectingType) {
+            typeOf<ByteArray>() -> (result as List<Byte>).toByteArray()
+            typeOf<CharArray>() -> (result as List<Char>).toCharArray()
+            typeOf<ShortArray>() -> (result as List<Short>).toShortArray()
+            typeOf<IntArray>() -> (result as List<Int>).toIntArray()
+            typeOf<LongArray>() -> (result as List<Long>).toLongArray()
+            typeOf<FloatArray>() -> (result as List<Float>).toFloatArray()
+            typeOf<DoubleArray>() -> (result as List<Double>).toDoubleArray()
+            else -> result.toArray(arrayElementType.createArray(result.size))
+        } as T?
     }
 
     @Suppress("UNCHECKED_CAST")
-    return mapToTypeOrNullImpl(expectingType, value) as T
+    return (mapToTypeOrNullImpl(expectingType, value) ?: context(expectingType, value)) as T?
 }
 
 private fun KType.createArray(size: Int): Array<Any?> {
@@ -131,8 +139,8 @@ private fun CommandValueArgument.mapToTypeOrNullImpl(expectingType: KType, value
     return result.mapValue(value)
 }
 
-@ExperimentalCommandDescriptors
-public inline fun <reified T> CommandValueArgument.mapToTypeOrNull(): T? {
-    @OptIn(ExperimentalStdlibApi::class)
-    return mapToTypeOrNull(typeOf<T>())
-}
\ No newline at end of file
+//@ExperimentalCommandDescriptors
+//public inline fun <reified T> CommandValueArgument.mapToTypeOrNull(): T? {
+//    @OptIn(ExperimentalStdlibApi::class)
+//    return mapToTypeOrNull(typeOf<T>())
+//}
\ No newline at end of file
diff --git a/mirai-console/backend/mirai-console/src/command/resolve/ResolvedCommandCall.kt b/mirai-console/backend/mirai-console/src/command/resolve/ResolvedCommandCall.kt
index 401330c21..641094d06 100644
--- a/mirai-console/backend/mirai-console/src/command/resolve/ResolvedCommandCall.kt
+++ b/mirai-console/backend/mirai-console/src/command/resolve/ResolvedCommandCall.kt
@@ -104,12 +104,10 @@ public class ResolvedCommandCallImpl(
 ) : ResolvedCommandCall {
     override val resolvedValueArguments: List<ResolvedCommandValueArgument<*>> by lazy {
         calleeSignature.valueParameters.zip(rawValueArguments).map { (parameter, argument) ->
-            val value = argument.mapToTypeOrNull(parameter.type) ?: context[parameter.type.classifierAsKClass()]?.parse(
-                argument.value,
-                caller
-            )
-            ?: throw  NoValueArgumentMappingException(argument, parameter.type)
-            // TODO: 2020/10/17 consider vararg and optional
+            val value = argument.mapToTypeOrNull(parameter.type) { type, message ->
+                context[type.classifierAsKClass()]?.parse(message, caller)
+            } ?: throw NoValueArgumentMappingException(argument, parameter.type)
+
             ResolvedCommandValueArgument(parameter.cast(), value)
         }
     }
diff --git a/mirai-console/backend/mirai-console/test/command/InstanceTestCommand.kt b/mirai-console/backend/mirai-console/test/command/InstanceTestCommand.kt
index b065f13f7..2cc6f3fd9 100644
--- a/mirai-console/backend/mirai-console/test/command/InstanceTestCommand.kt
+++ b/mirai-console/backend/mirai-console/test/command/InstanceTestCommand.kt
@@ -676,36 +676,213 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
                     assertEquals(1, arg1)
                     Testing.ok(x)
                 }
+
+                @SubCommand
+                fun enum(arg1: Int, vararg y: TestEnumArgCommand.TestEnum) {
+                    assertEquals(1, arg1)
+                    Testing.ok(y)
+                }
+
+                @SubCommand
+                fun long(arg1: String, vararg z: Long) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
+
+                @SubCommand
+                fun int(arg1: String, vararg z: Int) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
+
+                @SubCommand
+                fun byte(arg1: String, vararg z: Byte) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
+
+                @SubCommand
+                fun short(arg1: String, vararg z: Short) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
+
+                @SubCommand
+                fun float(arg1: String, vararg z: Float) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
+
+                @SubCommand
+                fun double(arg1: String, vararg z: Double) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
+
+                @SubCommand
+                fun char(arg1: String, vararg z: Char) {
+                    assertEquals("arg1", arg1)
+                    Testing.ok(z)
+                }
             }
             optionCommand.withRegistration {
-                assertArrayEquals(
+                // Array<String>
+                assertContentEquals(
                     emptyArray<String>(),
                     withTesting {
                         assertSuccess(sender.executeCommand("/test vararg 1"))
                     }
                 )
-
-                assertArrayEquals(
+                assertContentEquals(
                     arrayOf("s"),
                     withTesting<Array<String>> {
                         assertSuccess(sender.executeCommand("/test vararg 1 s"))
                     }
                 )
-                assertArrayEquals(
+                assertContentEquals(
                     arrayOf("s", "s", "s"),
                     withTesting {
                         assertSuccess(sender.executeCommand("/test vararg 1 s s s"))
                     }
                 )
+                // Array<TestEnum>
+                assertContentEquals(
+                    emptyArray<TestEnumArgCommand.TestEnum>(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test enum 1"))
+                    }
+                )
+                assertContentEquals(
+                    arrayOf(TestEnumArgCommand.TestEnum.V1),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test enum 1 ${TestEnumArgCommand.TestEnum.V1}"))
+                    }
+                )
+                assertContentEquals(
+                    TestEnumArgCommand.TestEnum.values(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test enum 1 ${TestEnumArgCommand.TestEnum.values().joinToString(" ")}"))
+                    }
+                )
+                // LongArray
+                assertContentEquals(
+                    longArrayOf(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test long arg1"))
+                    }
+                )
+                assertContentEquals(
+                    longArrayOf(1),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test long arg1 1"))
+                    }
+                )
+                assertContentEquals(
+                    longArrayOf(1, 2, 3),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test long arg1 1 2 3"))
+                    }
+                )
+                // IntArray
+                assertContentEquals(
+                    intArrayOf(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test int arg1"))
+                    }
+                )
+                assertContentEquals(
+                    intArrayOf(1),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test int arg1 1"))
+                    }
+                )
+                assertContentEquals(
+                    intArrayOf(1, 2, 3),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test int arg1 1 2 3"))
+                    }
+                )
+                // ByteArray
+                assertContentEquals(
+                    byteArrayOf(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test byte arg1"))
+                    }
+                )
+                assertContentEquals(
+                    byteArrayOf(1),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test byte arg1 1"))
+                    }
+                )
+                assertContentEquals(
+                    byteArrayOf(1, 2, 3),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test byte arg1 1 2 3"))
+                    }
+                )
+                // ShortArray
+                assertContentEquals(
+                    shortArrayOf(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test short arg1"))
+                    }
+                )
+                assertContentEquals(
+                    shortArrayOf(1),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test short arg1 1"))
+                    }
+                )
+                assertContentEquals(
+                    shortArrayOf(1, 2, 3),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test short arg1 1 2 3"))
+                    }
+                )
+                // FloatArray
+                assertContentEquals(
+                    floatArrayOf(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test float arg1"))
+                    }
+                )
+                assertContentEquals(
+                    floatArrayOf(1.0F),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test float arg1 1"))
+                    }
+                )
+                assertContentEquals(
+                    floatArrayOf(1.0F, 1.5F, 2.0F),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test float arg1 1 1.5 2"))
+                    }
+                )
+                // DoubleArray
+                assertContentEquals(
+                    doubleArrayOf(),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test double arg1"))
+                    }
+                )
+                assertContentEquals(
+                    doubleArrayOf(1.0),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test double arg1 1"))
+                    }
+                )
+                assertContentEquals(
+                    doubleArrayOf(1.0, 1.5, 2.0),
+                    withTesting {
+                        assertSuccess(sender.executeCommand("/test double arg1 1 1.5 2"))
+                    }
+                )
             }
         }
     }
 }
 
-fun <T> assertArrayEquals(expected: Array<out T>, actual: Array<out T>, message: String? = null) {
-    asserter.assertEquals(message, expected.contentToString(), actual.contentToString())
-}
-
 @OptIn(ExperimentalCommandDescriptors::class)
 internal fun assertSuccess(result: CommandExecuteResult) {
     if (result.isFailure()) {