Override typescript module exports definition - javascript

I have installed plugin that ship with types definition.
declare module 'autobind-decorator' {
const autobind: ClassDecorator & MethodDecorator;
export default autobind;
}
But, I thought that type definition was wrong. I need to change to this
declare module 'autobind-decorator' {
const autobind: ClassDecorator & MethodDecorator;
export = autobind;
}
How can I do that?

How can I do that
Fork the project and publish (till the original gets fixed).
More
This is essentially if an author publishes a bad JS lib how do I fix it. You would fix it by forking. TypeScript doesn't offer much magic here.
Reason
If TypeScript offered a way to override it, it would lead to only confusion which definition is used.

Related

How do I use TypeScript typing information from a Node.js package?

I've read a ton of different variations of this same question, but I just can't wrap my mind around it. I'm using the websocket module (which I've used many times before without TypeScript) and I can't figure out how to type my variables?
I have a function that takes in a WebSocketConnection object, but when I give it the type WebSocketConnection I get a "Cannot find name 'WebSocketConnection'" from TypeScript.
I've installed the #types/websocket package and I can see the index.d.ts file with all the type definitions in it located in ./node_modules/#types/websocket/index.d.ts relative to my tsconfig.json file...
I've tried adding the "typeRoots" option to the tsconfig.json file, as well as "types". I've tried many combination of values but as far as I can tell leaving them off entirely is a better bet, so I've tried that as well. I've also tried many variations of importing data from both the .d.ts file and also the package itself, with no luck of course.
I tried using /// <reference path="node_modules/#types/websocket/index.d.ts" /> also with no luck.
I looked in the .d.ts file and found a very clear declaration of an interface called IStringified that looked like this:
export interface IStringified {
toString: (...args: any[]) => string;
}
So I tried to access IStringified and I'm still getting the same "Cannot find name 'IStringified'" error.
I'm probably just being really dumb and missing something plainly obvious, but any pointers or advice would be much appreciated! What in the world am I doing wrong?
Types of installed packages are not available globally. They must be imported into each file in order to use them. Don't mess with typeroots or triple slash directives at all, that will only make things worse.
In this particular case, the module exports a connection class, which is probably what you want. It's unfortunate name means to make it it look the class constructor that it really is you should probably rename in on import:
import {
server as WebSocketServer,
connection as WebSocketConnection,
} from 'websocket'
And now you can do:
const wsServer = new WebSocketServer({ httpServer: server });
wsServer.on('request', function(request) {
var connection = request.accept('echo-protocol', request.origin);
doSomethingWithWsConnection(connection) // works
});
function doSomethingWithWsConnection(connection: WebSocketConnection) {
//...
}
Typesafe example on TS playground
So I tried to access IStringified and I'm still getting the same "Cannot find name 'IStringified'" error.
You import the type, then use the type:
import { IStringified } from 'websocket'
const foo: IStringified = { toString: () => 'asdf' }
Playground

New eslint errors with the #typescript-eslint/no-unsafe-* rules

I'm having some trouble with adding them into some existing projects. For example, I have a class in a module that I developed:
export default class ClassName {
// Class members
}
Now I import that into another project:
import ClassName from 'modulename';
const object = new ClassName();
I get 2 errors on this line.
On the object in const object:
error Unsafe assignment of an any value #typescript-eslint/no-unsafe-assignment
On the new in new ClassName:
error Unsafe construction of an any type value #typescript-eslint/no-unsafe-call
How can I avoid these errors?! I would really like to be able to follow these rules because I think they'd be so useful!
Thanks.
Here's another example:
import { readJsonSync } from 'fs-extra';
const testEnv = readJsonSync(testEnvPath);
Here I get the no-unsafe-assignment error on the testEnv of const testEnv, and the no-unsafe-call error on the readJsonSync call on the second line.
I can get rid of the first one with this code:
interface ITestEnv {
// interface members
}
const testEnv: ITestEnv = readJsonSync(testEnvPath) as ITestEnv;
however, I still can't figure out how to get rid of the second one on the readJsonSync call.
ESlint can not resolve the absolute import of your module,
which makes it to infer your class type as any.
Make sure baseUrl and paths in tsconfig.json file used by ESlint are defined correctly.
#see Typescript – Module Resolution
In the first case, you have just one error coming from the constructor, which is cascading to the const assignment. Something in your class implementation is making the type-inference to be inferred as any.
Not saying your code is incorrect. It might be, but there's an (open issue on Github) reporting a constructor as being incorrectly flagged by the same rule.
On your second issue, have you added #type/fs-extra as a project dependency? Many npm packages do not have types themselves. Types are created by someone and added to the #types library. When that's the case, the #types/package_name must be added as a dependency separately.

