typescript interface 报错,但是使用 type 就没问题

项目中封装了一个fetch方法,

fetch(url: string, params: Record<string, unknown>, option?: IOption): Promise<any>

第二个参数类型设置为 Record<string, unknown>

之后调用这个 fetch 方法封装了一个请求函数 getMenuTree

type IMenuTreeFilter = {
  super_menu_id?: string | number
  url?: string
  is_display?: 'Y' | 'N'
  for_edit?: boolean
}
/**
 * 获取菜单列表
 * @param {IMenuTreeFilter} filterForm
 * @returns 
 */
const getMenuTree = (filterForm: IMenuTreeFilter) => fetch('/dashboard/DashboardMenuController/menuTree', filterForm, { onlyData: true })

但是如果我用 interface 去声明 IMenuTreeFilter 时编辑器会报错

interface IMenuTreeFilter {
  super_menu_id?: string | number
  url?: string
  is_display?: 'Y' | 'N'
  for_edit?: boolean
}
类型“IMenuTreeFilter”的参数不能赋给类型“Record<string, unknown>”的参数。
类型“IMenuTreeFilter”中缺少类型“string”的索引签名。

不知道这是为啥?

阅读 4.2k
2 个回答

答案在这里:TS中的type、interface关于索引签名的区别

省流:

因interface可声明合并,声明的变量类型可新增属性,不是终态,所以在给有索引签名的类型赋值时,需增加索引签名限定新增属性的类型。而使用type声明的变量类型不可新增属性,已是最终状态,只要其属性符合被赋值变量的类型,就可以直接赋值,不会报错。

原因大概是在这里

TypeScript 的文档中虽然讲到了 interface 和 type 的区别,但并没讲到这一点。

说实在的,我也很疑惑,我一直认为 interface 和 type 没啥区别,直到看到这个问题。从表现来看,interface 比 type 更严格,但是原因不明,查了半天 issue 也没看出来个所以然。都是在讨论现象以及应该怎么样,并没找到讨论到本质上的原因。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进