How to use TypeScript ambient declaration interfaces in interface declared in d.ts file - node.js

I want to do a helper in .ts file like:
class ResponseHelper implements IResponseHelper {...}
and IResponseHelper is simple .d.ts file with
import * as mongoose from 'mongoose';
import * as express from 'express'
interface IResponseHelper {
toStandartResponse(response: mongoose.Promise<any>, res: express.Response): mongoose.Promise<any>;
}
as you can see params in toStandartResponse are coming from mongoose which is ambiently declared. So this if fine but if i do so I cannot us it with 'implements' like class ResponseHelper implements IResponseHelper because I got errror 'Could not find symbol IResponseHelper in external module ResponseHelper' in other words compiler cannot see d.ts file.
If i remove import statements from d.ts. file everuthing is ok but i cannot specify response types then.
Is there any way to use it all together?

I believe when you use import in makes the file a module, so you must export any members you want visible:
export interface IResponseHelper { }
Now you can import it from other files:
import {IResponseHelper} from "./IResponseHelper";
class ResponseHelper implements IResponseHelper { }

Related

Compiler error on using namespace's parameterized constructor of a class

I want to initialize a class present in Typescript's namespace. This class has a parameterized constructor, but when I tried to use this class then compiler complains about it and I cannot use this class for instantiation.
**Inside file tv.dto.ts**
export namespace tv{
export class Trial{
private name:string;
Trial(name:string){
this.name=name;
}}}
Inside my other Jest class file.
import { tv } from "./tv.dto";
import {Graph} from 'graphlib';
describe('testing',()=>{
it('TestCase1',() =>{
let k=new tv.Trial("WonderFulName");// It flags compiler error here.
console.log(JSON.stringify(k));
});
});
Error message which I received was "TS2554: Expected 0 arguments, but got 1."
Screenshot for the same.
Please help me in resolving this issue.
Edit:
I am able to resolve this issue by importing properly:
import {tv as tv} as './tv.dto'
Don't export the namespace, instead just keep the export of Trial. Then import that instead from the same file reference.
Edit: Alternatively, change the constructor to use the word "constructor" instead of the class name.

extend express request object with sequelize model using typescript 2

