(TypeScript 2.0.0 beta)
Developer dependencies imported using the npm @types namespace interfere with my project specific types.
In my case, I have a web project that should use TypeScript’s default type definitions. My developer dependencies however include something that requires beautylog which itself depends on the package typings-global that has a dependency on @types/node.
This causes some standard definitions to be overwritten with Node-specific definitions. For example, setTimeout() will return a NodeJS.Timer object (instead of a number).
So when using setTimeout() in my web application and attempt to save the return value into a number variable, I get an error since I cannot assign a NodeJS.Timer to that type. But using that NodeJS.Timer type would be wrong since that’s not what happens in the browser.
So a dependency of a dependency of a dependency … has some type definitions which is added into node_modules/@types/ which then causes my project to also load those although they are not relevant (and actually conflicting) to my project.
Is there any solution to this? npm 3’s “let’s try to put everything flat into node_modules” essentially creates a whole new scoping problem with TypeScript 2’s type definition resolution.
(I’ve also created an issue about this on beautylog’s repository.)
In your tsconfig.json, add this (at the same level as "compilerOptions" or "files"):
"types": [],
This will effectively disable the automatic enumeration of node_modules/@types. If there are types you do want to use from there, you can add the to the array (e.g. ["moment", "express"])
/cc @DanielRosenwasser -- this is a concrete reason to encourage package authors to not put @types entries in their dependencies list
There needs to be a mechanism though for expressing "I am also going to need this other API". npm handles this through peerDependencies and of npm@3 those will not get installed automatically but simply warn that they need to be present. It seems logical that peerDependencies should be used to express those and with npm@3 the worst is that you get an annoying error message saying you have an unmet dependency, but it does not halt things like CI.
FWIW someone on our team was talking to the NPM people and it sounds like they may be open to some new form of dependency (if we implement it for them, presumably :wink:). I feel like a recursive-walking dev-dependency is what we want, but we need to figure out what the scenarios are and spec it all out before going down that road.
FWIW someone on our team was talking to the NPM people and it sounds like they may be open to some new form of dependency (if we implement it for them, presumably 😉).
Awesome. These sort of ambient dependencies, where there can be two levels of "versioning" (the version the ambient definition is describing and the version of the ambient definition). It would also be nice to potentially resolve the ambient dependency automagically based on the run-time dependency. Would be glad to add to the conversation if it gets serious with npm.
In your tsconfig.json, add this […]
Thanks for the suggestion but for some reason this is not working properly for me. If I just run tsc (without arguments), then the types declaration in the tsconfig.json seems to be ignored. I still get the same errors from type definitions that I do not want to be included. If I run tsc -p . to specify the path to the tsconfig.json explicitly, then the @types definitions are not automatically included (regardless of whether I specify types in the tsconfig) but it also does not recognize types I specified in the tsconfig.
So what is the best approach right now to handle @types/ scope dependencies when I want to avoid installing all @types/ manually? My idea would be to define them as peer dependencies and build a separate tool that
That side effect with tsc vs tsc -p was fixed in #9785. What remains is that using "types": [] in the tsconfig.json does not do anything.
I’ve created a test repository for this here.
@poke your tsconfig.json should be:
{
"compilerOptions": {
"types" : []
}
}
@mhegazy Oh, so types is now part of compilerOptions? When was that changed? It works that way btw. so thanks a lot!
i do not think it has ever been other than that. only include, exclude, files are siblings to compilerOptions.
@RyanCavanaugh - The guidance given here to fix the conflicting types in @types by setting types: [] does not seem consistent with what's in the docs or my own experience:
Specify "types": [] to disable automatic inclusion of @types packages.
Keep in mind that automatic inclusion is only important if you’re using files with global declarations (as opposed to files declared as modules). If you use an import "foo" statement, for instance, TypeScript may still look through node_modules & node_modules/@types folders to find the foo package.
This means that even if the declaration is not being included automatically as an ambient declaration, another dependency can explicitly import that dependency and you can still end up with conflicting global declarations.
Am currently experiencing this with a project that is including (and importing) @types/react even though react is specifically not included in my types array in tsconfig.json. (Not only that, node_modules/@types is not even in my typeRoots in tsconfig.json)
i.e:
.../node_modules/@types/storybook__react/node_modules/@types/react/index.d.ts
(3544,13): error TS2403: Subsequent variable declarations must have the same type.
Variable 'a' must be of type 'DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>',
but here has type 'DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>'.
In case it helps anyone else, I managed to fix my issue of clashing @types dependencies by using the types: [] solution offered here AND also setting resolutions in my package.json. The latter was to specify a specific version of the @types package for yarn to install instead of multiple conflicting versions. It's possible that w/ the npm CLI this part of the solution wouldn't have been necessary, but we're using yarn workspaces so for us it was.
Most helpful comment
In your tsconfig.json, add this (at the same level as "compilerOptions" or "files"):
This will effectively disable the automatic enumeration of
node_modules/@types. If there are types you do want to use from there, you can add the to the array (e.g.["moment", "express"])