【问题标题】:Avoid duplicate identifier between objects and interfaces in TypeScript避免 TypeScript 中对象和接口之间的重复标识符
【发布时间】:2020-03-20 12:14:25
【问题描述】:

我目前正在使用 TypeScript 开发一个 React 项目,我遇到了一个非常愚蠢的问题,而且非常烦人......

例如,我创建了一个名为 Page 的虚拟组件,它需要 page 类型的 Page 作为道具:

interface Props {
  page: Page
}

export interface Page {
  id: number
  category: PageCategory
  path: string
  name: string
}

const Page: React.FunctionComponent<Props> = (props) => {
  ...
  return (
    ...
    <h1>{ props.page.name }<h1/>
    ...


export default Page

到目前为止没问题,但是一旦我决定导入具有以下类型的组件,它们就会出现:

import Page, { Page } from './component/Page'  // ts-error: 'Duplicate identifier 'Page''

所以为了避免这个问题,我将前缀I 添加到我的所有接口,如IPage,但我确信有一种更优雅的方法可以做到这一点。你是怎么处理的?

【问题讨论】:

  • 您可以在导入时将默认导出命名为您喜欢的任何名称...但真正的解决方案是为不同的事物赋予不同的名称。
  • 已经有issues没有导入:导出的Page得到any类型
  • @AlekseyL。 But real solution is to give different names for different things 是的,但是 Page 类型的另一个名称是什么?因为对象就像一个Page
  • @ford04 我真的不明白这个例子有什么问题?
  • @johannchopin 不清楚您要导出什么,接口 Pageconst Page 冲突在一起。正如 Aleksey 所说,给他们起不同的名字。

标签: reactjs typescript


【解决方案1】:

您的解决方案很接近。只需对两个对象使用相同的导出“样式”,以便您可以将它们一起导入。 Page 将是 Value 和 Type 的别名。

./component/Page.ts

interface Page { ... }
const Page: ...

export default Page

./App.ts

import Page from './component/Page'

const pageData: Page = { id: ... }
const pageComponent = Page 

【讨论】:

  • 这真是一个好问题。我以前也遇到过,我选择了一个解决方法,给它起了另一个名字。但我还是放不下。感谢@johannchopin 的坚持,最后我也看到了这个可以接受的答案。但是,一个问题是使用声明合并意味着我不能将声明与组件分开,它必须在同一个模块中,对吗?它违背了将所有声明放在一个地方的最佳做法。伙计们,有什么适合这个的吗?
【解决方案2】:

主要问题是因为您的界面和组件具有相同的名称,并且您都在导出它。

最简单的解决方案是重命名您的界面/类型。只需添加单词 Props 即可使其仍然有意义(或您喜欢的任何后缀)

interface Props {
  page: PageProps
}

export interface PageProps {
  id: number
  category: PageCategory
  path: string
  name: string
}

const Page: React.FunctionComponent<Props> = (props) => {
  ...
  return (
    ...
    <h1>{ props.page.name }<h1/>
    ...


export default Page

这样导入不会有问题

import Page, { PageProps } from './component/Page'

【讨论】:

  • 是的,我知道:So in order to avoid this problem I added the prefix I to all my interfaces like IPage。但是不鼓励,而且这里没有意义。接口不是Props。它是一个包含来自Page 的所有数据的对象。但称他为PageObject 与称其为IPage 一样有意义,但这不是一个好习惯。
  • @johannchopin 是的,PageObject 确实比PageProps 好而且更好。只要你更改接口的名称(这是我的回答所建议的),你的问题就会得到解决。
  • 你看到我评论的结尾了吗?添加这样的后缀不是一个好习惯,就像使用 I 前缀一样,这是非常不鼓励的。
  • @johannchopin 如果是这种情况,为什么不将您的组件命名为“PageComponent”呢?如果您还认为这是一种“不好的做法”,为什么不创建一个专用于接口的文件,这样您就不必将它与同名的组件一起导出?
  • 是的,我认为重命名 react 组件更有意义。但是后缀Component 也不是一个好习惯。我已经实现了“一个文件用于所有接口”的概念,但是这样做很脏。我发布了一个关于这个主题的问题stackoverflow.com/questions/60740173/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 2018-12-12
  • 2015-02-05
  • 2019-12-11
相关资源
最近更新 更多