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