Adding declarations file manually (TypeScript) - javascript

I didn't find a declaration file for 'google-spreadsheet' so I'm trying to create one by myself:
in typings -> modules, I've added a new folder named "google-spreadsheet", and there I've added a new file named "index.d.ts" which has the following content:
export class GoogleSpreadsheet {
}
In the client file I have this:
import * as GoogleSpreadsheet from 'google-spreadsheet';
But 'google-spreadsheet' is marked with red, saying:
TS2307 Cannot find module 'google-spreadsheet'.
BTW I've NPM-installed 'google-spreadsheet' and it works JavaScriptly. Only the TypeScript bothers me here.
Any ideas how to solve that?

If you dont need to care about the typings inside this module you can only create a *.d.ts file and put the following content (e.g. create a typings.d.ts):
declare module 'google-spreadsheet';
To define the types inside the module you can change the above code to:
declare module 'google-spreadsheet' {
// define the types...
}

From the root of your project:
mkdir -p src/#types/google-spreadsheet - create a folder for your module's type declarations.
echo "declare module 'google-spreadsheet';" > src/#types/google-spreadsheet/index.d.ts
Also, ensure your tsconfig is configured to include the #types folders using the typeRoots option.
{
"compilerOptions": {
"typeRoots": ["src/#types", "node_modules/#types"]
}
}
Also, you might want to take a look at the documentation on declaration files.

I´ve ran into this problem while developing PowerBI custom visuals with echarts.
Just creating the .d.ts file didnt helped. I had to make an include statement inside the tsconfig.json which pointed to the root (where my .d.ts file is located with the declare mdoule statement)
externals.d.ts ->
declare module 'XXX/XXX'
tsconfig.json ->
"include": ["./"]

Related

How to include a global file type declaration in a TypeScript (Node.js) package

