Typescript 2: Custom Type definition in node_modules - javascript

Let's say I publish a custom library called my-library. This library will be of the structure
node_modules/
my-library/
lib/
index.js
src/
...
typings/
index.d.ts
package.json
Say now I export default something called Application from the index.js, so you use it by import Application from 'my-library';
Now, in my index.d.ts I want to declare its typing:
export = Application;
export as namespace Application;
declare namespace Application {
function foo(arg1: string): object;
}
I know expect this to return an error but it does not:
import Application from 'my-library';
Application.foo(123)[0].blahblah;
Not only is the argument wrong, but so is the use of the return value. I don't know how I am supposed to add my type definitions so that the above works.

You can look here to see where Typescript looks for definitions.
What you probably want is to add a types in your package.json to point to a custom definition file.
{
"types": "typings/index.d.ts",
}

Related

ESLint: constructors and enum values are reported as unused but they are used in app.ts

I have a NodeJS project with Express and TypeScript.
Some of the classes/enums usied in the project are reported by ESLint as unused althought they are used in the project's entrypoint file (app.ts in my case).
For instance, I have a class defined in handler/RequestHandler.ts as follows:
export class RequestHandler {
constructor (private readonly manager: Manager) {}
...
}
The in the app.ts it is used like this:
import { RequestHandler } from './handler/RequestHandler'
//....
const handler = new RequestHandler(manager)
But when I run linter I get:
/path-to-my-project-root/src/handler/RequestHandler.ts
5:2 error Useless constructor no-useless-constructor
I thought it ignores app.ts but if I break linter rules for app.ts (for instance by adding unneeded spaces) it would report it.
The same happens with enumeration values.
Question: How to make ESLint see constructor/enum usages in the app.ts file?
Check out the project FAQ which answers your question:
https://typescript-eslint.io/docs/linting/troubleshooting#i-am-using-a-rule-from-eslint-core-and-it-doesnt-work-correctly-with-typescript-code
Specifically, you're using the wrong lint rule.
https://typescript-eslint.io/rules/no-useless-constructor/

TypeScript declarations for JavaScript module

I recently started using a Node library called bpmn-js (npmjs.com).
It is written in JavaScript, and I'd like to have typings. Thus, I've began reading about d.ts files.
I created this folder structure
webapp
#types
bpmn-js
index.d.ts
With a simple content
declare module 'bpmn-js' {
export class BpmnJS {
constructor();
}
}
But this doesn't seem to work.
"Before" typings, I was able to import the object I needed using
import BpmnJS from 'bpmn-js';
And I was able to instantiate it using
new BpmnJS();
How can I get the typings file to be recognized?
I'm using WebStorm 2019.1.*.
Pretty simple, I was missing export default, or better, the default part.
declare module 'bpmn-js' {
export default class BpmnJS {
constructor(param?: { container: string });
...
}
}
Now this works too
import BpmnJS from 'bpmn-js';

Import JS web assembly into TypeScript

I'm trying to use wasm-clingo in my TypeScript React project. I tried to write my own d.ts file for the project:
// wasm-clingo.d.ts
declare module 'wasm-clingo' {
export const Module: any;
}
and import like this:
import { Module } from 'wasm-clingo';
but when I console.log(Module) it says undefined. What did I do wrong?
Notes:
clingo.js is the main js file.
index.html and index_amd.html are two example pages
Solution:
I solved the problem like this:
// wasm-clingo.d.ts
declare module 'wasm-clingo' {
const Clingo: (Module: any) => Promise<any>;
namespace Clingo {}
export = Clingo;
}
and
import * as Clingo from 'wasm-clingo';
Here's the source for this solution
I know you found a solution acceptable to you; however, you don't really have any types here, you just have Module declared as any, which gives you no typescript benefits at all. In a similar situation I used #types/emscripten, which provides full type definitions for web assembly modules compiled using emscripten. You simply need to do:
npm install --save-dev #types/emscripten
then change your tsconfig.json types array to add an entry for emscripten.
After that you can just write Module.ccall(...) etc. If you like you could of course write const Clingo = Module and then make calls against that if you want a more descriptive name than Module (which is a terrible name!).
You're welcome ;)
I think the issue is that wasm-clingo exports the module itself but import { Module } from 'wasm-clingo' expects a property.
Try
import Clingo_ from 'wasm-clingo';
const Clingo: typeof Clingo_ = (Clingo_ as any).default || Clingo_;

FlowTypes how to import types from private npm module

I am writing private npm package to use internally, I also want to include some flowtypes in there that will be shared between internal projects and imported in following format import type {SomeType} from 'our-private-lib' But I am having trouble in doing so, what is the best approach to include flow types with npm package?
Currently I am transpiling all ES code with babel and then also using flow-copy-source to copy original files over along side transpiled files but with .js.flow extension, but then that means that the name of these files should be the same as the transpiled file?
For example if I have file in /super-schema/index.js with
export type SuperSchemaType = {
prop1: boolean,
prop2: string
}
const SuperSchema = {
prop1: true,
prop2: 'Hello'
}
module.exports = SuperSchema;
And package.json points to main file index.js which exports SuperSchema like so
module.exports = {
superSchema: require('./super-schema.js/index.js');
}
I then can import that like so
import {superSchema} from 'our-private-lib';
but what about flowtype? import type { SuperSchemaType } from 'our-private-lib'; Doesn't really work
Your general approach is correct (using flow-copy-source), but if you want to consume types out of the main entry point of your module, you need to export the types out one way or another. You can do that explicitly by doing something like
export type {
SuperSchemaType
} from './super-schema';
Or, if you're using babel 7, export type * might be useful for you
export type * from './super-schema';

How do we declare import types from NPM library that has no declaration files?

For example, if I have the following in my app,
import Node from 'infamous/motor/Node'
console.log(Node)
that works just fine. But the moment I actually do something with it,
import Node from 'infamous/motor/Node'
console.log(new Node)
then TypeScript will complain because there's no type definition for Node. How do I define the type of Node?
The library has no type declarations of it's own. I tried something like
import MotorNode from 'infamous/motor/Node'
declare class MotorNode {}
console.log(' --- ', new MotorNode)
but I get the error
./src/app.tsx(6,8): error TS2440: Import declaration conflicts with local declaration of 'MotorNode'
When I need to do what you are trying to do, I create an externals.d.ts file in which I put module augmentations for my project and make sure that my tsconfig.json includes it in the compilation.
In your case the augmentation might look something like this:
declare module "infamous/motor/Node" {
class Node {
// Whatever you need here...
}
export default Node;
}
I put it in a separate file because a module augmentation like this has to be global (must be outside any module), and a file that contains a a top-level import or export is a module. (See this comment from a TypeScript contributor.)

Categories

Resources