Definitelytyped: Unable to use the newest @types/angular with @types/angular-mocks and others

Created on 13 Aug 2017  路  14Comments  路  Source: DefinitelyTyped/DefinitelyTyped

| Package | Version |
| --- | --- |
| typescript | 2.4.2 |
| @types/angular | 1.6.28 |
| @types/angular-mocks | 1.5.10 |

Hello,

Since I upgraded @types/angular package I have a problem with compilation. I'm getting following error when I try to run the test:

error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.

The problem exists not only with @types/angular-mock but also angular-bootstrap, angular-growl-v2, etc. In short, everything that has an angular. prefix in definition files.

I've found similar issues within this repo's page but none of the solutions or workarounds works.

All 14 comments

https://github.com/leonard-thieu/test_angular-angular-mocks

I can't seem to reproduce this issue. Could you supply a minimal repro?

@diegovilar @thorn0 @calebstdenis

Yes, please provide a minimum reproduce.

@leonard-thieu @thorn0 Sure, I'll provide something soon. The problems occurred when I was migrating to webpack with ts-loader, I'm not sure if it's related.

@eps90 Could you provide some more info?
Im also having this issue, but only on jenkins (locally it works)

  • awesome-typescript-loader
  • ts version - 2.5.3
  • @types/angular - 1.6.32
  • @types/angular-mocks - 1.5.11

when I run the tests locally in intellij, it seems fine. However it fails on jenkins with messages:
Property 'mock' does not exist on type 'IAngularStatic'

I have the same problem. I use types/[email protected] and types/[email protected] alongside types/[email protected]. My Typescript version is 2.6.1.

It seems to be related to the dependency angular-mocks and angular-ui-router have to types/angular.

The dependency for both is specified as:

"dependencies": {
    "@types/angular": "*"
}

Which for some reason resolves to version 1.6.2 and not the latest 1.6.39. In my case I get one types/[email protected] and two types/[email protected] which seems to confuse Typescript. Manually removing the 1.6.2 version resolves all issues.