I'm working on a package that I am planning to publish publicly on npmjs. Let's call it the "text package".
I would like that by default when installing that package, you can import .txt files directly and get the correct type (out of the box), like this:
import text from './file.txt'
The text variable would be of type string because the package would have defined its type, using something like this (in a global.d.ts):
declare module '*.txt' {
export const text: string;
export default text;
}
If I include that global.d.ts in my package, and that I import something from this package, then I will automatically get the correct type when importing a .txt file.
But the problem is sometimes I would just need to import a .txt file without importing anything from the "text package", which is why I was wondering if there is some sort of way, as you install a package to install a global type that does not require to import anything else for the type to apply.
In other words, as soon as you install my "txt package" the declare module '*.txt' would apply to my entire project out of the box.
Is there even a way to do this, or whoever installs my package would have to declare their own global type (e.g., declarations.d.ts) to be able to import .txt files globally?
I know that even if the import type works, it will still require Webpack or another bundler to really work but this question is just about the type.
The short answer is:
TypeScript does not support Global types without importing the file referring to the type.
More details:
One example that I found doing this was Next.js - when creating a TypeScript app using npx create-next-app#latest --typescript you can start importing *.css files (for example) and get the correct type.
Where I got confused is that I originally thought that the type was coming from the next-env.d.ts but even when I deleted the file, *.css import was still working in Visual Studio code. But the reason it was, is because a file in the pages directory were importing Next.js' index.d.ts file.
Basically, in Visual Studio Code, as soon as your import a type somewhere in your project, if it's global, it will be accessible everywhere.
Workaround
So what can be done with the current TypeScript capabilities? To support new file types, you will need a file loader such as Webpack. The logical thing to do would be to add a reference to the file type declaration in the file loader itself. This way, as soon as you configure your file loader to be able to import the file, you will inherit the type:
create a txt.d.ts in our package's source directory (e.g. src) - you can use any name for the file, it's not important
if you are using eslint, add an entry to ignore the type file (e.g. 'src/*.d.ts' in your ignorePatterns option
Since you are adding a d.ts file in your source that is not managed by tsc, you need to add a script that will perform the following actions:
Copy txt.d.ts in the target directory of the compiled files for your package
Add this line at the top of your package's file loader (e.g. loader/index.d.ts: /// <reference types="../txt" />\r\n - this will link the declaration file back into your package. Note that you can add this reference to any file of your package.
This workaround will only work once you import the file referencing back to the declaration - this is the only way TypeScript can be made aware that this type exists (see https://github.com/microsoft/TypeScript/issues/49124).
Another alternative could also be to add manual steps (in a readme file) to add a global type declaration file.
to bundle global types, do the following. form typescript
specify default typings directory at typeRoots. .e.g "typeRoots": ["./src/types"].
create a file /src/types/global.d.ts in the specified directory
declare your types in the file inside declare global {} and make sure to have export {} if you don't already export anything.

How to configure Webpack to build without importing an external module?

I Have a third-party library needed to be used in project ts code, which is added to the application using a CDN path in the HTML. And this library is exporting a window variable, which is used in the code.
The package is not available as an npm module. While running the webpack build it's failing with the following error message:
error TS2304: Cannot find name 'CUSTOM_WINDOW_VARIABLE'.
I have added this in name in the webpackconfig.js file as :
externals: {
CUSTOM_WINDOW_VARIABLE: "CUSTOM_WINDOW_VARIABLE",
},
But still getting the same error.
How to tell webpack to ignore these global variables while building. Or convert them to window.CUSTOM_WINDOW_VARIABLE from CUSTOM_WINDOW_VARIABLE.
As I know your problem is not about webpack at all. The issue is most likely throwing from ts-loader which uses tsc compiler your tsx? files so in order to fix this issue you might need to define the type for your global value which is available on window as following steps:
Create your project typing dir and the file types/global.d.ts (you can name whatever you want, feel free to use my suggested name in terms of no idea how to name it) with following content:
// global.d.ts
// You can define your own type by replacing with the exact type
declare const CUSTOM_WINDOW_VARIABLE: any;
Make sure your tsconfig.json which is placed at repo's root dir in most cases includes your types dir by adding to include config option:
// tsconfig.json
{
"include": ["types", ...]
}
Hopefully it would work for your case
PS: If you don't import your library as externals, basically you don't have to configure the externals property in your webpack.config file

Error: "Could not find a declaration file for module 'react-search-input'"

I am trying install react-input-search. I have error:
Could not find a declaration file for module 'react-search-input'. '.../app/node_modules/react-search-input/lib/index.js' implicitly has an 'any' type.
Try npm install #types/react-search-input if it exists or add a new declaration (.d.ts) file containing declare module 'react-search-input';ts(7016)
Typescript should go with Typescript NPM package, the Typescript NPM package had prefix #types/ on it name.
The NPM package react-search-input do not had Typescript package for it yet, then you can simple fix by following
Create file with name globals.d.ts and put on your source root of Typescript watcher folder
Put declare module 'react-search-input' on that file
And it should working fine
This is a common error that you can simply solve by creating an index.d.ts file and then add a declaration line like this:
declare module 'react-input-search';
You can save this file anywhere you wish but make sure to add the filepath to tsconfig.json like this "typeRoots": [
"types/index.d.ts"
],
This is assuming you saved it in types/index.d.ts
It's a typescript error. It means that there is no type declarations in 'react-input-search' library. There is no package 'react-input-search' with types for it, so you need to declare usage of these library in your project by creating a file with extension .d.ts (for example libraries.d.ts) and insert a line declare module 'react-search-input'; into it.
You can always create the type definition library for this library react-search-input and put it on definitelytyped so now everyone including you can use it.
Here is a guide with examples on how to create a type definition library.

What is the best approach for handling modules that don't have a type definition file?

I'm using a module called three-orbit-controls in my typescript/react project. This module does not have a #types package so as I understand I will need to write a type definition file. I'm confused as to the best way to approach this. Ideally I would like to have a file called index.d.ts that defines this module that I can add to as I use more features of the library. I have added this file to my project however the typescript compiler claims that it can't find the module. Here is my index.d.ts file that is in the root of my project
declare module 'three-orbit-controls' {
export default class OrbitControls {}
}
I'm trying to include this module in the following way
import OrbitControls from 'three-oribit-controls';
However when I do this the typescript compiler claims it can't find the module. Is there something basic I'm missing? I even tried to include the type def file in my code by adding
/// <reference path="../index.d.ts" />
However this does not work and it would seem strage that I would have this line to each file that I require three-orbit-controls. Why does typescript think the module is not defined? What is the best way to define a module in a .d.ts file? Is there a way to have a .d.ts file that my entire project can see with out importing a .d.ts file everywhere?

How to require an external js library in Node.js with a typescript declaration file

I have a Node.js project written in Typescript and I am trying to get it to work with mime.js (https://github.com/broofa/node-mime). I have a declaration file (https://github.com/borisyankov/DefinitelyTyped/blob/master/mime/mime.d.ts) but cannot get node.js in typescript to work nicely with it.
I have the following:
/// <reference path="../../libs/mime.d.ts" />
import mime = require( 'mime' );
This keeps the type script compiler happy and all is good until I try to run it in Node.
When I try to run it I get
Cannot find module 'mime'
However, if I edit the generated javascript to the following:
import mime = require( '../../libs/mime' );
It all works fine. If I change the typescript file to have the require with the relative path I get a compiler error:
Cannot find external module '../../libs/mime'
How do I refer Typescript to both the mime.d.ts file and to the mime.js file so that both the compiler and Node are happy.
Many Thanks
TypeScript supports relative paths only for TypeScript modules. Ambient JavaScript modules should be placed in node_modules folder. From Node.js doc:
If the module identifier passed to require() is not a native module, and does not begin with '/', '../', or './', then node starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location.
Workaround 1
Place .d.ts next to .js module and change it from:
declare module "mime" {
...
}
to:
declare module Mime {
...
}
export = Mime;
Workaround 2
Rewrite .d.ts files from:
declare module "mime" {
export function lookup(path: string): string;
...
}
to:
declare interface IMime {
function lookup(path: string): string;
...
}
And then use plain var instead of import:
var mime = <IMime>require( '../../libs/mime' );
Try the following: in the root of the project 'npm install mime'. It will create the node_modules directory with mime inside of it. You can import it by 'require('mime')'. You also have to 'reference' the .d.ts file but that's the minor thing, with the npm package node will be able to import the actual javascript lib.
I also recommend using TSD ('npm install tsd -g') for getting the .d.ts files from DefinitelyTyped.
Btw sry for typos, I'm writing from mobile.
you need:
Add definitions file(*.d.ts) of the library
You must understand, the definition file contains only the interfaces of the library. You should be add the library source code separately.
References:
The typescript definitions:
https://github.com/borisyankov/DefinitelyTyped
The definitions for mime:
https://github.com/borisyankov/DefinitelyTyped/blob/master/mime/mime.d.ts
I've found a better way of doing this that works with node_modules folders and typings folder. A working example can be seen here:
https://github.com/Roaders/contact-list-checker/tree/external-js-module-example
In this app I import the csv js library in the ContactList class:
import csv = require('csv');
This is after installing it:
npm install csv
as the csv lib is in the node_modules folder we do not need to specify and path to the lib and just csv is sufficient for the compiler to find it. Without a d.ts declaration file we get errors though. This declaration file could be located in the typings folder and come directly from tsd but this lib is not found on tsd so I had to create my own. csv.d.ts is in libs/csv:
declare module "csv" {}
(I will add function interfaces to this later)
the module name HAS to match the import name. The filename can be anything.
You can add a reference to this file in the file that's doing the import:
///<reference path="../../../libs/csv/csv.d.ts" />
or as I have done you can just add a reference to it in the tsconfig.json in the root of the project:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"diagnostics": true
},
"files": [
"./app.ts",
"./typings/tsd.d.ts",
"./libs/libs.d.ts"
]
}
(where libs.d.ts has a reference to csv.d.ts)
This method allows you to install js libs using npm install and use declarations from tsd.

Categories

Resources