likes
comments
collection
share

typescript索引签名的参数类型(ts interface使用动态键)

作者站长头像
站长
· 阅读数 48

在使用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, modalTypeVisiblestate的某一个key, 也可以理解为索引, {}字面量中的索引是key, []字面量的索引则是index, 此例中该索引的类型是字符串, 也就是最终我们会写成这样:

state = {
  page: 1,
  total: 100,
  createTableItemModalVisible: false
}

createTableItemModalVisible(创建表格项弹窗可见性), 这个单词自然是一个字符串, 实际上其他的statekey也都是字符串(至少这个例子中是这样的), 而它的值是布尔值, 这里定义interface的时候为何定义为any呢, 这是因为[modalTypeVisible: string]: any;这个定义实际上的意思是: state的一个key为字符串, 值为any, modalTypeVisible是个变量, 之所以叫这个只是为了便于我们理解它的作用是给模态框显示用的, 实际上可以为任意名字, 相当于这个定义: [xxx: string]: any;相当于是一个通配的定义, 我们的page: 1total: 100也是符合这个定义的, 实际上我们stateinterface写成这样也是可以的:

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
评论
请登录