I use [email protected] to install these dependencies. Yarn specifies the * syntax as 'any version' (https://yarnpkg.com/lang/en/docs/dependency-versions/#toc-x-ranges) which apparently does not mean 'latest version'.

Would changing the * to 1.6.39 solve the problem?

I managed to fix it in my specific example by removing my yarn.lock and my node_modules folder. Next I reinstalled with yarn. I also cleared my yarn cache in between but I am not sure if this helped. It is possible my yarn.lock file still contained a reference to the older types/@angular version causing it to use this one for some dependencies.

Was also running into this issue, and '*' was resolved to a different version in my yarn.lock. Deleting the yarn.lock and regenerating it converged the references to the same version, i.e.:

"@types/angular@*", "@types/angular@^1.6.29":
  version "1.6.40"
  resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.6.40.tgz#f4e5a77573068c07ccab320e63e1616e1f097fc9"

This fixed the issue for me.

I was having a related problem with my own (privately published) typedef packages, which also depend on @types/angular. The fix turned out to be replacing the direct dependency with a peerDependency (for consumers of my typedefs) and a devDependency (to prevent IDE errors when developing the typedefs).

The issue is that when the versions don't exactly match (thanks, yarn.lock...) we end up with two (or more) copies of the same ambient declarations. In the case of IAngularStatic, it's the one from node_modules/@types/angular-mocks/node_modules/@types/angular that's augmented, which is why the one at node_modules/@types/angular (imported with import * as angular from 'angular';) doesn't have mock. You can even see this by changing that import to import * as angular from 'angular-mocks/node_modules/@types/angular';

The related issue that I came across (which I think you should also be seeing) comes from @types/angular/jqlite.d.ts. TypeScript tries to merge the declarations in the various versions of that file only to discover that they're creating duplicate references:

node_modules/@types/angular-mocks/node_modules/@types/angular/jqlite.d.ts(29,5): error TS2375: Duplicate number index signature.
node_modules/@types/angular-mocks/node_modules/@types/angular/jqlite.d.ts(824,5): error TS2374: Duplicate string index signature.

The fix I mentioned in the first paragraph works if I do it manually to my downloaded node_modules/@types/angular-mocks package. Just open node_modules/@types/angular-mocks/package.json and change "dependencies" to "peerDependencies", and then delete node_modules/@types/angular-mocks/node_modules. And this fixes both the above issues, with the IAngularStatic and with jqlite.d.ts.

I could easily run through all the angular-related typedefs and do this fix myself, but I've never contributed to DefinitelyTyped before. Don't know the rules. I can look into it though, if the regular contributors don't jump on it.

I'm not sure if there's a mechanism to set peerDependencies on @types packages. @andy-ms ?

Also, isn't regenerating yarn.lock the more appropriate fix here?

There isn't such a mechanism -- I don't see why that's the fix in this case though?

@leonard-thieu Oh, right. I just had a look in angular-mocks after I read your comment, and no package.json. So I guess it's generated. Interesting.

I'd have to disagree with the second point, though. Hoping that users who face this issue eventually find this conversation and find out what to do to repair their broken dependency tree isn't a fix, it's an __obscurely documented workaround.__

You're also asking them to break the rules of yarn by wiping their lockfile, which would have the effect of upgrading all dependencies at once (since the package.json has a caret on each version number by default). Which would also pollute what should be an atomic commit, combining "Set up mocks" with "Upgrade dependencies" - you don't want to make Linus cry, do you?

Yes, these are minor gripes, but my point is that the bug is not in yarn or the lockfile it generates. And the bigger problem is that people just won't know to do it. The tsc errors we get do not point in the right direction at all. It literally took me two hours of my employer's time to find this thread, manually edit my lockfile (also against the rules, technically), and then use this new information to figure out what was really going on and fix my private typedefs for good. If a package augments a declaration in another package, it must refer to the same declaration as the one that will be imported in the consuming project, otherwise it's worthless. Likewise in the very particular case that it depends on a package with an ambient declaration of the form { [key: string]: any }, it must not bring in a second copy of that declaration. I'm sorry if there's not a mechanism for it already, but these really should be peerDependencies.

Either that, or make it very clear to anyone using them that they should always set the version range to "*" for all @types packages they depend on in their projects, to avoid these conflicts. At least when using yarn. And probably npm shrinkwrap.

@andy-ms Because that's the very definition of what a peerDependency is for. If it's just a normal dependency, then there will be situations where the consumer ends up with two copies of the dependency (in this case @types/angular, but I'm sure there are others), which then causes the above-mentioned issues. This is the reason peerDependencies were invented, for plugins to other packages. I think a definitions package that augments the definitions in another definitions package qualifies as a plugin!

But since it seems it's not possible, I guess I'm not achieving anything here. If it's at all feasible to create that mechanism, I'd urge you to consider it. Yarn is a pretty popular alternative to npm, and growing in popularity all the time. And it does the equivalent of npm shrinkwrap by default, fixing version numbers with the lockfile until you choose to upgrade your dependencies manually, in order to achieve deterministic builds across multiple systems. I don't think asking us to deliberately undermine that feature of our package manager in order to use your packages successfully (by deleting and re-generating the lockfile every time we add one of them) is the best way to go about things.

For more information on proper use of peerDependencies and why they're necessary, the Yarn team have recently published a relevant blog post.

Of particular relevance is the section on what each type of dependency can guarantee to you as a library (or typedef package!) author.

Note that this is not new information. Peer deps were first introduced to node and npm in 2013, and for the same reasons I've already outlined in earlier comments.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

csharpner picture csharpner  路  3Comments

victor-guoyu picture victor-guoyu  路  3Comments

jgoz picture jgoz  路  3Comments

JudeAlquiza picture JudeAlquiza  路  3Comments

JWT
svipas picture svipas  路  3Comments