Accessing Window Object from .tsx file

Typically in my .ts files I can access the window object by calling something such as:
(<any>window).myObject
I am getting compilation errors for this in my .tsx files. Is there any way I can access it from a .tsx file?
Thanks.
You can use the as syntax for type assertion. This is the alternate syntax for type assertion as <type>obj conflicts with JSX syntax:
(window as any).myObject
The above will work, however if you want strong typing consider augmenting the Window interface to add your property so you will get compile-time type checking:
declare global {
interface Window {
myObject: YourObjectType;
}
}
The syntax <type> is being deprecated by the ts team. This is because there is too much ambiguity between it and the new jsx syntax. Instead the ts team introduced the as operator for type assertions.
So this syntax:
(window as any).things
is more update to date.
This change was done, because basically, its very tough to tell a compiler when is such a syntax relating to a type or a jsx-element. Likewise the notation becomes much harder to read (see below for example):
<Component>
{<String>something}
</Component>
Some more detail can be found here https://basarat.gitbooks.io/typescript/docs/types/type-assertion.html#as-foo-vs-foo and here https://github.com/Microsoft/TypeScript/issues/296
Further Explanation on #Saravana Answer,
best way is to have this defined in your types folder, and add a definition file with .d.ts extention, i.e: window.d.ts and place your extended definitions for the window object, as typescript global augmentation typically offers merging interfaces.
declare global {
interface Window {
myObject: YourObjectType;
}
}
// but make sure to export that as default so Typescript will consider it automatically on the project
export default global;

Is it necessary to have typing/definiton files for every JS library you use in typescript?

Is it necessary to have typing for every JS library you use in typescript?
if not, then how to get rid of errors and make use of a library which doesn't have available definition files
import { NotificationContainer, NotificationManager } from 'react-notifications';
can't find typings for react-notifications
It's not necessary. For your example, you create a file react-notifications.d.ts (you can call it anything you like as long as the extension is .d.ts but it makes sense to name it consistently):
declare module "react-notifications" {
const NotificationContainer: any;
const NotificationManager: any;
}
That's a near-minimal starting point. But you could go a little further and improve on those any declarations. They are a temporary cop-out.
An alternative to #Daniel Earwicker answer, as long as you are in a commonJS environment (and I guess you are using webpack) is to simply require the library using node require
const rn = require('react-notifications')
then use rn.NotificationContainer directly or import NotificationContainer = rn.NotificationContainer

TypeScript - Attach module/namespaces to window

I've built a lot of APIs and applications using ES2015, but I am not used to the best practices in TypeScript yet, so maybe you can help me.
Let's say I am building an API/SDK for a shop. The goal is that the user includes my js file and accesses the shop and its namespaces via the window object, much like it is possible with angular and other libs as well.
window.shop.init();
window.shop.cart.get();
window.shop.cart.set();
window.shop.cart.clear();
In ECMAScript 2015, I would write my methods like get and set, import them in my main file and extend the shop object and finally the global object.
// in my cart.js namespace file
export {get} from './get';
// in my shop.js
import * as cart from './cart';
global.shop = {
cart
}
Being a good approach for namespacing in ES2015, it feels kinda wrong in TypeScript having all those module and namespace keywords.
I basically want to achieve the same in TS. I tried things like the following, but with no success.
module shop {
export const cart = {...}
}
(<any>window).shop = shop;
or
namespace shop {
// ...
}
(<any>window).shop = shop;
There where some tutorials claiming that a module is automatically attached to the global/window object, but that did not happen for me.
I am using TypeScript 1.8.10. Any help is greatly appreciated!
There where some tutorials claiming that a module is automatically attached to the global/window object, but that did not happen for me.
Maybe because the code of your namespace is in an (ES6) module instead of in a script? The differences between scripts and modules are detailed here.
The code below makes a global variable shop in the browser if it is loaded as a script, ie with a tag <script src="shop.js"> (or you can concatenate this file with other JavaScript files, for example with uglifyjs).
// File shop.ts
namespace shop {
export const cart = { /* ... */ }
}
If your code is loaded as an ES6 module (ie with the help of Webpack, SystemJS, RequireJS or other), your solution is valid:
(<any>window).shop = shop;
The answer by #paleo is not perfect.
It just suppress the type inference for shop.
I also encounter the similar problem this morning. I tried so many "solutions" on SO, but none of them produce no type error absolutely and enable triggering type jumping in IDE(webstorm or vscode).
Finally, from here
https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512
, I find a reasonable solution to attach typings for global variable which acts as interface/class and namespace both.
Example is below:
// typings.d.ts
declare interface Window {
shop?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
Now, the code above merges the typings of namespace MyNamespace and interface MyNamespace into the global variable shop(the property of window).

Categories

Resources