How to find type definition file for xss-clean npm library - node.js

I just started to learn typescript and just started converting my nodejs/express application to typescript.
I have successfully got all types for the library using npm i #types/some-lib
only library, I can't find was npm i #types/xss-clean
where to find this library
import xss from 'xss-clean' //getting type definition error
app.use(xss())

If the library does not have many TypeScript users, chances are that no published types exist. In that case you can add your own to whatever degree of detail you wish.
You can create a type definition file, e.g. xss-clean.d.ts:
declare module 'xss-clean'
{
const value: Function;
export default value;
}
[More on declaration files]

You can use this page to look up if a package has types or not. xss-clean does not seem to have any types yet, so you would have to declare them by yourself.
More info on that here.

Related

Missing type definition information in VS Code when own Node.js package is published on NPM

I cannot figure out why, once my own efficy-enterprise-api NPM package is published, the type definitions (used by VS Code intellisense) are not available anymore compared to locally referencing the package, e.g. import { CrmRpc} from "../efficy-enterprise-api";
Package is written in native ES6 (using .mjs extension) with JSDoc annotations.
No issue when locally referencing the Node.js package:
import { CrmRpc } from "../efficy-enterprise-api";
const crm = new CrmRpc(); // Type definition CrmRpc is accessible
const Cont = crm.openEditObject("Cont", 0); // Type definition "EditObject" is accessible
Missing type definitions when referencing the published package:
import { CrmRpc} from "efficy-enterprise-api";
const crm = new CrmRpc(); // Type definition CrmRpc is accessible
const Cont = crm.openEditObject("Cont", 0); // Type definition "EditObject" is not accessible anymore...
I deduced the issue to the usage of the separated ./#typings folder for the generate .mts and .mts.map files. I was unable to find a functional configuration of package.json to point to these multiple generated files (not only index.mjs)
By running typescript tsc without outDir=#typings configured, the typings are fully functional.

Stripe + TypeScript: How to extend #types/stripe definitions for stripe-node?

I'm working on project, where we're using Stripe library for Node. We also want to use TypeScript on this project.
I've figured out that Stripe isn't providing official TypeScript definitions but I've found some community definitions #types/stripe on NPM. So I installed them and after a while I got an error:
Property 'sources' does not exist on type 'Stripe'.
Well there are missing some definitions, for example for this stripe.sources-related functionality.
I want to add missing definitions locally. So I need to extend this file:
#types/stripe/index.d.ts
I think that for the problem above I need:
to add property sources: Stripe.resources.Sources; to class Stripe,
to add class Sources to namespace resources,
to add missing function declarations to class Sources.
The problem is that I really don't know how. How should the .d.ts file with extensions look like? I've made many attempts according some examples and TypeScript docs but it always doesn't work. Do you have any idea?
I don't believe there's a way to augment the export-assigned Stripe class; the problem is similar to this open issue about augmenting a default-exported class. At this time, since you can't use augmentation, you'll have to fork the #types/stripe definitions for your project, and then you may as well make all the desired changes that way.
I think my colleague has found a solution that works for me. Here is how he made it:
import ST from 'stripe'
declare module 'stripe' {
namespace sources {
interface ISource extends IResourceObject {
...
}
interface ISourceCreationData {
...
}
}
namespace resources {
class Sources {
create(data: sources.ISourceCreationData): Promise<sources.ISource>;
retrieve(source: string, client_secret?: string): Promise<sources.ISource>;
}
}
class Stripe extends ST {
sources: ST.resources.Sources;
}
}

Having error "Module 'name' resolves to an untyped module at..." when writing custom TypeScript definition file

I can't find TypeScript definition #type/{name} for one of my installed NodeJS packages, so I attempt to write a d.ts file for it, and put the file in {project root}\typings folder. This is how I do:
// My source code: index.ts
import Helper from 'node-helper-lib';
// My definition: \typings\node-helper-lib.d.ts
declare....(something else)
declare module 'node-helper-lib' {
class Helper { ... }
export = Helper;
}
However, Visual Studio Code keeps yielding this error and puts red line under declare module 'node-helper-lib':
[ts] Invalid module name in augmentation. Module 'node-helper-lib'
resolves to an untyped module at '{project
path}\node_modules\node-helper-lib\index.js', which cannot be
augmented.
Isn't it legit that because the library is untyped, so I should be allowed to add typing to it?
UPDATE:
I am using:
TypeScript: 2.1.4
Visual Studio Code: 1.9.1
Node JS: 6.9.4
Windows 10 x64
The actual solution is given in a comment by #Paleo in #hirikarate's answer:
Imports should be declared inside the module declaration.
Example:
declare module 'node-helper-lib' {
import * as SomeThirdParty from 'node-helper-lib';
interface Helper {
new(opt: SomeThirdParty.Options): SomeThirdParty.Type
}
export = Helper;
}
After some tries and errors, I found that augmentation means "declaring a module in the same file with other module declaration(s)".
Therefore if we want to write a definition file for an untyped 3rd-party JavaScript library, we must have ONLY ONE declare module 'lib-name' in that file, and 'lib-name' must exactly match the library name (can be found in its package.json, "name" property).
On the other hand, if a 3rd-party library already has definition file .d.ts included, and we want to extend its functionalities, then we can put the additional definition in another file that we create. This is called augmenting.
For example:
// These module declarations are in same file, given that each of them already has their own definition file.
declare module 'events' {
// Extended functionality
}
declare module 'querystring' {
// Extended functionality
}
declare module '...' { ... }
I leave my discovery here just in case somebody has same question. And please correct me if I missed something.
The issue for me was that I was trying to declare the module in a .ts file. I changed it to .d.ts and it all worked just fine.
I was getting that error message too. The issue for me was that I was trying to declare another module in an existing type definition file that had a module declaration in it. After I moved the new module declaration to a new file, the error went away.

