I have a "parent" app which is a base library that we use in other apps. We recently moved all the dependancies into the parent package.json, and removed them all from the children apps keeping only the parent. Making sure we had the right versions was cumbersome, and NPM would install all the dependancies of the parent app anyway so things work.
The problem we noticed is that we can only auto import from the parent (which is in the child app's package.json), and not things like Angular or RxJS.
TypeScript Version: 3.9.7 (also 3.8.3, and 4.0.0-dev.20200803 with a VS Code plugin)
Search Terms: auto import package.json dependancies types
Code
I have created an example repo here: https://github.com/cjdreiss/ts-import-error
It contains the "parent" app, and a "child" app with instructions in the readme.
Parent package.json
"dependencies": {
"@angular/animations": "~10.0.6",
"@angular/common": "~10.0.6",
"@angular/compiler": "~10.0.6",
"@angular/core": "~10.0.6",
"@angular/forms": "~10.0.6",
"@angular/platform-browser": "~10.0.6",
"@angular/platform-browser-dynamic": "~10.0.6",
"@angular/router": "~10.0.6",
"rxjs": "~6.5.5"
}
Child package.json
"dependencies": {
"@cjdreiss/ts-import-error-parent" : ">0.0.0"
}
Component trying to import things from rxjs
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { ExampleComponent } from '@cjdreiss/ts-import-error-parent';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'child';
test: Observable<any>;
// test2: BehaviorSubject<any>; // won't auto import even though there is an rxjs import already...
parent: ExampleComponent; // auto imports because @cjdreiss/ts-import-error-parent is in package.json
}
Expected behavior:
Auto imports from things like rxjs and @angular/xxx should work
Actual behavior:
Only auto imports from dependancies listed in package.json work (my library as an example). If we change the TypeScript version VS Code is using to 3.6.3 it can import it.
Non working import in 3.9.7

Working import after switching the TS version to 3.6.3

