@types/xxxx package and had problems.Definitions by: in index.d.ts) so they can respond.Hey there! I'm combining Node, React, React DOM and React Native code in the same codebase (So that I can generate simultaneously iOS, Android and Web apps with Server-side rendering support), and I'm hitting the following errors in the type definitions for React native:
ERROR in [at-loader] ./node_modules/@types/node/index.d.ts:60:13
TS2451: Cannot redeclare block-scoped variable 'global'.
ERROR in [at-loader] ./node_modules/@types/node/index.d.ts:84:13
TS2300: Duplicate identifier 'require'.
ERROR in [at-loader] ./node_modules/@types/react-native/index.d.ts:8872:11
TS2451: Cannot redeclare block-scoped variable 'global'.
ERROR in [at-loader] ./node_modules/@types/react-native/index.d.ts:8873:14
TS2300: Duplicate identifier 'require'.
ERROR in [at-loader] ./node_modules/@types/webpack-env/index.d.ts:186:13
TS2300: Duplicate identifier 'require'.
It looks like React Native redefines global and require:
declare global {
const global: GlobalStatic;
function require(name: string): any;
/**
* This variable is set to true when react-native is running in Dev mode
* Typical usage:
* <code> if (__DEV__) console.log('Running in dev mode')</code>
*/
var __DEV__: boolean
}
Since these are already defined by @types/node, the compiler complains. I was able to work around the issue by adding the following option to my tsconfig.json file, however I'd like to avoid doing that if possible:
{
"skipLibCheck": true
}
Thanks in advance
This is a good question, alas I don't know the right answer. I have not had to deal with it, other than us running our RN tests within node, but there I opted to just get rid of the few places where the node typings were needed.
I do wonder, wouldn't it be more correct to have a tsconfig.json file per env, rather than treating all of it as a single combined env?
skipLibCheck worked.
However it seems much more logical to skip lib checks in node_modules by default (since we don't control them) but not in our source directories (since we can take action on the errors). I don't see why anyone would want to download npm packages and immediately have build break because of lib checking.
Are there any issues open to this regard? I certainly imagine many people are running into this issue (anyone using both react-native and TS).
I'm in the same boat with OP. any chance this can get cleaned up?
I don't see why anyone would want to download npm packages and immediately have build break because of lib checking.
On the other hand, you also don't want to have your code start giving bizarre errors because of a suppressed error in libs, which I have run into.
Seems it's now just the require() function with [email protected] and [email protected]:
// node/index.d.ts
interface NodeRequireFunction { (id: string): any; }
interface NodeRequire extends NodeRequireFunction {
resolve(id: string): string;
cache: any;
extensions: NodeExtensions;
main: NodeModule | undefined;
}
declare var require: NodeRequire;
// react-native/index.d.ts
declare function require(name: string): any;
Not sure how this ideally would be fixed, maybe something like:
// node/index.d.ts
declare function require(name: string): any;
declare namespace require {
export function resolve(id: string): string;
export var cache: any; // shouldn't this be Record<string, NodeModule>?
export var extensions: NodeExtensions;
export var main: NodeModule | undefined;
}
but I'm not sure if that's compatible with all existing @types/node using code? In particular, with other @types/* code that has declared require to be compatible with @types/node's existing require will probably be broken by this. I'm not sure what the reverse, declaring react-native's require to be compatible with nodes, without also adding the require.* definitions.
I do wonder, wouldn't it be more correct to have a tsconfig.json file per env, rather than treating all of it as a single combined env?
This is more correct, and should be what you do so you get correct build errors, but IDE's won't understand it, so you need a base "union" config that at least accepts everything. Not ideal :(.
I'm also running in to this issue with @types/react-native and @types/node because jest has a dependency that needs @types/node even if I don't have it in my package.json.
Any other workarounds than using skipLibCheck would be appreciated. Would it make any sense for @types/react-native to just require the use of @types/node instead of adding their own type for require?
Would it make any sense for @types/react-native to just require the use of @types/node instead of adding their own type for require?
Even if the react-native declarations could pull the node declaration of react out, it would not quite be right anyway, as node also supports things like require.resolve(foo), require.cache, etc, which (AFAIK) react-native's environment does not. Worse, I'm not sure that that's possible, so you more likely would end up with all the nodeisms, like process, etc...
Thanks for the explanation @simonbuchan. So using @types/node is not going to work.
Looking at this linked issue https://github.com/tkrotoff/react-form-with-constraints/issues/12, maybe the solution is to have a separate package where we would move these polyfills out of the RN package. Then when people have overlapping definitions, they can choose to not use the polyfill package by explicitly specifying the types to use?
I鈥檓 still on the fence about this, it would definitely be nicer to have a solution that would not require us to split packages.
As I mention above, node's require could be updated to be compatible with react-native's definition, but for all I know that could break other people who've made their defs compatible with node's?
I guess it's reasonable to make a PR, at least, I'll look into it later (I'll have to figure out how tests, etc. works for DT).
I think @types/node is the definitive declaration. require() should be removed from @types/react-native and it should just depend on @types/node instead. If an indirect dependency brings in @types/node, I can鈥檛 avoid this error otherwise. Also, a single project may target both react-native and node by having different scripts used for build/test time (node) and also runtime (react-native).
Discussed, and not a great solution, see my previous comments.
Now Jetbrains IDEs support multiple tsconfigs, so if other editors are handling it, this might not need to change?
@simonbuchan How does using multiple tsconfigs help with this issue? And how do I get react-native to run targeting node in a test environment if its typings prevent me from using node鈥檚 typings at the same time? That case requires the typings to be made compatible, does it not鈥攑erhaps by making the require definition conditional so that it is skipped when targeting node?
One config has types: node and exclude: <source files>, the other has has types: react-native and include: <source files>.
The tests are a more interesting problem, I normally simply don't unit test platform-specific code, using integration tests instead (for example, detox), but that won't work for everyone.
Try only jest (eg) and react-native in test files, and only node in mock files?
@binki @simonbuchan I managed to solve the issue with a workaround, a postinstall script from here: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/15960#issuecomment-373922019
That script just goes and removes the require definition from node_modules/@types/node/index.d.ts, which is ok in my case as I don't directly depend on @types/node.
So that means that the workaround is only useful if your react-native project does not directly depend on @types/node in your package.json.
Here's the script that I'm using (includes also a fixed sed command):
postinstall.sh
#!/bin/sh
# postinstall.sh
# TL;DR node require() and react-native require() types conflict, so I'm
# commenting out the node type definition since we're in a RN env.
# https://github.com/DefinitelyTyped/DefinitelyTyped/issues/15960
# https://github.com/aws/aws-amplify/issues/281
# https://github.com/aws/aws-sdk-js/issues/1926
# Make sed behave on all platforms.
# https://stackoverflow.com/a/38595160s
cross_platform_sed () {
sed --version >/dev/null 2>&1 && sed -i -- "$@" || sed -i "" "$@"
}
cross_platform_sed "s/\(^declare var require: NodeRequire;\)/\/\/\1/g" node_modules/\@types/node/index.d.ts
Doing a little bit of digging, what exactly is require in React Native? It seems like at some point they switched to use ES6 syntax so they support import rather than require out-of-the-box. I'm not 100% sure as someone with proper RN source code experience would know better, but it seems that the require declaration in RN is deprecated in favour of import at this point.
Both are supported and used. In particular, conditional or delayed require is legal, and would bundle but not immediately execute, so there's quite likely to be users of it. The import expression is what's recommended now, but it brings in promises, meaning you need to churn to convert to it.
FYI for people that run into this situation because one of their runtime dependencies (implicitly) depends on @types/node; the best solution imo is to send a PR upstream to that package to remove the @types/* packages from the runtime dependencies, because these are dev only and should be left up to you as dev to decide how to pull in.
Eh. If you ship types bundled with your library such that your typescript users can't build without it, I can see a good argument for having a "production" dependency on a types package. I'm not sure if there's specific guidance here though.
You normally can work around it easily by specifying "types": [] in your tsconfig, but it's possible this library you're importing has a /// <reference types="node" /> comment that pulls it in anyway, and it will likely be referencing node types and will need some work to get it typing.
The "skipLibCheck": true worked for me!
The
"skipLibCheck": trueworked for me!
I works, but I would not recommend doing it. The description says "Skip type checking of all declaration files (*.d.ts).", which basically means that most libraries (that have type definitions in separate files) will not have any type checking in your project.
@kristerkari That's not what it means. It means that it won't do type checking for the index.d.ts in those libraries. You still get the typechecking when you use it in your project.
Why would you need to type check code already in a package's codebase? That's like running eslint on your code as well as every npm package you install to check if their code has errors.
That's not what it means. It means that it won't do type checking for the index.d.ts in those libraries. You still get the typechecking when you use it in your project.
The option skips *.d.ts files, so if I import some types from another project or use .d.ts files in my project, those files will be skipped. So it depends on how you use types in your project.
Why would you need to type check code already in a package's codebase? That's like running eslint on your code as well as every npm package you install to check if their code has errors.
At least I am interested in knowing that the type definitions of the node modules that I am using in my project are compatible with the Typescript version that I am using. If I set "skipLibCheck": true, then the Typescript compiler won't show me any errors of mismatching library typings.
I am running into the same issue. I agree that by setting "skipLibCheck": true it sounds more like a work-around the problem rather than actually fixing the issue.
Has anyone else found a proper fix for this? Thanks.
Has anyone else found a proper fix for this? Thanks.
At least I'm not aware of a proper fix.
If you look at my previous messages, I have posted a workaround script that can be used if your React Native project does not directly depend on @types/node. Yes it's a hack, but it solved the issue for me while waiting for a proper solution.
OP theoretically fixed by https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33302
@alloy This should be reopened as its not fixed. Now errors out with:
node_modules/@types/react-native/index.d.ts:9302:9 - error TS2403: Subsequent variable declarations must have the same type. Variable 'require' must be of type 'NodeRequire', but here has type 'ReactNativeRequireFunction'.
Thanks for the update!
Should now be fixed by https://github.com/DefinitelyTyped/DefinitelyTyped/pull/33800
Most helpful comment
skipLibCheck worked.
However it seems much more logical to skip lib checks in node_modules by default (since we don't control them) but not in our source directories (since we can take action on the errors). I don't see why anyone would want to download npm packages and immediately have build break because of lib checking.
Are there any issues open to this regard? I certainly imagine many people are running into this issue (anyone using both react-native and TS).