I can't seem to get any import to work when the module isn't defined as a string. What is going on?
test.ts
import b = module('Backbone')
Does not work:
backbone.d.ts
declare module Backbone {
export class Events {
...
Works:
backbone.d.ts
declare module "Backbone" {
export class Events {
...
Edit 1:
FYI From 10.1.4
An AmbientModuleIdentification with a StringLiteral declares an external module. This type of declaration is permitted only in the global module. The StringLiteral must specify a top-level external module name. Relative external module names are not permitted
I don't understand how it's useful to not specify it as the string literal format as found here and here. It works if you use ///<reference... without a string literal module but I'm trying to generate AMD modules that depend on these libraries so I need the import to work. Am I the minority and I have to go and modify each .d.ts to be the string literal version?
Edit 2:
Declaring a module using a string literal requires that your import is an exact match if that string literal. You can no longer use relative or absolute paths to the location of this module/module definition even if it is not located in the same directory as the file trying to import it. This makes it that a ///<reference and an import are required but produces a module with tsc --module AMD that was exactly looking for (path to module is as dictated by the module string literal "Backbone").
For example.
+- dep/
|- backbone.d.ts
|- test.ts
backbone.d.ts:
declare module "Backbone" {
export class Events {
Works: test.ts:
///<reference path="../dep/backbone.d.ts" />
import b = module('Backbone')
// generates
// define(["require", "exports", 'Backbone']
Does not work: test.ts:
import b = module('./dep/Backbone')
Note that this works as well...
declare module "libs/Backbone" {
...
///<reference path="dep/backbone.d.ts" />
import b = module('libs/Backbone')
...
// generates
define(["require", "exports", 'libs/Backbone']
When you write this:
declare module Backbone {
It means you have already a module which is in the global scope (so you can immeadiately use it, no import is required). But when you write this:
declare module "Backbone" {
It means you specify how the imported module (import ... = module("...")) will look.
Related
I have JS/TS code base in my project. Some file looks like:
import Something from '#some-lib/things/something'; // index.jsx file here
const someFunction = () => {
// do something with "Something"
};
In VS Code and tsc result i have error:
Could not find a declaration file for module
'#some-lib/things/something'.
'/Users/user/Projects/project/node_modules/#some-lib/things/something/index.jsx'
implicitly has an 'any' type.
Try npm install ... if it exists or add a new declaration (.d.ts)
file containing declare module '#some-lib/things/something';
I tried to add definitions by creatig file src/#types/#some-lib/index.d.ts with this content:
declare module '#some-lib/things/something' {
const Something: (props: React.SVGProps<SVGSVGElement> & {
size?: number,
color?: string,
inline?: boolean,
className?: string,
}) => React.ReactElement;
export default Icon;
}
But i get this error:
Invalid module name in augmentation.
Module '#some-lib/things/something' resolves to an untyped module at '/Users/user/Projects/project/node_modules/#some-lib/things/something/index.jsx', which cannot be augmented.
Please, help me. How can i declare TypeScript types for JS libraries from npm with subdirectories/submodules ?
I found solution.
If you want to create d.ts for js/jsx files from npm-modules you import like this:
// this is reference to ./node_modules/#some-lib/things/something/index.js
import Something from '#some-lib/things/something'
you need to
Add paths to your tsconfig.json:
{
"compilerOptios": {
// ...
"baseUrl": ".", // just require for "paths"
"paths": {
"#some-lib/*": ["src/types/some-lib"] // 'src/types' is just for example
}
}
}
Create file src/types/#some-lib/things/something.d.ts with content:
declare module '#some-lib/things/something' { // equal to import
const Something = number; // number just for example
export = Something;
}
As far as I understand, your d.ts file path in should be the same as the path from node_modules, except that its root starts at src/types/ in example.
I really hope this will help you, good luck!
Duplicate of
Having error "Module 'name' resolves to an untyped module at..." when writing custom TypeScript definition file
Imports should be declared inside the module declaration.
I am currently confused on when code in a file is actually executed an when it is not. If I have a file1.ts file like the following:
export interface myInterface {}
export function myFunction() {}
export const myConst: {}
// ... and more exports
// top-level non-exported code
if (condition) {
myConst = ...
}
And a file2.ts containing one the following:
import { myInterface } from "./file1.ts"
import * from "./file1.ts"
import * as file1 from "./file1.ts"
import "./file1.ts"
How does the the behaviour differ? When is the top-level code that wasn't exported in file1.ts executed and when is it not executed? Is it executed even when only a specific export is imported (see first variant)?
This is making me crazy right now and I didn't find anything about it on the TypeScript handbook page for modules.
Multiple conditions determine if TypeScript module gets included in final, transpiled JavaScript files, or not:
Kind of usage of imported variables in the your own code.
Type of imported variables (class, interface, etc).
Since TypeScript 2.8 compiler settings importsNotUsedAsValues to control the behavior.
Since TypeScript 2.8 there is also new syntax import type and export type for modules that are explicitly excluded from final, compiled JavaScript files.
Check following section in the TypeScript 2.8 release notes for more details:
Type-Only Imports and Export
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.)
Is it ok in TypeScript to mix these too 'include' types?
import { SomeType, someFunc } from "./MyThings";
And:
import events = require('events');
The first would be a TypeScript module with an export or two... and the second is just a node module called events (I guess this could be anything pulled in from NPM too).
Am I ok to mix these two conventions in a single TypeScript file?
Yes, this is acceptable in TypeScript.
When using the import foo = require('foo');, you must have a module 'foo' declared with declare module 'foo', typically in a .d.ts file.
This is typically covered in node.d.ts.
I want to switch from JavaScript to TypeScript to help with code management as our project gets larger. We utilize, however, lots of libraries as amd Modules, which we do not want to convert to TypeScript.
We still want to import them into TypeScript files, but we also do not want to generate definition files. How can we achieve that?
e.g. The new Typescript file:
/// <reference path="../../../../definetelyTyped/jquery.d.ts" />
/// <reference path="../../../../definetelyTyped/require.d.ts" />
import $ = require('jquery');
import alert = require('lib/errorInfoHandler');
Here, lib/errorInfoHandler is an amd module included in a huge JavaScript library that we do not want to touch.
Using the above code produces the following errors:
Unable to resolve external module ''lib/errorInfoHandler''
Module cannot be aliased to a non-module type.
This should actually produce the following code:
define(["require", "exports", "jquery", "lib/errorInfoHandler"], function(require, exports, $, alert) {
...
}
Is there a way to import a JavaScript library into TypeScript as an amd Module and use it inside the TypeScript file without making a definition file?
A combination of the 2 answers given here worked for me.
//errorInfoHandler.d.ts
declare module "lib/errorInfoHandler" {
var noTypeInfoYet: any; // any var name here really
export = noTypeInfoYet;
}
I'm still new to TypeScript but it looks as if this is just a way to tell TypeScript to leave off by exporting a dummy variable with no type information on it.
EDIT
It has been noted in the comments for this answer that you can achieve the same result by simply declaring:
//errorInfoHandler.d.ts
declare module "*";
See the github comment here.
Either create your own definition file with following content:
declare module "lib/errorInfoHandler" {}
And reference this file where you want to use the import.
Or add the following line to the top of your file:
/// <amd-dependency path="lib/errorInfoHandler">
Note: I do not know if the latter still works, it's how I initially worked with missing AMD dependencies. Please also note that with this approach you will not have IntelliSense for that file.
Create a file in lib called errorInfoHandler.d.ts. There, write:
var noTypeInfoYet: any; // any var name here really
export = noTypeInfoYet;
Now the alert import will succeed and be of type any.
Typically if you just want to need a temporary-faster-solution, that could be done by defining a new index.d.ts in the root of the project folder, then make a module name like described inside package.json file
for example
// somefile.ts
import Foo from '#awesome/my-module'
// index.d.ts on #awesome/my-module
declare module '#awesome/my-module' {
const bind: any;
export default bind;
}
Ran into that that problem in 2020, and found an easy solution:
Create a decs.d.ts file in the root of your TS project.
Place this declaration:
declare module 'lib/errorInfoHandler';
This eliminates the error in my case. I'm using TypeScript 3.9.7