TypeScript: XXX has or is using name 'Foo' from external module "../bar" but cannot be named
TypeScript Version: 2.0.0
npm init
npm install clime --save
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noEmitOnError": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"strictNullChecks": true,
"declaration": true,
"sourceMap": true,
"rootDir": "src",
"outDir": "bld"
},
"exclude": [
"node_modules"
]
}
src/cli.ts
#!/usr/bin/env node
import * as Path from 'path';
import { CLI, Shim } from 'clime';
let cli = new CLI('henge', Path.join(__dirname, 'commands'));
// This is okay.
export default cli;
// This gives errors:
// TS4023: Exported variable 'foo' has or is using name 'Promise' from external module "C:/Projects/clime/node_modules/thenfail/bld/promise" but cannot be named.
// TS4023: Exported variable 'foo' has or is using name 'Printable' from external module "C:/Projects/clime/bld/core/object" but cannot be named.
let foo = cli.execute([]);
export { foo };
It seems that if I import Printable from clime, the second error would go away, but I cannot import Promise from the dependency of clime.
Is this expected behavior or a bug?
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 150
- Comments: 64 (16 by maintainers)
Commits related to this issue
- https://github.com/Microsoft/TypeScript/issues/9944 compact selenium-webdriver types v2, hope @types v3 will publish soon — committed to wechaty/wechaty by huan 8 years ago
- refactor: Removes attempts to have all exports in one file. All exports in one file caused a lot of issues: Microsoft/TypeScript#9944. BREAKING CHANGE: No longer supporting exports from one file, im... — committed to js-entity-repos/core by ryasmi 7 years ago
- Remove AbstractCheckboxChangeEvent, fix TS4029 error See https://github.com/Microsoft/TypeScript/issues/9944 — committed to ant-design/ant-design by yesmeck 6 years ago
- Add the defaultActiveTabKey property for the Card component (#9526) * Add the defaultActiveTabKey property for the Card component (close #8789, #8942) * `activeTabKey` should be added * Improve... — committed to ant-design/ant-design by u3u 6 years ago
- fixed ts declaration issue XXX has or is using name 'Foo' from external module "../bar" but cannot be named see: https://github.com/Microsoft/TypeScript/issues/9944 — committed to ruanyl/universal-data-loader by ruanyl 6 years ago
- remove unused imports * since https://github.com/Microsoft/TypeScript/issues/9944 has been resolved — committed to vladimiry/fs-no-eperm-anymore by vladimiry 5 years ago
- fix: export interface — committed to monkindey/uform by monkindey 5 years ago
- Be explicit about return types to avoid tsc complaints See https://github.com/microsoft/TypeScript/issues/9944 — committed to evanpurkhiser/prolink-connect by evanpurkhiser 4 years ago
- Update mixins to avoid compilation issues The following 2 issues appears internally: https://github.com/microsoft/TypeScript/issues/15870 https://github.com/microsoft/TypeScript/issues/9944 Change-I... — committed to GerritCodeReview/gerrit by gdmfilippov 4 years ago
- Update mixins to avoid compilation issues The following 2 issues appears internally: https://github.com/microsoft/TypeScript/issues/15870 https://github.com/microsoft/TypeScript/issues/9944 Change-I... — committed to GerritCodeReview/gerrit by gdmfilippov 4 years ago
- Remove RuntypeName Symbol for branded types. It was breaking the declaration feature See: https://github.com/microsoft/TypeScript/issues/9944 — committed to TheryFouchter/runtypes by TheryFouchterEpitech 4 years ago
Please consider adding adding imports to resolve this error. This is an error which comes up daily in our workflow with TypeScript and would be easier for us if this was never an issue again.
š
Just came across this issue today after upgrading Angular-CLI.
Needless to say, from my perspective as a ānaiveā developer, the requirement that implicitly used interfaces be imported everywhere has the serious downside of poor developer tooling support. At least in WebStorm using the TypeScript service, the imported interfaces are shown as being unused and thus subject to removal by other developers or automatic removal whenever Optimize Imports is executed. Aside from that it is extremely non-obvious, from the wording of the error message, how the problem can be fixed.
There is no explicit type annotation on the functions or variables. the declaration emitter infers their type and tries to write it. if the type is coming from a different module, then a. it needs to add an import or b. error.
The emitter can write the additional import, but that would have been changing your API shape in a way you did not indicate clearly in your code. so we opted to error instead.
the fix would be to add an explicit type annotation on the source of the problem.
Having siad that, i think we should reconsider this design decision, and add imports anyways.
@andy-ms you have a valid point but the real power of TS is that it is smart enough to resolve types implicitly based on return type of the function for example. And if you have a large codebase built on top of another one it is pointless to repeat types if they can be resolved implicitly.
I would suggest that it might be a good idea to make a feature like auto re-import in declaration files as an opt-in option in TS config file, something like
"implicitDeclaration": true.In this case default behavior will remain the same unless user knows what he wants and how it might modify his/her declaration files.
@mdekrey an even harder case with this and
noUsusedLocals:This is unfortunately a much larger issue with the new
noUnusedLocalscompiler switch; we can no longer just import the typing from the external module due to causing the new errorXXX is declared but never used. Instead, we have to make sure the imported value is actually used somewhere.@borislemke This error only happens when the type of an export is implicit, so try adding an explicit type declaration, as in
export const WebsitePagesRouter: XXX = express.Router().As a relative newcomer to TypeScript, itās dismaying to see this two-year-old issue still in the discussion phase, especially since it amounts to mixed messaging from the TypeScript compiler, which in turn adds unnecessary confusion and ambiguity.
A slice of my experience: TSLintās
no-unused-variablerule is reliant on the TypeScript compilerāsnoUnusedLocalsoption (example scenario withReact), but enabling said option generates false positives for imports of external type definitions.This feels like a kind of design stalemate, which leaves me without any clear sense of which code quality tool* or configuration settings might allow me to reliably assess unused imports and local variables in my own TypeScript source files while also maintaining comprehensive type definitions.
Going all the way back to @gundās comment and @disintegratorās comment, it seems like there are at least two viable options:
"declaration": trueand"noUnusedLocals": trueprevents false positives for external type definition imports required to name any in-scope types"implicitDeclaration": true) be added to explicitly cover this scenario[Edit] I suppose this is a relatively advanced use / edge case which primarily affects library authors. More than happy to keep things in perspective. All things considered, I would love to see this particular discussion continue ā working with TypeScript has been very good overall, and this is really only my first major āgotchaā. šÆāØ
ā
* At some point I had ESLint + TypeScript working, but Iām not convinced that ESLint + Babel 7 + TypeScript + eslint-typescript-parser is a reliable and/or great developer experience as of this writing (May 2018).
Im new to typescript, but when a compiler complains to me that it cant find an import, because one dependency explicitly import its, but another imports it under an alias, thats just a bug, not ambiguity, or a feature, or being explicit⦠its a bug. Either dont let me do it at anywhere - or it needs to be supported.
Whatās the status of this? I canāt even begin to list the number of times Iāve had to help people with this issue. At least several times a week in our projects. Thereās something urgently wrong here.
We just changed the return type of
graphql-tagfromanytoDocumentNodefrom thegraphqlpackage, which because of this issue is a breaking change and needs to be postponed to the next major https://github.com/apollographql/graphql-tag/issues/150 It would be nice if operations like that were safeAny movement on this now the new emitter has been merged? This would allow us to cleanup so many useless imports/re-exports.
My team at Microsoft is having this issue too, but in our case (a mapping of enum values to functions) itās not reasonable to add explicit types. Hereās a greatly simplified version of our scenario:
tsconfig.json:
Mapping.ts:
FooFunction.ts:
BarFunction.ts:
An manually written interface for the mapping would be incredibly ugly and hard to maintain (the actual mapping has 20+ values):
In our case, I worked around the issue by adding the relevant imports to the mapping file and wrapping them in tslint:disable (we disallow unused variables with a lint rule rather than a compiler flag). But it would be better if that wasnāt necessary.
Donāt wanna bring this issue up again but Iām really struggling with this error. I read through the comments but canāt really understand my problem & solution provided above.
The error
My code:
From what Iāve read in this issue, I just need to import the
RedBNtype to myexample.ts? ButRedBNwas declare locally & have no export then how can I resolve this problemā¦As a reminder that auto re-export or other mechanisms are needed to properly resolve this issue. Adding import only is not sufficient.
https://github.com/Microsoft/TypeScript/issues/5711#issuecomment-231501080
----------- Original comment ----------
This could have deeper consequences.
Consider
moduleA->moduleB->moduleC->moduleD.moduleBis the one that needs to doimport { ABC } from 'moduleA'to get around this issue.When
moduleCusesmoduleBand export its signature, it again fails to compile becausemoduleBneedsABCfrommoduleAbut this timemoduleBdidnāt export it.This means either:
moduleCneeds to have a hard dependency ofmoduleAand importABCmoduleBneeds to not just import but also re-exportABCand thenmoduleCimports it.If
moduleDdoes similar things, then basically you need to know the whole chain of dependencies.~~I wasnāt able to test this to prove that it is the case because Iām using
typingsand there is an issue blocking me so: https://github.com/typings/typings/issues/625~~EDIT: I am able to reproduce it and indeed my
moduleDneeds to referencemoduleAto importABC. In my example:moduleA=>reduxmoduleB=>redux-thunkmoduleC=> custom code on top ofredux-thunkmoduleD=> some libraryABC=>Dispatchinterface inreduxIām happy to import the types from external modules explicitly. I just wish there was a way to have
--noUnusedLocalsunderstand this scenario instead of flagging as error. This issue is quite important to library authors that want to use TypeScript to write library code[1] that depends on third party modules.[1]: meaning code that is distributed with declarations
You mean when a JS client would be using undocumented internals, a TS client would get a fully typed public api for an internal dependency? I can see where someone might want that, but that would be something to solve when you have the ability for TS to know what an internal API even is! For example, if type declaration merging becomes a thing, then it makes sense that the merged file does not include declarations you didnāt ask for. At the moment, without that, and the weird way package.json
typesfield works, I donāt think thereās a way to have an NPM package with external submodules, which is a reasonable pattern - tree-shaking isnāt permitted to remove module-init code, and packages can have different āmodesā of use (react-devtools-extension/logOnlyInProduction,core-js/lib/*,rxjs/operators)So I would ask for the current 1:1
.tsto.d.tsmodel for--declarationsto be ājust make it workā in the absence of future options, given how awkward and arduous it can be to work with the current behavior.Another option that keeps the current behavior without requiring the complexity of declaration merging may be:
--publicFiles, which requires manual annotations only the exports of the listed files? And hopefully editors/doctools respect it and only expose those files (e.g. in path completion).@weswigham do you believe the new declaration emitter will fix this, or should we consider this as a standalone bug?
The workaround for this at the moment seems to be to import the used types. However, unless you use this elsewhere in your code file (and have
--noUnusedLocalsenabled) youāll then be warned that youāre importing something but arenāt using it.Because of these two conflicting issues I have to awkwardly include some reference to the type in my files. For example, all of my styled-components code files that export their components have this abomination somewhere in the file just to keep TypeScript happy:
I donāt know if this is a genuine fix or just masking an underlying issue I donāt understand.
The alternative being to have something like:
Which is even worse.
To every commenting that they have the same issue, please š the top comment. This allows the maintainers to easily see the magnitude of this issue.
I know other Microsoft teams like VS Code use š s to rank features/issues to be implemented/fixed.
+1 for this problem.
I do not think add an explicit type annotation is a good way, since itās hard to maintain.
you do not need an interface, you just need to import the types:
Mapping.ts:
Edit: fixed the sample above, thanks for @vladima for point out.
@weswigham Iām on typescript
v3.3.0-dev.20181129, and it looks like this issue is not completely fixed.The following issue has a sample of what my code looks like along with the problem described here: https://github.com/Microsoft/TypeScript/issues/28754#issuecomment-443820268
Unfortunately I am not able to make a small reproduction, and I canāt share the larger private code where it is happening.
The strange thing is that it only happens in some files, but not all of them.
Since this issue has been closed, hereās some follow-up from my previous comment: https://github.com/Microsoft/TypeScript/issues/9944#issuecomment-385599123
One of my concerns, which led me to this issue, was that TypeScriptās ācannot be namedā error was telling me to import an additional type. When I did that, I got a warning about the imported type not being used, since I have
"noUnusedLocals": trueset in my tsconfig.json.The solution was to explicitly declare my types. In VSCode, this is really easy: you can hover over a symbol, select the text in the tooltip, which shows that symbolās automatically inferred type, and then paste that type declaration into your source file.
Et voilĆ ā at this point, youāve referenced the imported type locally, The now-explicit type can be named by the TypeScript compiler, and the āunused localā warning disappears. š
Still doesnāt work for me: Typescript: 2.9.1-insiders.20180525 / 3.0.0-dev.20180522
Repro: file1.ts
file2.ts
Exported variable 'A' has or is using name 'Color' from external module "/Users/asvetl/work/test/node_modules/@types/color/index" but cannot be named.This is becoming a major annoyance for me at the moment.
Iāve created an internal library for wrapping my functions for various purposes. This is basic example of something similar:
Management.ts
MyColorFunction.ts
Finally at the end I want to keep these functions neatly namespaced inside a kind of āServiceā object:
Usage.ts
And the resulting error:
Now, I would expect Typescript to be able to infer those types because
createFunction<I, O>is clear about what types it is using when exportingmyColorFunctionCreated.It doesnāt even work if I be even more explicit on that export like this:
The only way to mitigate this (and it gets very tedious very quickly - not to mention makes my code very unreadable after a while) is this:
Usage.ts
Or, of course, to just have those imports in the file and not explicitly make use of them. But that causes other issues like others have mentioned (unused imports) and in most IDEs will complain or refactor out automatically because they are not being used.
Basically, we are required to redefine types at the latest stage of usage - even though these types have a very clear pathway to exactly what they are. This is really dirtying up the code base with unnecessary declarations all over the place.
I started looking into this, but Iām afraid that my knowledge of the TypeScript codebase will hinder me from making a PR for this all on my own: itād be my first PR to TypeScript, and this is still flagged as a āSuggestionā by @mhegazy anyway.
Reason for the change:
noUnusedLocalsset to true can result in edge cases that are difficult to solve, especially while keeping the implicit nature of TypeScript clean.My understanding of the proposal:
shouldExportImplicitTypes, should be added tocompilerOptionsto allow developers to opt-in to this case. (I personally would propose that this eventually is made the default for"declaration": true.)Changes that I believe need to happen:
isSymbolAccessiblein checker.ts (approx line 2286 of the linked version) will need to be updated to provide a newSymbolAccessibilityResultresult that specifies the new import statement, possibly usingaliasesToMakeVisible.additionalTypeImportsmap similar tousedTypeDirectiveReferenceswould be added to declarationEmitter.ts to allow injection of imports at the top of the file. Naming collisions would need to be observed and avoided, however these types would not be referenced anywhere outside of this file, since they werenāt imported before and wouldnāt be exported, so the naming could be something clearly auto-generated. Paths to the imported file would need to be relative and follow the module pathing conventions.@andy-ms ahh now I got it. Thanks for the quick reply. Simply adding the type fixed it
Ran into this too. Hereās a repro.
This gets errors in both
b.tsandc.ts.I was able to get around this issue by doing what @mhegazy suggested. After adding an explicit type annotation (my return type was blank and having to get inferred from the parent class) then the errors went away. Worked like a charm. Thanks!
Thanks @weswigham , thatās a good idea. I also found another workaround, using
--stripInternalexperimental flag.This is my attempt to summarize of workarounds:
--stripInternaland add comments to your exports:@pmoleri yes, there is - disable declarations on your main build, then add a second build with
declarationsOnlyset, and only include your entry point file, rather than all of your TS in that build.It would be great if
--noUnusedLocalswould ignore names prefixed with an underscore, just like--noUnusedParameters. Then you could import type-only dependencies like so:(This is currently possible with
tslintās equivalent no-unused-variable rule.)Iām not sure I follow, @unional. The top of the output .d.ts will have the reference to the original export; TypeScript is tracking the location of the symbols by their original path already.
From your original example:
I believe your option 1 is the better solution, as it does not require re-exporting:
Re-exporting changes the contract of the module, including the JS in the case of types that also have emitted JS (such as classes). Adding an explicit dependency where there was previously an implicit dependency is a less breaking change (I could see an argument where itās a non-breaking change, but thatās I believe the proposal should be opt-in), and only affects the typing⦠which is the source of the problem.
This is a particularly painful requirement limitation for lib code, and given the fact that ES2015 modules are statically defined, itās sad to see that a game plan (at least) for ameliorating this issue has yet to be defined.