Hi, I’m using react4xp and I’m getting the typescript warn when using the “app” global variable “Cannot find name ‘app’.ts(2304)”.
How can I prevent that warning since the global variable exists and the code works properly?
Thank you
Hi Reinaldo,
As usual the answer is “it depends”.
The easy answer
You can install "@enonic-types/global"
from npm, and add it to types
in tsconfig.json to get these global types.
My preferred approach…
I will usually create a types.ts file in each of my projects where I declare these types.
The reason I want to declare app
myself, is that I want app.name
to be a string literal (and not a string
). That way I can use the string literal to build template strings.
E.g.
// types.ts
declare const app: {
name: "com.myproject";
version: string;
config: { [key: string]: string };
};
// otherfile.ts
import type { Article } from "/site/content-types";
type ContentArticle = Content<Article, `${typeof app.name}:article`>;
// ----------------------
declare const content: ContentArticle;
// content.type = "com.myproject:article"
Happy coding!
– Tom Arild
Thank you for your response. But I already have @enonic-types/global installed and added to tsconfig.json and yet it’s not working.
Not only that happens for the “app” variable as I said, but also for the “log” variable, another global variable.
@reinaldoams Can you share your tsconfig.json?
Sure! Here it is:
// This file is used by your code editor so it must be permissive to support
// * Enonic XP serverside files running on Nashorn
// * React4xp files running both on Graal-JS and in the browser
// * Potential assets running in the browser only
{ // https://www.typescriptlang.org/tsconfig
"compilerOptions": {
//──────────────────────────────────────────────────────────────────────
// Modules
//──────────────────────────────────────────────────────────────────────
"allowUmdGlobalAccess": true,
"baseUrl": ".",
"paths": {
"/lib/enonic/react4xp": ["node_modules/@enonic-types/lib-react4xp"],
"/lib/xp/*": ["node_modules/@enonic-types/lib-*"],
// So one can import local files using absolute path same as
// * react4xp resolves during build time
// * and Enonic XP resolves during runtime
"/*": ["src/main/resources/*"], // For some reason this doesn't work in Visual Studio Code :(
},
// By default all visible ”@types” packages are included in your compilation.
// Packages in node_modules/@types of any enclosing folder are considered visible.
// For example, that means packages within ./node_modules/@types/,
// ../node_modules/@types/, ../../node_modules/@types/, and so on.
// If typeRoots is specified, only packages under typeRoots will be included.
"typeRoots": [
"node_modules/@types",
"node_modules/@enonic-types"
],
// By default all visible ”@types” packages are included in your compilation.
// Packages in node_modules/@types of any enclosing folder are considered visible.
// For example, that means packages within ./node_modules/@types/,
// ../node_modules/@types/, ../../node_modules/@types/, and so on.
// If types is specified, only packages listed will be included in the global scope.
// This feature differs from typeRoots in that it is about specifying only the exact
// types you want included, whereas typeRoots supports saying you want particular folders.
"types": [
"@enonic-types/global", // No point, already added via typeRoots
// "@enonic-types/lib-event" // No point, since it doesn't affect global scope
// "@enonic-types/lib-react4xp"
],
//──────────────────────────────────────────────────────────────────────
// Interop Constraints
//──────────────────────────────────────────────────────────────────────
"esModuleInterop": true, // Allow import React from 'react';
//──────────────────────────────────────────────────────────────────────
// Language and Environment
//──────────────────────────────────────────────────────────────────────
"jsx": "react", // Support jsx and tsx
"lib": [
// Keep in mind that DOM doesn't exist serverside, so only use it
// in clientSide assets or pure clientSide React4xp components.
"DOM",
"ES2015"
],
//──────────────────────────────────────────────────────────────────────
// Completeness
//──────────────────────────────────────────────────────────────────────
// Even though the setting disables type checking for d.ts files,
// TypeScript still type checks the code you specifically
// refer to in your application's source code.
"skipLibCheck": true, // Disable type checking for node_modules
},
"include": [
"src/main/resources/**/*.ts",
"src/main/resources/**/*.tsx"
]
}
I can’t see anything wrong with your tsconfig-file. Sorry
But I think you probably don’t need "typeRoots"
, since libraries are associated with the correct types in "paths"
, and you add the global in "types"
.
– Tom Arild
Hi, I’m using react4xp and I’m getting the typescript warn when using the “app” global variable “Cannot find name ‘app’.ts(2304)”.
Can you post an example of your code which triggers the build warning?
It’s not a build warning. It’s a warning in the vs code editor.
I’m trying to access app in the .ts controller of parts, pages or in .ts files in the lib folder. Should be global and without any warning since the .tsconfig is configured for that.
Here is an example in a part controller:
const query = `type = "${app.name}:event"`,
In the app variable, I get
Cannot find name 'app'.ts(2304)
What if you simply add an import of app
and log
like this:
import {app, log} from '@enonic-types/global';
I’ve tried it now and resolution of both variables worked fine for me, but I’m using IntelliJ.
If I try to do that, I get
File '(...)/xp/node_modules/@enonic-types/global/global.d.ts' is not a module.ts(2306)
VSCode is complaining that @enonic-types/global/global.d.ts' is not a module
because the things you are trying to import are not exported.
If I add the export
keyword to the declare const app
statement in this file, the error message and red squiggly line go away.
I have no idea why IntelliJ is not complaining over this issue.
Edit: Managed to get VSCode to work properly without changing global.d.ts
to a module. Steps:
enonic project create
and choose the typescript starter.- Create a controller with a .ts-file referencing the global objects
app
andlog
. - Observe that VSCode reports the error (Cannot find name ‘app’):
- Run
npm install
in the project root directory. - Observe that the error is gone:
Similarly, for React4XP:
enonic project create
and choose the React4XP starter.- Edit the example controller at
src/main/resources/site/parts/example/example.ts
. - Observe that VSCode reports the error (Cannot find name ‘app’):
- Run
npm install
in the project root directory. - Remove lines 27-30 in
tsconfig.json
- the ones about typeRoot. - Observe that the error is gone:
Yup, the import suggestion won’t work as the error message says, it’s not a module, it doesn’t export anything… It just modifies global scope.
Already been looking into that before the summer
There is a workaround by using triple slash import
With regards to the tsconfig.json file.
If one reads these two sections of the documentation:
It’s not entirely clear what happens if both typeRoots and types are defined at the same time.
–
Also keep in mind that Enonic globals such as app, log, etc only exists on the serverside.
In react4xp projects, server-side and “client-side” files can be in the same folder,
so setting up a perfect tsconfig.json file is impossible.
Either the Enonic Globals will be missing for both server and client, which is wrong for the server files.
Or the Enonic Globals will be present for both server and client, which is wrong for the client files…