I would like to use a small javascript library within a typescript project. (For the full example see here).
The javascript library defines the following:
"use strict";
exports.__esModule = true;
exports["default"] = functionOfInterest;
function functionOfInterest(val) { }
module.exports = exports["default"];
This has been typed using a .d.ts file as:
export default function functionOfInterest(val: number): void;
In a typescript file I use:
import functionOfInterest from "the-package";
functionOfInterest(1); // invoke it.
This is compiled to:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var functionOfInterest_1 = require("the-package");
functionOfInterest_1.default.apply(void 0, 1);
This errors with:
TypeError: Cannot read property 'apply' of undefined
My tsconfig.json file is:
{
"compilerOptions": {
"outDir": "js",
"module": "commonjs",
"declaration": true,
"target": "es5",
"lib": ["es6", "dom"],
"sourceMap": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "ts",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true
},
"exclude": [
"node_modules",
"build"
]
}
I'm sure there's just a simple configuration error somewhere but I can't figure it out at the moment.
Typescript 2.2.2
You have to use:
import functionOfInterest = require("the-package");
(functionOfInterest as any)(1);
** Alternatively **
You can change the definition file to:
declare function functionOfInterest(val: number): void;
export = functionOfInterest;
And then consume without the cast to any:
import functionOfInterest = require("the-package");
functionOfInterest(1);
Try this:
import * as _ thePackage from "the-package";
thePackage.functionOfInterest(1);
Related
I have been switching to typescript recently, before I used js and it worked perfectly.
I have the following lines in my file:
import Verifier from 'google-play-billing-validator';
var options = {
"email": serviceAccountSub["client_email"],
"key": serviceAccountSub["private_key"],
};
const verif = new Verifier(options);
Now the typescript compiler is telling me that "This expression is not constructable", referring to Verifier.
Now inside the google module we have this code:
declare const Verifier: {
new (options: Options): IVerifier;
};
export default Verifier;
I do not understand what is happening, Verifier should be the default export right?
I'm using this typescript config :
{
"compilerOptions": {
"resolveJsonModule": true,
"outDir": "./dist",
"allowJs": true,
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "nodenext",
"esModuleInterop": true,
},
"include": [
"./**/*"
]
}
I'm messing around with modules but came across this scenario that I can't fully grasp. I have everything set up like so:
import MyTesterImpl from "./MyTesterImpl";
declare module "./MyTesterImpl" {
interface MyTesterImpl {
augmented: boolean;
}
}
const main = async (): Promise<void> => {
let testy: MyTesterImpl = {
basicA: "hey",
basicB: "there"
} as MyTesterImpl;
testy.augmented = true;
};
main();
Where I have MyTestImpl defined as:
export default class MyTesterImpl {
public basicA: string;
public basicB: string;
constructor(a: string, b: string) {
this.basicA = a;
this.basicB = b;
}
showStuff() {
console.log(`${this.basicA} ${this.basicB}`);
}
}
Using a tsconfig defined as such:
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"lib": ["dom", "es6", "es2017", "esnext.asynciterable"],
"skipLibCheck": true,
"sourceMap": true,
"outDir": "./dist",
"moduleResolution": "node",
"declaration": false,
"removeComments": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"baseUrl": ".",
},
"exclude": ["node_modules", "**/*.d.ts", "**/*.spec.ts"],
"include": ["./**/*.ts"]
}
Even after adding the module augmentation in order to append the augmented field to the MyTesterImpl class, the compiler still throws the error that:
Property 'augmented' does not exist on type 'MyTesterImpl'.
You can see a reproducible example for the issue here.
I've been staring at this for hours and I can't find out why the error keeps persisting. I'm pretty positive I can do module augmentation between a class and interface as long as they share the same name, so I don't think that's the issue. And I made sure to point to the class file path when declaring the module for augmentation.
Everything looks in place to me; what am I missing here?
This is due to a bug in TypeScript whereby classes exported as default cannot be merged into; see microsoft/TypeScript#14080. The issue in GitHub has been open for a long time and is marked as being on the "Backlog", so I wouldn't count on it being fixed anytime soon.
A workaround mentioned in the issue is to re-export the class as a named export, and then merge into that. It would look something like
// ./MyTesterImplRepackaged.ts
import MyTesterImpl from "./MyTesterImpl";
export { MyTesterImpl };
and then
// ./index.ts
import { MyTesterImpl } from "./MyTesterImplRepackaged";
declare module "./MyTesterImplRepackaged" {
interface MyTesterImpl {
augmented: boolean;
}
}
const main = async (): Promise<void> => {
let testy: MyTesterImpl = {
basicA: "hey",
basicB: "there"
} as MyTesterImpl;
testy.augmented = true; // okay
};
It's not pretty, but it seems to work, at least for your example code.
CodeSandbox link
I am using the following package: https://www.npmjs.com/package/macos-release
Here is my code:
import macosRelease from 'macos-release';
import { asyncExec } from '../../helpers/os-util';
import OsReleaseService from './os-release.service';
export default class OsReleaseDarwinController extends OsReleaseService {
protected async getReleaseImpl() {
const releaseName = macosRelease().name;
const [releaseVersion, osBuildVersion] = await Promise.all([
asyncExec('/usr/bin/sw_vers -productVersion').catch(() => ''),
asyncExec('/usr/bin/sw_vers -buildVersion').catch(() => ''),
]);
return `MacOS ${releaseName} ${releaseVersion} ${osBuildVersion}`;
}
}
When I run the code, I get an error:
......../macos-release/index.js:1
import os from 'node:os';
^^^^^^
SyntaxError: Cannot use import statement outside a module
Here is my tsconfig:
{
"compilerOptions": {
"experimentalDecorators": true,
"target": "ES2018",
"module": "CommonJS",
"lib": ["dom", "esnext"],
"declaration": true,
"declarationMap": true,
"noEmit": true,
"jsx": "react",
"strict": false,
"pretty": true,
"sourceMap": true,
"typeRoots": ["./node_modules/#types", "./#types"],
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"allowJs": true,
"noImplicitAny": true,
"skipLibCheck": true
}
}
Is it possible to overcome this error without changing any configuration? I don't want to change tsconfig file nor package.json file
It appears this lib doesn't support common js. It seems like a pretty small lib, so maybe you could either create your own implementation or use a larger package
I'm using create-react-app in my ReactJS app with TypeScript, and I would like to import a TypeScript/JavaScript module that I created in another project.
The module consists of a file mymodule.js, in which the code looks approximately like this:
var mymodule;
(function (mymodule) {
var MyClass = /** #class */ (function () {
function MyClass() {
}
MyClass.myMethod = function () {
// code
};
return MyClass;
}());
mymodule.MyClass = MyClass;
})(mymodule || (mymodule = {}));
Then there is the type definition file mymodule.d.ts, which looks like this:
declare module mymodule {
class MyClass {
private static myMethod;
}
}
In my create-react-app project, I placed these two files in the folder /src/vendor, and I want to use the module like this:
import { MyClass } from '../vendor/mymodule';
...
However, Visual Studio Code (i.e. the TypeScript compiler) says
File '.../vendor/mymodule.d.ts' is not a module. ts(2306)
When I run the project, the variables from the module (e.g. the class MyClass) are undefined.
This might be the reason for the error: The library is generated using module: "AMD", but create-react-app seems to enforce module: "esnext".
Edit: Here's the tsconfig.json of the create-react-app project:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"jsx": "react",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true
},
"include": [
"src"
]
}
You can't import the file due to the fact that you are not exporting the module. In order for module loading to work, you should have an export at the bottom of your myModule class file.
export {
mymodule
}
I'm working on a project where the front-end and the back-end reside in the same directory and both use TypeScript.
I am using a shared path to store some interfaces and constants between the two projects.
But, when I try to export a constant from any file in /shared, I get a :
Error: Cannot find module '#shared/test'
server-config.ts:
"compilerOptions": {
"baseUrl": "./src/server/",
"sourceMap": false,
"module": "commonjs",
"moduleResolution": "node",
"target": "ES2017",
"types": ["node"],
"outDir": "./dist/",
"allowJs": true,
"typeRoots": [
"node_modules/#types"
],
"paths": {
"#shared/*": ["../shared/*"]
},
/shared/test.ts:
// If I remove the following line, no compile error, even finds TheTest
export const TEST = 'test';
export class TheTest {
}
import
// << Module not found (only if I import TEST)
import { TEST, TheTest } from '#shared/test';
export function Foo() {
console.log(TEST);
}