.default is not a constructor using declaration file with javascript package - javascript

I am using external javascript package, which doesn't have default export and declaration file. I thought of writing one myself, but I have a problem importing it after I do just that.
Javascript package that I wrote declaration file to looks like this:
function Speech() {
// code
}
Speech.prototype.say = function (saying) {
// code
};
module.exports = Speech;
My declaration file:
declare class Speech() {
constructor()
say(saying: string): Speech
}
export default Speech
When I try to import this package in my .ts files using imports like this:
import Speech from './index'
And try to initialize it:
const speech = new Speech()
I get an error saying index_1.default is not a constructor.
If I import module using another import like:
import Speech = require('./index')
It works as intended and doesn't throw any errors.
Is it possible to somehow fix declaration file, so that I could use default imports and I wouldn't have to use require?
Or is using import with require the right way in my situation?
Thanks

Related

Cannot import Javascript file in other Javascript file

For a project, I'm using Django for my backend, HTML/CSS/JS for frontend.
For one HTML page, I use two JS files: dom_creator.js and console_page.js. I would like to use the functions of dom_creator in console_page, but whatever I try, I cannot find the right statement to import (and many of the ES6 import statements even make my console_page.js to stop working).
I also have a module imported to my HTML (console_module.js). In that file, I have no issue importing dom_creator.js with
import {function1, function2} from "./dom_creator.js"
How would I be able to import functions from dom_creator in console_page.js (which is not a module)? I've tried all suggestions on Stack Overflow, but none of them seem to work.
the problem maybe in html code when you tried to import js files
add TYPE = "MODULE" to script element
script type="module" src="./myscript.js" script
and at js file to import, use
function print(y){
console.log(y);
}
export {print};
to import the x function in another js file do the following:
import {print} from "./main.js" // dont forget .js
// another way to import all functions
import * as main from "./main.js" // dont forget .js
//to use the last one:
let variable = main.print('hello word');
For importing a function into the other file, first, you need to export it,
so if you are using es5 (mostly the case in NodeJs) you need to export it as below:
var myfunction = function () {}
module.exports = { myfunction }
and in newer versions (es6+) you can use export like this:
var myfunction = function () {}
export myfunction;
// then you can import it like: import {myfuntion} from 'file.js';
// or with another name: import {myfuntion as john} from 'file.js';
// or export it as default like:
export default myfunction;
// then you can import it like import myfuntion from 'file.js';
// or any other custom name: import john from 'file.js';
the only thing I couldn't understand from your question is the relation of with question with Django ๐Ÿค”

Importing NodeJs into TypeScript compiling errors

I am trying to import a nodejs class into the typescript code using a declaration (d.ts) file.
To test it I created a simple nodejs class, declaration file and the typescript file that is going to import (consume) the nodejs class.
contents of TS_PROJECT/node_modules/newtest/index.js:
var HelloWorld = function() {
}
HelloWorld.hello2 = function() {
console.log("hello2");
}
HelloWorld.prototype.hello1 = function() {
console.log("hello1");
}
module.exports = HelloWorld;
So as you can see, it's a class that will have a member function "hello1" and a static function "hello2".
Now i'm trying to declare it in TS_PROJECT/newtest/index.d.ts:
declare module newtest {
export class HelloWorld {
hello1():void;
static hello2():void;
}
}
export = newtest;
And eventually trying to consume it from index.ts:
/// <reference path="./newtest/index.d.ts" />
import * as mymodule from "newtest";
Now I'm trying to instantiate the object and call the functions but no matter what i try it doesn't compile. I tried lots of variations, but none of them works. For example this:
// Doesn't Work
import HelloWorld = mymodule.HelloWorld;
let s: HelloWorld = new HelloWorld();
// It results with the following compile errors:
// error TS2339: Property 'HelloWorld' does not exist on type 'typeof "newtest"'.
// error TS2694: Namespace '"newtest"' has no exported member 'HelloWorld'.
I won't list all the rest of my variations. But i would appreciate if anybody could help me with proper declaration and instantiation of the object.
Thank you!
You don't need to import the type, since you're already importing everything from the module and naming it mymodule. You can do a couple things:
Import the class directly:
import { HelloWorld } from 'newtest'
let s:HelloWorld = new HelloWorld();
Access the type from the imported module:
import * as mymodule from 'newtest';
let s:mymodule.HelloWorld = new mymodule.HelloWorld();
Create a local variable reference to the type:
import * as mymodule from 'newtest';
const HelloWorld = mymodule.HelloWorld;
let s = new HelloWorld();
I think i figured the answer. In my example the declaration module "newtest" represents the exported nodejs object. Since the exported object is already HelloWorld object, it's wrong to define inside another class HelloObject.
So the simplest solution would be to have a nodejs code like:
var HelloWorld = function () {
}
HelloWorld.hello2 = function () {
console.log("hello2");
}
HelloWorld.prototype.hello1 = function () {
console.log("hello1");
}
// Only this part changed
module.exports.HelloWorld = HelloWorld;
This way we are exporting an object that has HelloWorld class inside. That fixed the compilation and the compiled JS.
Also another issue that I had, in the declaration file "newtest" has to be in quotes. Only that way it attaches the module to the nodejs package.
These to fixes solved my problem. But the question is still remains. What if I still have to use "module.exports = HelloWorld;"? How should I declare this module in this case?