Related Issues: I believe this issue might be related (although it says its in Milestone 4.0.0), and there are other related issues in that https://github.com/microsoft/TypeScript/issues/37812
This seems to demonstrate the same issue: https://github.com/microsoft/TypeScript/issues/37187 which was closed as a duplicate of https://github.com/microsoft/TypeScript/issues/36042
Can you try out a nightly release of TypeScript to see whether the problem is fixed?
https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-next
@DanielRosenwasser I've added that plugin to VS Code, selected the latest (4.0.0-dev.20200803), restarted VS code, and still having the same issue.
Pretty sure this is intentional - we scoped autoimports to only the contents of the package.json we found and the current projects existing imports, iirc.
@weswigham is there a config option we can use? I was trying to add things like "node_modules/@angular" to typeRoots but that didn't seem to help (or maybe I just put it in the wrong place?).
It works in an older version of typescript though, my work machine still can switch to 3.6.3 and it works then (but has other issues because we use newer TS features)
Sorry, that's correct, I misread.
The behavior is intentional. I'm not sure if @andrewbranch had any other workarounds, but if you do intend to auto-import from this package, the recommended workflow is to add it as a dependency of some sort. A big reason why we did this was that this sort of import won't even work with pnpm or certain versions of npm and yarn. You can also re-export declarations from those packages, but we don't necessarily recommend that.
Were you just trying to avoid duplication with your dependencies?
I believe this is an exact duplicate of https://github.com/microsoft/TypeScript/issues/38768 and I explained the rationale there, although Daniel pretty much covered it. As far as workarounds go, I think you could put a dummy file with triple slash references (/// <reference types="@angular/core" />) to everything you want to show up that isn’t. That seems of limited use to me though, since they’ll show up after you import from them once.
Yes, we want to avoid duplicates, and sometimes other versions of our apps would also become libraries and if they had miss matched versions, multiple get installed which could cause issue. Also it was a pain to keep all the apps in sync as well.
I see that issue now, "transient" was the word I was looking for in terms of the dependancies.
We only upgrade our TS versions when Angular does (and not right away either) which is why "filter 3" took a while to hit for us.
(3)> Files that are either not in node_modules or part of packages listed in your package.json deps
Am I misunderstanding what typeRoots is for? It sounds like it might help us.
I'll try the triple slash method as well, but the issue is even in the same file it does not auto import even after we have other imports already.
Am I misunderstanding what
typeRootsis for? It sounds like it might help us.
Yes, more or less. typeRoots is mostly to accommodate systems that predate @types on npm, which worked similarly but were often downloaded to a folder called typings instead of going inside node_modules. typeRoots lets people continue using that, potentially in combination with node_modules/@types. If I recall correctly, adding node_modules/@angular to typeRoots works partially somewhat by coincidence, but will give you errors if you have @angular/cli installed, for example, because that package doesn’t contain type definitions, and the assumption is that typeRoots exclusively contains folders that contain type definitions.
the issue is even in the same file it does not auto import even after we have other imports already
Ah yeah, I forgot about this, even though I mentioned it in #38768:
It does seem reasonable to stop filtering them out within the same file, although I’m not sure how big of a performance penalty that will incur (but it _will_ incur one).
I still believe the pattern you’re using is one that should strictly be avoided (although I, along with every JS developer, can sympathize with the difficulties of package version management). I think I’ll look into bypassing the filter for modules that have already been imported from in the same file, but your experience will still be sub-par since normally this would work cross-file. I would strongly recommend solving your version syncing/deduplication issues another way, maybe by using a looser version range in the “parent” package, and/or clever use of peerDependencies somewhere.
The pattern we're using seemed a bit out of the norm, we had been working with different peerDependencies to get something that worked, and we figured let's try this. And it was great because it worked! Till we upgraded Angular, which brought a new version of TypeScript along which broke the functionality.
I've tried the triple slash imports but either I'm doing them wrong, or its still getting filtered out.
I've tried adding them in the parent library, in both the public_api.ts file, one of the exported module.ts files, and even including them directly in a file inside the child app. My build is not removing them, the final JS for my parent library has those triple slash comments in them still.
It still doesn't want to ever auto import, even if there is an import in the file already. Is this expected?
It's just frustrating that it worked in one version, and then was disabled in a newer minor version with out a way to opt out (and the seemingly other ways to do it don't appear to work either).
Commit adding the triple slash to public_api.ts
https://github.com/cjdreiss/ts-import-error/commit/fbbd5118d85a3e708d947c2383b01d56747dad6f#diff-64cc85193ba4ef4f8c02f0187c48e3ab
Commit trying the triple slash in a shared module file from the parent
https://github.com/cjdreiss/ts-import-error/commit/88596f434be1914f9c9252e4b42fc8f165c9bc15#diff-ebe96b65194c05f616e8b988d70cf718
Commit adding the triple slashes directly in the app.component.ts in the child app
https://github.com/cjdreiss/ts-import-error/commit/ac4a20ad8b3790e1f467099a2a0814302ee70b32#diff-aa6dfe7d2762a02702f781c7cd35f38a
Is it possible for the TS team to add some option to specify which dependencies it should use to resolve auto-imports for? That way you could opt in to the old behavior for a specific dependency.
Anyone who builds a "base class library" type situation used to have this scenario work and it's now broken. That seems like a major regression to me...
We are having similar issues. We have 20+ apps utilizing the same framework, which acts as a central place for common dependencies.
An opt out of some sort would really be helpful.
This is very much the intentional behavior; dependencies of your dependencies are not part of the dependency contract and it's fundamentally incorrect for us to encourage violating that assumption. You are always free to write the imports manually.
@RyanCavanaugh
TypeScript used to work with this use-case (having a shared framework). It no longer does. You guys inadvertently broke an important use case we and others were using in production. A use case that is important for enabling enterprise-level web development (which was one of the original goals of TypeScript...). Just because you philosophically disagree with it doesn't change any of those facts.
Couldn't the TypeScript compiler at least provide a compiler flag to opt-in to the old behavior?
"Writing imports manually" isn't a solution when you have dozens of developers with varying degrees of expertise all utilizing the same common framework.
This is very much the intentional behavior; dependencies of your dependencies are not part of the dependency contract and it's fundamentally incorrect for us to encourage violating that assumption. You are always free to write the imports manually.
Looks like TS team should talk with other well-known teams, like framework devs to find out a way, that will still provide import suggestions (at least for frameworks classes and objects). Like an option or separate feature.
Just disabling such feature, is not a correct way. Huge step back.
why can't we provide option to atleast allow some indirect dependant modules via some config...seems legit behavior to expect auto imports from indirect dependencies...
Most helpful comment
@RyanCavanaugh
TypeScript used to work with this use-case (having a shared framework). It no longer does. You guys inadvertently broke an important use case we and others were using in production. A use case that is important for enabling enterprise-level web development (which was one of the original goals of TypeScript...). Just because you philosophically disagree with it doesn't change any of those facts.
Couldn't the TypeScript compiler at least provide a compiler flag to opt-in to the old behavior?
"Writing imports manually" isn't a solution when you have dozens of developers with varying degrees of expertise all utilizing the same common framework.