typescript索引签名的参数类型(ts interface使用动态键)
在使用ts开发项目的过程中, 我们难免会用到例如object字面量{k: v}结构的形式, 比如在react中的state:
interface State {
page: number; // 页码
total: number; // 总数
}
state = {
page: 1,
total: 100
}
以及还有一种情况: 某一个state它的值的类型是一样的, 只是名字不同, 以不同的名字来表示不同的功能, 比如某一个react tsx页面, 它有多个弹窗, 我们需要用布尔值来控制这些弹窗的显示与否, 但由于是多个弹窗, 需要用多个值为布尔值的state, 此时就联想到了动态键, 就是类似object的动态键: {[k]: v}, 此时这个键名k就可以是一个变量
多番尝试之后得到了我这个需求的state的写法:
interface State {
page: number; // 页码
total: number; // 总数
[modalTypeVisible: string]: any; // 弹窗显示标识
}
[modalTypeVisible: string]: any, modalTypeVisible为state的某一个key, 也可以理解为索引, {}字面量中的索引是key, []字面量的索引则是index, 此例中该索引的类型是字符串, 也就是最终我们会写成这样:
state = {
page: 1,
total: 100,
createTableItemModalVisible: false
}
createTableItemModalVisible(创建表格项弹窗可见性), 这个单词自然是一个字符串, 实际上其他的state的key也都是字符串(至少这个例子中是这样的), 而它的值是布尔值, 这里定义interface的时候为何定义为any呢, 这是因为[modalTypeVisible: string]: any;这个定义实际上的意思是: state的一个key为字符串, 值为any, modalTypeVisible是个变量, 之所以叫这个只是为了便于我们理解它的作用是给模态框显示用的, 实际上可以为任意名字, 相当于这个定义: [xxx: string]: any;相当于是一个通配的定义, 我们的page: 1和total: 100也是符合这个定义的, 实际上我们state的interface写成这样也是可以的:
interface State {
[modalTypeVisible: string]: any;
}
或者
interface State {
[xxx: string]: any;
}
但这样就太笼统或者说太偷懒了, interface的定义太模糊了, 不利于代码的维护, 因此写成这样是比较合适的:
interface State {
page: number; // 页码
total: number; // 总数
//...
[modalTypeVisible: string]: any; // 弹窗显示标识
}
而最后, 这个类型是any而不是boolean, 是为了兼容其他state的类型, 比如我们的interface这么写:
interface State {
page: number; // 页码
total: number; // 总数
//...
[modalTypeVisible: string]: boolean; // 弹窗显示标识
}
将这个值的类型改为boolean, 然后state保持不变:
state = {
page: 1,
total: 100,
createTableItemModalVisible: false
}
那么此时, ts就会给你报错了:
类型“number”的属性“page”不能赋给字符串索引类型“boolean”。ts(2411)
这也从另一个侧面印证了[modalTypeVisible: string]: any;这个写法是一个通配的写法这个结论, 所以标准的写法就是上面提到的这样了:
interface State {
page: number; // 页码
total: number; // 总数
//...
[modalTypeVisible: string]: any; // 弹窗显示标识
}
既保证了我们的动态键的写法, 也给其他的state留出了空间, 方便开发, 也方便后续代码的维护, 最后, 这个any的定义可以写在interface的任何位置, 比如写在第一行:
interface State {
[modalTypeVisible: string]: any; // 弹窗显示标识
page: number; // 页码
total: number; // 总数
//...
}
但我个人还是喜欢写在最后一行, 具体写法因人而异, 喜欢写在哪都行
如果你觉得这篇文章对你有用记得给我点个赞, 或者点个收藏, 众人拾柴, 愿没有难写的代码, 没有难实现的需求
转载自:https://juejin.cn/post/6936006115209510948