React Native: How to split a file up into multiple files and import them?

I am writing my first app in react native and my js file is getting pretty big. What is the proper way to split the file up.
If i have something like
var MyClass = React.createClass({
...
})
Can I save it at myclass.js and include in by some command in another js file?
Here is the updated solution with using the import statement (in latest React-Native and generally Javascript adhering to ECMAScript6 and later):
file1 myClass.js:
export default class myClass {...}
file2 app.js:
import myClass from './myClass';
This is the basic version using a single default export. You can also export named exports that have to be explicitly listed on import. For more info see export and import.
In general you can do the following:
var MyClass = React.createClass({
...
)}
module.exports = MyClass;
This way you tell what should be publicly available.
And then, in your former big file you can load the contents like this:
var MyClass = require('./myclass.js');
Require returns the object that references the value of module.exports.

TypeScript ES6 import module "File is not a module error"

I am using TypeScript 1.6 with ES6 modules syntax.
My files are:
test.ts:
module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
}
main.ts:
import App from './test';
var a = new App.SomeClass();
When I am trying to compile the main.ts file I get this error:
Error TS2306: File 'test.ts' is not a module.
How can I accomplish that?
Extended - to provide more details based on some comments
The error
Error TS2306: File 'test.ts' is not a module.
Comes from the fact described here http://exploringjs.com/es6/ch_modules.html
17. Modules
This chapter explains how the built-in modules work in ECMAScript 6.
17.1 Overview
In ECMAScript 6, modules are stored in files. There is exactly one
module per file and one file per module. You have two ways of
exporting things from a module. These two ways can be mixed, but it is
usually better to use them separately.
17.1.1 Multiple named exports
There can be multiple named exports:
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
...
17.1.2 Single default export
There can be a single default export. For example, a function:
//------ myFunc.js ------
export default function () { ยทยทยท } // no semicolon!
Based on the above we need the export, as a part of the test.js file. Let's adjust the content of it like this:
// test.js - exporting es6
export module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
export class OtherClass {
getName(): string {
return 'name';
}
}
}
And now we can import it in these three ways:
import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";
And we can consume imported stuff like this:
var a1: app1.App.SomeClass = new app1.App.SomeClass();
var a2: app1.App.OtherClass = new app1.App.OtherClass();
var b1: app2.App.SomeClass = new app2.App.SomeClass();
var b2: app2.App.OtherClass = new app2.App.OtherClass();
var c1: App.SomeClass = new App.SomeClass();
var c2: App.OtherClass = new App.OtherClass();
and call the method to see it in action:
console.log(a1.getName())
console.log(a2.getName())
console.log(b1.getName())
console.log(b2.getName())
console.log(c1.getName())
console.log(c2.getName())
Original part is trying to help to reduce the amount of complexity in usage of the namespace
Original part:
I would really strongly suggest to check this Q & A:
How do I use namespaces with TypeScript external modules?
Let me cite the first sentence:
Do not use "namespaces" in external modules.
Don't do this.
Seriously. Stop.
...
In this case, we just do not need module inside of test.ts. This could be the content of it adjusted test.ts:
export class SomeClass
{
getName(): string
{
return 'name';
}
}
Read more here
Export =
In the previous example, when we consumed each validator, each module only exported one value. In cases like this, it's cumbersome to work with these symbols through their qualified name when a single identifier would do just as well.
The export = syntax specifies a single object that is exported from the module. This can be a class, interface, module, function, or enum. When imported, the exported symbol is consumed directly and is not qualified by any name.
we can later consume it like this:
import App = require('./test');
var sc: App.SomeClass = new App.SomeClass();
sc.getName();
Read more here:
Optional Module Loading and Other Advanced Loading Scenarios
In some cases, you may want to only load a module under some conditions. In TypeScript, we can use the pattern shown below to implement this and other advanced loading scenarios to directly invoke the module loaders without losing type safety.
The compiler detects whether each module is used in the emitted JavaScript. For modules that are only used as part of the type system, no require calls are emitted. This culling of unused references is a good performance optimization, and also allows for optional loading of those modules.
The core idea of the pattern is that the import id = require('...') statement gives us access to the types exposed by the external module. The module loader is invoked (through require) dynamically, as shown in the if blocks below. This leverages the reference-culling optimization so that the module is only loaded when needed. For this pattern to work, it's important that the symbol defined via import is only used in type positions (i.e. never in a position that would be emitted into the JavaScript).
Above answers are correct. But just in case...
Got same error in VS Code. Had to re-save/recompile file that was throwing error.
How can I accomplish that?
Your example declares a TypeScript < 1.5 internal module, which is now called a namespace. The old module App {} syntax is now equivalent to namespace App {}. As a result, the following works:
// test.ts
export namespace App {
export class SomeClass {
getName(): string {
return 'name';
}
}
}
// main.ts
import { App } from './test';
var a = new App.SomeClass();
That being said...
Try to avoid exporting namespaces and instead export modules (which were previously called external modules). If needs be you can use a namespace on import with the namespace import pattern like this:
// test.ts
export class SomeClass {
getName(): string {
return 'name';
}
}
// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();
In addition to A. Tim's answer there are times when even that doesn't work, so you need to:
Rewrite the import string, using the intellisense. Sometimes this fixes the issue
Restart VS Code
I had this issue and I had forgotten to export the Class.
In addition to Tim's answer, this issue occurred for me when I was splitting up a refactoring a file, splitting it up into their own files.
VSCode, for some reason, indented parts of my [class] code, which caused this issue. This was hard to notice at first, but after I realised the code was indented, I formatted the code and the issue disappeared.
for example, everything after the first line of the Class definition was auto-indented during the paste.
export class MyClass extends Something<string> {
public blah: string = null;
constructor() { ... }
}
Just in case this may works for you as it did form me, i had this files
//server.ts
class Server{
...
}
exports.Server = Server
//app.ts
import {Server} from './server.ts'
And this actually raised an error but i changed server.ts to
//server.ts
export class Server{
...
}
and it worked ๐Ÿ˜Ž๐Ÿ‘Œ
Note: i am using this config
"target": "esnext",
"module": "commonjs",
I faced the same issue in a module that has no exports. I used it for side-effects only. This is what the TypeScript docs say about importing side-effects modules:
Though not recommended practice, some modules set up some global state that can be used by other modules. These modules may not have any exports, or the consumer is not interested in any of their exports. To import these modules, use:
import "./my-module.js";
In that situation, you can fix the "File is not a module" error by simply exporting an empty object:
// side-effects stuff
export default {};
I faced the same issue ("File is not a module error") for import js in vue component
import handleClientLoad from "../../../public/js/calendar.js"
I do this and solve it
// #ts-ignore
import handleClientLoad from "../../../public/js/calendar.js"
The file needs to add Component from core hence add the following import to the top
import { Component } from '#angular/core';

TypeScript: access global var from a class without import

I got this module like this:
module MyModule {
export class Constants {
public static WIDTH:number = 100;
public static HEIGHT:number = 100;
....
}
}
export = MyModule;
Now I need to use MyModule.Constants.WIDTH in another class but I can't use import (I need to deliver this class js to a third party, and they don't use requirejs). Right now I use reference to get code checking but it keep giving this error (at transpilling time)
error TS2095: Could not find symbol 'MyModule'
What should I do now so I can use autocomplete and get rid of this error?
I hope you're not mindplay on the TypeScript forum otherwise I'm about to repeat myself.
export and import work together. You should either be using both or neither. If you check what the generated code looks like with and without the export keyword you'll see that export causes a module to be built. Since the third party can't use RequireJS I don't think this is what you want.
I would structure my classes like the following:
// file pkg/Foo.ts
module company.pkg {
export class Foo {}
}
// file pkg2/Bar.ts
module company.pkg2 {
export class Bar{}
}
Putting everything into the name space of your company minimizes the chance of a conflict with another library. Classes know about each other using a reference /// <reference path="..." /> which will allow it to compile.
Since you're not doing modules I would also compile to a single file using --out filename.js. That gets all the files included in (usually) the right order.

Categories