如何避免在模块声明中重复类型定义?
How do I avoid repeating type definitions in module declarations?
免责声明: 总的来说,我对 Flow 和静态类型还是有些陌生,所以我很可能忽略了一些东西 easy/obvious这个问题。
假设我有一个名为 my-library
的图书馆。该库向其用户公开一个模块 index.js
,它导入几个其他模块(moduleA.js
和 moduleB.js
)供内部使用。
我想将 Flow 与此库一起使用,既用于我自己的内部开发,也用于 index.js.flow
文件中,该文件为同样使用 Flow 的库用户提供模块声明。所以文件结构看起来像这样:
- index.js
- index.js.flow (contains the module declaration for library users)
- moduleA.js
- moduleA.js.flow (just exported type definitions, no module declaration)
- moduleB.js
- moduleB.js.flow (just exported type definitions, no module declaration)
问题是 index.js.flow
模块声明需要使用来自 moduleA.js.flow
和 moduleB.js.flow
的类型。 (我有 moduleA.js.flow
和 moduleB.js.flow
而不是直接在 .js 文件中定义类型的原因是 .js 文件中的类型定义将被 Babel 删除,我希望它们对于图书馆用户来说仍然存在于某个地方。
我知道以下内容不会对导入的外部 JS 进行类型检查 my-module
:
index.js.flow(这个不行)
import type { SomeType } from './moduleA'
declare module 'my-module' {
declare function exports(): {
someMethod: () => SomeType
}
}
SomeType 在导入时在模块声明中似乎不可用,但在本地定义它确实有效:
index.js.flow(有效)
export type SomeType = string
declare module 'my-module' {
declare function exports(): {
someMethod: () => SomeType
}
}
所以一种解决方案是只定义和导出 index.js.flow
中的所有类型,然后 moduleA.js
和 moduleB.js
导入它们(而不包括 .js.flow
文件对于 moduleA
和 moduleB
),但是将所有类型定义都放在根流文件中而不是 .js.flow
文件中与这些类型源自的模块相匹配似乎很奇怪。
或者,我知道我可以在各自的开发模块中定义类型,然后在 index.js.flow
模块声明中再次定义它们,但我不想在中重复类型定义如果可能的话,两个不同的地方。
如果您能帮助我找出最好的组织方式,我将不胜感激。 (再一次,我知道我很有可能在做一些愚蠢的事情或忽略了一些明显的事情。)
.js.flow
文件的目的是完全 与您实施中相应的 .js
文件一样,除了[=41] =] 它们不是由 Babel 翻译的。特别是,它们就像相应的 .js
文件一样导入和导出内容。此外,就像 .js
文件根据其在文件系统中的位置自动与模块关联一样,.js.flow
文件也是如此。
按照问题中的例子,假设 index.js
的 module.exports
是一个函数,returns 一个包含 属性 someMethod
的对象类型 () => SomeType
,其中类型 SomeType
由 moduleA.js
导出。然后我们可以在 index.js.flow
中有以下内容:
// @flow
import type { SomeType } from './moduleA'
declare module.exports: () => {
someMethod: () => SomeType;
};
以及 moduleA.js.flow
中的以下内容:
// @flow
export type SomeType = string;
假设我们将 index.js.flow
和 moduleA.js.flow
放在 src/node_modules/my-module/
中,我们可以通过在 src/
中的 test.js
中添加以下内容来测试我们的设置是否正确]:
// @flow
var foo = require('my-module');
(foo().someMethod(): number); // error (string incompatible with number)
免责声明: 总的来说,我对 Flow 和静态类型还是有些陌生,所以我很可能忽略了一些东西 easy/obvious这个问题。
假设我有一个名为 my-library
的图书馆。该库向其用户公开一个模块 index.js
,它导入几个其他模块(moduleA.js
和 moduleB.js
)供内部使用。
我想将 Flow 与此库一起使用,既用于我自己的内部开发,也用于 index.js.flow
文件中,该文件为同样使用 Flow 的库用户提供模块声明。所以文件结构看起来像这样:
- index.js
- index.js.flow (contains the module declaration for library users)
- moduleA.js
- moduleA.js.flow (just exported type definitions, no module declaration)
- moduleB.js
- moduleB.js.flow (just exported type definitions, no module declaration)
问题是 index.js.flow
模块声明需要使用来自 moduleA.js.flow
和 moduleB.js.flow
的类型。 (我有 moduleA.js.flow
和 moduleB.js.flow
而不是直接在 .js 文件中定义类型的原因是 .js 文件中的类型定义将被 Babel 删除,我希望它们对于图书馆用户来说仍然存在于某个地方。
我知道以下内容不会对导入的外部 JS 进行类型检查 my-module
:
index.js.flow(这个不行)
import type { SomeType } from './moduleA'
declare module 'my-module' {
declare function exports(): {
someMethod: () => SomeType
}
}
SomeType 在导入时在模块声明中似乎不可用,但在本地定义它确实有效:
index.js.flow(有效)
export type SomeType = string
declare module 'my-module' {
declare function exports(): {
someMethod: () => SomeType
}
}
所以一种解决方案是只定义和导出 index.js.flow
中的所有类型,然后 moduleA.js
和 moduleB.js
导入它们(而不包括 .js.flow
文件对于 moduleA
和 moduleB
),但是将所有类型定义都放在根流文件中而不是 .js.flow
文件中与这些类型源自的模块相匹配似乎很奇怪。
或者,我知道我可以在各自的开发模块中定义类型,然后在 index.js.flow
模块声明中再次定义它们,但我不想在中重复类型定义如果可能的话,两个不同的地方。
如果您能帮助我找出最好的组织方式,我将不胜感激。 (再一次,我知道我很有可能在做一些愚蠢的事情或忽略了一些明显的事情。)
.js.flow
文件的目的是完全 与您实施中相应的 .js
文件一样,除了[=41] =] 它们不是由 Babel 翻译的。特别是,它们就像相应的 .js
文件一样导入和导出内容。此外,就像 .js
文件根据其在文件系统中的位置自动与模块关联一样,.js.flow
文件也是如此。
按照问题中的例子,假设 index.js
的 module.exports
是一个函数,returns 一个包含 属性 someMethod
的对象类型 () => SomeType
,其中类型 SomeType
由 moduleA.js
导出。然后我们可以在 index.js.flow
中有以下内容:
// @flow
import type { SomeType } from './moduleA'
declare module.exports: () => {
someMethod: () => SomeType;
};
以及 moduleA.js.flow
中的以下内容:
// @flow
export type SomeType = string;
假设我们将 index.js.flow
和 moduleA.js.flow
放在 src/node_modules/my-module/
中,我们可以通过在 src/
中的 test.js
中添加以下内容来测试我们的设置是否正确]:
// @flow
var foo = require('my-module');
(foo().someMethod(): number); // error (string incompatible with number)