You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中实现类似TypeScript映射类型的统一属性类型接口?

Kotlin中实现类似TypeScript映射类型的方案

核心差异说明

TypeScript的[s: string]: number属于字符串索引签名,是动态类型范畴的语法;而Kotlin是静态类型语言,没有直接等价的写法,但可以通过几种方式实现类似需求——让类的所有成员都是数字类型,且能安全遍历这些成员。

方案一:标记接口+反射遍历(接近数据类形式)

先定义一个标记接口标识配置类,再通过反射遍历属性并筛选数字类型的成员:

// 标记接口,仅用于标识这类配置类
interface IConfig

// 数据类实现标记接口,属性用Kotlin的具体数字类型(Int/Float/Double等)
data class ConfigDataClass(val volume: Int, val brightness: Float) : IConfig

// 扩展函数:遍历IConfig实现类的所有数字类型属性
fun IConfig.getNumberProperties(): Map<String, Number> {
    return this::class.memberProperties
        .filter { it.returnType.isSubtypeOf(Number::class.starProjectedType) }
        .associate { prop ->
            prop.name to prop.get(this) as Number
        }
}

// 使用示例
fun main() {
    val config = ConfigDataClass(volume = 70, brightness = 0.6f)
    config.getNumberProperties().forEach { (key, value) ->
        println("$key: $value (类型: ${value::class.simpleName})")
    }
}

优缺点

  • 优点:完全使用Kotlin数据类,保留自动生成的equals/hashCode/toString等特性
  • 缺点:依赖反射,编译期无法强制所有属性都是数字类型(如果数据类里加了非数字属性,运行时才会被过滤掉)

方案二:基于Map的容器类(编译期类型安全)

如果更看重编译期类型安全,直接用Map<String, Number>封装,或者包装成数据类:

// 用数据类包装Map,自动获得数据类特性
data class Config(val properties: Map<String, Number>) {
    // 重载[]运算符,方便取值
    operator fun get(key: String): Number? = properties[key]
    
    // 遍历方法
    fun forEachProperty(action: (String, Number) -> Unit) {
        properties.forEach(action)
    }
}

// 使用示例
fun main() {
    val config = Config(mapOf(
        "volume" to 50,
        "brightness" to 0.8f,
        "contrast" to 90.0
    ))
    
    config.forEachProperty { key, value ->
        println("$key: $value")
    }
}

优缺点

  • 优点:编译期严格保证所有值都是Number子类,无需反射,性能更好
  • 缺点:不像普通数据类那样可以直接用.访问属性,需要通过[]或自定义getter

方案三:编译期校验(KSP实现强制约束)

如果需要编译期强制数据类的所有属性都是数字类型,可以用Kotlin Symbol Processing(KSP)编写注解处理器:

  1. 定义注解:
@Target(AnnotationTarget.CLASS)
annotation class AllNumberProperties
  1. 给数据类添加注解:
@AllNumberProperties
data class ConfigDataClass(val volume: Int, val brightness: Float) : IConfig
  1. 编写KSP处理器,在编译时检查被注解类的所有属性是否都是Number的子类,若存在非数字属性则抛出编译错误。

这种方案实现复杂,但能在编译阶段就避免不符合要求的配置类,适合大型项目。


内容的提问来源于stack exchange,提问作者Karveiani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:57:24