Why does tsc give so cryptic errors when leaking transitive implementation types?

I have a node module A depending on another node module B, both written in Typescript. Module B returns Promises to A and have chosen bluebird as the Promise implementation. B of course have typings for bluebird.
However, if A doesn't have typings of bluebird (which it probably shouldn't in my case), I get errors like:
~/d/p/ensime-vscode ❯❯❯ tsc -p . ⏎ master ✭ ✱
node_modules/ensime-client/**/file-utils.d.ts(1,26):
error TS2307: Cannot find module 'bluebird'.
It took me a while to realize that this was due to me leaking the concrete Promise type of bluebird. Changing all the public return types to PromiseLike made the errors go away.
My question is, is there a way to detect these earlier on my independent module B? I recall sometimes getting errors when modules leaked types that wasn't public before, but in this case module B built just fine. It's all very blurry to me this thing since I'm very new to Typescript. I guess Typescript is a different beast compared to what I'm used to.
Also, isn't it possible for tsc to emit better error messages for these cases?
Small update:
When I'm "leaking" a type that is locally defined this is caught directly in B:
export interface CompletionsResponse extends Typehinted {
completions: [Completion]
}
interface Completion {
}
[ts]
Property 'completions' of exported interface has or is using private name 'Completion'.
interface Completion
I would like to be able to catch this kind of thing directly if I'm exposing something from a dependency like 'bluebird'.Promise as well. It was never my intention to expose 'bluebird' as a transitive dependency, and I honestly don't even know how to do that with typings? So as this builds just fine, what has happened is that 'bluebird' silently became a typings "peer dependency" in npm toungue.
If a package has a type dependency on another module, this dependency should be included in the package's typings.json, with typings install bluebird --save.
Your type declaration of module B should look something like this type declaration for redux-persist (but then inside your actual project). It depends on redux for several types. Therefore, there is a dependency listed in the typings.json.
Concerning typescript error messages, they're kind of a pain. ¯\_(ツ)_/¯

How to import node module in TypeScript without type definitions?

When I try to import node.js module in TypeScript like this:
import co = require('co');
import co from 'co';
without providing type definitions, both lines reports same error:
error TS2307: Cannot find module 'co'.
How to import it correctly?
The trick is to use purely JavaScript notation:
const co = require('co');
Your options are to either import it outside TypeScript's module system (by calling a module API like RequireJS or Node directly by hand) so that it doesn't try to validate it, or to add a type definition so that you can use the module system and have it validate correctly. You can stub the type definition though, so this can be very low effort.
Using Node (CommonJS) imports directly:
// Note there's no 'import' statement here.
var loadedModule: any = require('module-name');
// Now use your module however you'd like.
Using RequireJS directly:
define(["module-name"], function (loadedModule: any) {
// Use loadedModule however you'd like
});
Be aware that in either of these cases this may mix weirdly with using real normal TypeScript module imports in the same file (you can end up with two layers of module definition, especially on the RequireJS side, as TypeScript tries to manage modules you're also managing by hand). I'd recommend either using just this approach, or using real type definitions.
Stubbing type definitions:
Getting proper type definitions would be best, and if those are available or you have time to write them yourself you should definitely should.
If not though, you can just give your whole module the any type, and put your module into the module system without having to actually type it:
declare module 'module-name' {
export = <any> {};
}
This should allow you to import module-name and have TypeScript know what you're talking about. You'll still need to ensure that importing module-name does actually load it successfully at runtime with whatever module system you're using, or it will compile but then fail to actually run.
I got an error when I used the "Stubbing type definitions" approach in Tim Perry's answer: error TS2497: Module ''module-name'' resolves to a non-module entity and cannot be imported using this construct.
The solution was to rework the stub .d.ts file slightly:
declare module 'module-name' {
const x: any;
export = x;
}
And then you can import via:
import * as moduleName from 'module-name';
Creating your own stub file lowers the barrier to writing out real declarations as you need them.
Just import the module the following way:
import 'co';

Resources