I have some models, such as:
import * as Sequelize from 'sequelize'; // !
export interface UserAttributes {
id?: number;
email?: string;
googleToken?: string;
}
export interface UserInstance extends Sequelize.Instance<UserInstance, UserAttributes>, UserAttributes {
}
export interface UserModel extends Sequelize.Model<UserInstance, UserAttributes> {
}
// ... model definition
I need use import statement to use generic type Sequelize.Instance<TInstance, TAttributes>
I wright some middleware to add user instance to request object (or req.session object, doesn't metter)
Then I need typescript to know my new extending, for this I have file src/_extra.ts with content:
/// <reference path="./models/db.ts" /> -- also does not work
declare namespace Express {
export interface Request {
oauthClient: Googleapis.auth.OAuth2; // Googleapis is namespace
user?: UserInstance; // or ContactsProject.Models.UserInstance;
}
export interface Session {/* ... some same */}
}
I need to import my UserInstance type from my model file. Imports break all my _extra namespace definitions, inside namespace I can't use imports.
I have tried create namespace ContactsProject, but I getting same problem: if I use imports, typescript don't see my namespace, if I don't, I cant define my UserInstance type.
Sequelize doesn't declare namespaces.
I just want import some generic type in my namespace.
I use typescript Version 2.0.3.
When you use an import statement in a file, TypeScript treats it as a module. Therefor any namespace you declare inside it will not be global anymore, but local to that module.
Import your interface, and then wrap the namespace declaration in a declare global { ... }.

Difference between `import from` and `import require` in TypeScript

I use node.js and I recently decided to give TypeScript a shot, But I'm kinda confused on how modules get imported. I see two different syntax that I couldn't find out what's their difference exactly:
import * as a from 'a'; // ES6 standard to import stuff
// OR ...
import a = require('a');
Are these the same thing? and if they're not, where should I use each one of them?
import * as a from 'a'; is the new "ES6 style" import syntax (available since Typescript 1.5).
Whenever possible, this syntax should now be used.
There is one caveat though. The ES6 import syntax can only import modules (as defined by ES6) or objects (classes, interfaces, vars,... ) exported as part of a module.
Some Javascript librairies will directly export a function or class, and the corresponding definition file will typically look like this:
declare module "my-class" {
class MyClass { ... }
export = MyClass
}
In this case, the "old" import syntax is the only one that can be used
import MyClass = require("my-class");
Failure to use this syntax will result in error TS2497
Check this issue for details and a possible workaround which would be, in the previous case, to add an empty module declaration to the definition file
declare module "my-class" {
class MyClass { ... }
module MyClass {} // <=
export = MyClass
}

Inheritance TypeScript with exported class and modules

I'm getting crazy with inheritance using typescript. I don't know why but it cannot resolve the class I want to inherit.
lib/classes/Message.class.ts
///<reference path='./def/lib.d.ts'/>
///<reference path='./def/node.d.ts'/>
export module SharedCommunication {
export class Message{
// Stuff
}
}
lib/classes/ValidatorMessage.class.ts
///<reference path='./def/lib.d.ts'/>
///<reference path='./def/node.d.ts'/>
///<reference path='Message.class.ts'/>
export module SharedCommunication {
export class ValidatorMessage extends Message{
private _errors;
}
}
Message cannot be resolved. I tried SharedCommunication.Message too but it's the same. I reference the class so I don't understand at all what's going on. Do you have any idea?
I tried without the module (two class without be in any module) but it's the same. I need to export the class (and the module if I use it) to get them from another node_module: typescript.api, which I use to load the class and use it in node.
lib/message.js
var Message = require('./classes/Message.class.ts');
module.exports = Message.SharedCommunication.Message;
What's the trick here? Because I have source code on the same project in a different folder working with inheritance, without module or export. Thanks.
ValidatorMessage.class.ts should look like this:
///<reference path='./def/lib.d.ts'/>
///<reference path='./def/node.d.ts'/>
import message = require('./Message.class');
export module SharedCommunication {
export class ValidatorMessage extends message.SharedCommunication.Message {
private _errors;
}
}
It's usually redundant to have a single export module at the top level of a file since the file itself constitutes a namespace anyway.
Bill mentioned this in your other question, but I'd again caution on using RequireTS if you're just starting out with TypeScript - it sounds pretty unmature and is likely to introduce a lot of confusion.
Take out the export from the mododule declaration:
module SharedCommunication
{
export class ValidatorMessage extends message.SharedCommunication.Message
{
private _errors;
}
}

TypeScript module import in nodejs

What is best practice for importing modules in nodejs with typescript? I come from c# background so I want to do something like this
MyClass.ts
module MyNamespace {
export class MyClass {
}
}
app.ts
// something like using MyNamespace
new MyNamespace.MyClass();
or
MyClass.ts
export class MyClass {
}
app.ts
import MyClass = module("MyClass")
new MyClass();
I know I can do this and it will work, but then I have to think up for two names for each class
import MyClass2 = module("MyClass")
new MyClass2.MyClass();
Point is separating classes to multiple .ts files (preferably one file per class). So question is, how is this done?
You have two choices here:
If you insist on using CommonJS or AMD modules, then you will have to use external modules just the way you described it in your question. Whether or not you use a module to declare your own namespace is mostly a matter of taste. The only way to circumvent the issue of specifying two names is to create a variable that aliases the type:
mymodule.ts
export module MyNamespace {
export class MyClass {
}
}
app.ts
import ns = require('mymodule');
var myclass = new ns.MyNamespace.MyClass();
var myclassalias = ns.MyNamespace.MyClass;
var myclass2 = new myclassalias();
Your other option is to use internal modules which are mostly used to structure your code internally. Internal modules are brought into scope at compile time using reference paths.
mymodule.ts
module MyNamespace {
export class MyClass {
}
}
app.ts
///<reference path='mymodule.ts'/>
var myclass = new MyNamespace.MyClass();
I think you'll have to decide for yourself which of those two approaches is more appropriate.
You can import TypeScript modules into a node.js file using the typescript-require module, which was created for this specific purpose.
I would recommend against using the explicit module (or namespace) keyword, it's a vestigial remnant of an earlier time.* You generally don't need them because any typescript file with a top-level import or export is automatically a module. Your second myModule.ts example was good.
export class MyClass {
...
}
But when you import it to another typescript module, you'll want to use something like this:
import { MyClass } from './myModule';
var myInstance = new MyClass();
Personally, I don't like repetitiveness of line 1, but it is what the language calls for, so I've learned to accept it. I think the utility of this syntax isn't apparent unless you abandon the file-per-class pattern. You pick and choose what names to import from the module, so that no unintended namespace pollution occurs.
An alternative import syntax pulls in all names from the module, but you must qualify the names with the module when you use them. Therefore it is also name collision resistant.
import * as myModule from './myModule';
var myInstance = new myModule.MyClass();
There are exceptions to the general rule about not needing module / namespace keywords, but don't start by focusing on them. Think file == module.

Resources