-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Importing files other than TS modules #2709
Comments
if you can use absolute path you can do this today by doing something like: // Define a module declare module "template.html!text" {
var html: number;
export default x;
} then your code would look like
|
It would be nice to not have to create manual declarations for every javascript module I want to import. I would think this keeps to the spirit of "Typescript is a superset of Javascript". For example, I have an ES6 foo.js file sitting next to my bar.ts file. I'd love to just be able to: import * as foo from 'foo.js' and then have |
The problem is not the import, the problem is the type of your import (the type of import * as foo: IFoo from "foo"; Which would tell the compiler that you know shape of the module, and optionally you can pass |
I actually tried something like that just as guess when I was playing around with it :) The issue I think I'd still have is that I couldn't just take a bunch of es6 javascript files and one by one convert them to typescript without breaking everything. I love the fact that I used to be able to take a I wonder if there could be a compiler flag like the |
Using TypeScript 1.5-beta, transpiling to ES6.
The above code complains:
However, the following JavaScript is generated:
As far as static type checking goes, Foo is considered to be "any" so you can also call it as a function, use it in arithmatic, etc. Interestingly, when building with gulp-typescript I don't get the error but atom-typescript does give me the error. I'm guessing there is a compiler option that controls this, but I am not sure what it is (which is why I am here). |
@Zoltu please see my comment in #3019 (comment) to answer your question..
TypeScript errors do not block emit. it tells you the compiler did not understand some aspects of your code, but syntactic transformations still take place.
You need to tell the compiler the shape of the thing you are importing. currently the only way to do that is to write a .d.ts file e.g.: declare module "foo" {
export class Foo{ }
} |
I'm coming to this as a newcomer, having only recently started playing with TypeScript as part of the Angular 2 developer preview. I presume there's going to be plenty more people who follow a similar path, so let me capture my impressions: I appreciate the value of typing, but it's not my primary motivation for using TypeScript. I'm more interested in decorators and the fact that its the recommended language for Angular 2. My expectation was that typing would be an optional addition that I could gradually apply, but not that I'd have to immediately find or create type definitions for all my code and its dependencies. Whatever the reason, throwing errors on valid JavaScript code is confusing when TypeScript is explicitly described as a superset of JavaScript. The first thing many people will do is load up an existing app and try to compile it. Getting a bunch of errors in response doesn't give a great first impression. That "Cannot find external module" error is really bad. At first I thought it meant the compiler couldn't find the file on disk, so I spent quite a while moving it around and trying to figure out what was wrong. I also thought that it meant the compiler hadn't output anything. Compiler errors that don't prevent compilation are rather odd. Shouldn't these be warnings, or at least the compiler should make it clear that they haven't prevented code emission? I have a large, existing Angular 1 application, organised into a few hundred ES6 modules. Eventually I want to migrate it Angular 2, and thus probably TypeScript, but this is going to have to be a gradual process. Having the compiler throw hundreds of errors because my code lacks types isn't going to make this much fun. |
@jonrimmer This is good feedback. Would be curious to here what your preferred workflow would've been. As far as the module errors go, I totally agree they're pretty bad and very painful to debug. As for the superset/errors part, what behavior would you prefer? Keep in mind the errors you're seeing are more like warnings in most languages, they can be ignored and JS is still emitted (were you using VS or some other editor?). Then you can fix up those errors over time. Some of them are to satisfy the compiler, some might be actual bugs in your code. The hope is that you can grab an existing .d.ts from DefinitelyTyped for much of your library code and fix any errors related to common code. We also have some ideas for ways to ease this process further (ex #2916). If we didn't give those errors (ex some compiler flag like --noTypeErrors) then what would really be the point in starting to write with TypeScript? It'd be identical to your JavaScript except with an additional compile step in your workflow. Eventually you'd have to turn off the --noTypeErrors flag and be back in this state with many errors due to lack of type information. If you only got errors on the code you explicitly annotated then you'd actually have to write way more type annotations than necessary to get the type checking we advertise as powerful and useful. |
@danquirk I am using Visual Studio Code. I can live with the current behaviour, but I wish the compiler's messaging was clearer. Something like "Warning: No registered type information for external module foo — using implicit 'any' type." If you have to keep calling them errors, some message making it clear that code is still being emitted would be helpful. @mhegazy's suggestion of being able to add an explicit type, even if it's As for using TypeScript with untyped code, I actually get a lot. First, I get all the other ES6 and ES7 features you guys have implemented. In particular, I get to use Angular 2's annotations, which require decorator support. If you compare the TS vs ES5 examples in the Angular 2 documentation you can see that the ES5 equivalent code isn't nice, whereas the TS version is pretty awesome. That alone would be enough to make me use TS for my Angular 2 code, regardless of typing. Also, even if my existing codebase and some of its dependencies aren't typed, by using TS for compilation, I can write all my new code with types, and gradually add them to the old code. I can also consume the core Angular 2 libraries in their original TS form, and get intellisense and checking on my use of them, at least. Finally, I think maybe there's a question of project philosophy to consider here. It seems like until recently TypeScript existed in a niche where it existed to provide JavaScript + Types to people who wanted them, and could afford to be somewhat uncompromising in how it applied that vision. But its recent enhancements have turned it into more of a general ES.next compiler along the lines of Babel, and maybe that requires a reconsideration of how hard it pushes typing, vs. making interop with untyped code as painless as possible. I'm optimistic that types will make it into JS proper eventually. But with the best will in the world, there is going to be more untyped JS code around than not for a long time to come. |
But what do you expect to happen with your untyped code? Do you want some way to turn off all type checking for a file? I get that the migration initially involves a lot of type errors but what do you envision instead? Even with file level settings as soon as you want to add type annotations to one function in that file you need to deal with the many errors from that file. The entire purpose of emitting in the face of these type errors is to acknowledge how much untyped code is out there. Then the migration process to TypeScript can happen piecemeal without having broken your entire application until you've dealt with every single type error. TypeScript is definitely aiming to add value in the form of ES6/7/etc features before they're in every browser/engine. But the fundamental point of the project is types (hence the name :)). There have always been type-less transpilers and will continue to be. What parts of the migration process are particularly painful to you with the .d.ts on DefinitelyTyped and if #2916 existed to easily get .d.ts for your JSDoc'd code? (I assume a bunch of code without JSDocs would be one). |
I seem to recall at one of Anders talks at Build 2015, he again referenced how any valid javascript file was a valid typescript file. I'd vote for, again, having a compiler switch similar to allowing implicit anys. If typescript can find a type for a module import, use it, else use "any". If people want to be strict, they can set it appropriately. For cases where you are starting new with Typescript, you can set the flag to strict, and then for external, untyped modules, use some sort of language construct (see @mhegazy idea above) to explicitly set the import type to "any". For existing code bases, you can set the compiler to allow implicit any imports. I really love Typescript, it's a wonderful, powerful tool. I think it's adoption has been so high in part because it's so flexible (both in the optional typing and it's cross platform behavior). It plays nice with the existing Javascript ecosystem. The current module implementation unfortunately does not. |
Is Mohamed's suggestion of
enough to satisfy all the use cases here? Basically the logic would be that if we see a type annotation ( |
It would work for my current cases, where I'm starting with a Typescript code base and want to import a js library without any type defs. Partial conversion of an |
Howdy, Dealing with a large existing untyped codebase and porting it to TypeScript is something that does and will happen frequently, I agree with the sentiments @dfaivre in this respect - there should be an 'implicitly any' flag for the compiler. The idea of typing I think typescript should make the transition easy and make saying "now I care about the types of this module" simple - so I don't have to edit existing typescript code to make it all care - I can do it through one (or two) actions:
To achieve this I think these things need to happen:
Two sides to the same story of course - but I think you can cater for both camps:
In terms of what to do when partially migrating source to TypeScript, those partially typed modules may now throw errors - but that's a good thing - by partially typing you're indicating that you do now care about the type of the module. |
This is good feedback on migration pain. I would just note that of your 3 suggestions there 2 are actually in place, just somewhat poorly communicated. Our errors are actually more like warnings in the sense that they will not block a build/emit phase. So while your migrated JavaScript may have errors reported by the TypeScript compiler (including module type resolution ones) you should still be getting emit that makes sense for the most part (syntax errors are another story). |
+1 for That would support importing html strings and json objects, e.g. |
One serious issue with treating untyped modules as errors is that it can fail the build process in Visual Studio and MSBuild in general. I have had to explicitly disable the "No emit on error" checkbox for a lot of projects; I feel it would be much better if untyped modules were raher shown as warnings. It also fails browserify, e.g. this code in
when compiled with this command:
will fail with the error:
On another note, if it was possible to explicitly ignore specific TS**** errors, that would be an acceptable workaround, e.g. something like this in
|
if you are using declare module "npm-package\*"; // any module import with this prefix is considered `any`. |
@mhegazy That's better but you still have to Why can't just TypeScript do |
if you want to disable all module checking, use |
@mhegazy I don't want to disable all module type checking. I have npm packages that include their own d.ts file, I also use typings for other d.ts files and then, there are some packages for which d.ts files do not exist anywhere. But according to what I've been reading, this is not possible and it won't be possible either in 2.0. A |
if a declaration file is found the compiler uses it. if not, it issues an error for unknown module. if i understand correctly you do not want to see this error. |
If I have only installed typings for EDIT: Actually I can confirm that this is working just as intended, after setting |
@geirsagberg:
What else is needed ? please |
isn't
dangerous as you won't get any real errors either on missing modules? I am still having an issue with this (Sep 2016) I am using systemjs with the text plugin and angular2, so I am importing templates as:
everything works great
any way to quiet the error down? |
declare module '*!text' {
var _: string;
export default _;
} |
thanks sooooo much! |
Is there anything special I have to do to reference the .d.ts file so that my imports work? I can't seem to get the solutions listed here to work. // webpack.d.ts
import {IUseableStyle} from './common/IUseableStyle';
declare module '*.html' {
var _: string;
export default _;
}
declare module '*.scss' {
var _: IUseableStyle;
export default _;
} // component.ts
import template from './component.html'; // [ts] cannot find module './component.html'; tsconfig.json looks like:
|
Your .d.ts is a module (i.e. it has a top level declare module '*.html' {
var _: string;
export default _;
}
declare module '*.scss' {
import {IUseableStyle} from './common/IUseableStyle';
var _: IUseableStyle;
export default _;
} |
Wildcard is not working for me , maybe it's due to I use typescript 1.8. declare module '*.html' {
var _: string;
export default _;
} The following works fine: import "text!Components/Templates/MyTemplate.html";
...
var template = require('text!Components/Templates/MyTemplate.html'); |
@bomzj Wildcard only works in TS 2.0 or higher. |
EDIT: never mind. It seems that the README for the svg-inline-loader plugin is wrong. You need to use // webpack.config.js
config.module.loaders.push({
test: /\.svg$/,
loader: 'svg-inline-loader'
}); I've tried to follow through this issue but I'm a bit lost and would appreciate some help. I'm trying to load a SVG file into my .ts file, so I can use it in my HTML template (Angular 2) as an inline SVG. This allows me to change the colour of the SVG with CSS. I'm using web pack 1.x. This is what I've tried: // webpack.config.js
config.module.loaders.push({
test: /\.svg$/,
loader: 'svg-inline'. // Installed locally with `npm install svg-inline-loader`
}); // declarations.d.ts
declare function require(string): any;
declare module "*.svg" {
const content: any;
export default content;
} // Tried both this:
import damSvg from '../../../assets/icon/barrier-types/dam.svg';
// And this:
const damSvg = require('../../../assets/icon/barrier-types/dam.svg'); In both cases, I get a webpack 'Cannot find module' error. Can anybody shed any light on what I'm doing wrong? |
You either have the wrong path or you haven't listed .svg as a resolvable extension. resolve: ['.svg', '.ts'] Your question would probably be better asked on stack overflow. it also has nothing to do with TypeScript , being about Webpack loading neither TypeScript nor JavaScript files |
@aluanhaddad thank you for taking the time to respond. It ended up being an error with the loader I was using. I've updated my post above. |
I didn't realize your issue was resolved (but I'm glad to hear it). I guess I'm used to seeing edits in bold. |
Is there a way to import a file, raw as is, as a string, using Typescript purely? I dont want to involve SystemJS, webpack or rollup to solve this problem. |
TypeScript does not provide run-time functionality. If emitted TypeScript runs under NodeJS this functionality is already there. There are other libraries that provide similar functionality in the browser. |
@avindra I have written in typing.d.ts
in TS file
@kitsonk could you suggest library which can be used to import non-code module in typescript. |
Nothing worked for me, until I've changed my import to the This works with TS 2.4.1:
Then:
And the relevant parts of webpack config:
|
I tried this: declare module "mirage-server"
import MirageServer, { Factory } from 'mirage-server'; but get: error TS2665: Invalid module name in augmentation. Module 'mirage-server' resolves to an untyped module at '/Users/nikos/WebstormProjects/client/node_modules/mirage-server/lib/index.js', which cannot be augmented. |
@quantuminformation You can't put the |
I've successfully been using SystemJS and TypeScript for a while now. I've been about to use the CommonJS syntax to easily import other TS modules, as well as other resources:
This is made possible by simply declaring the following function:
I'm now trying to do the same with the new ES6 syntax:
Of course I can do the same as before and declare and use 'require', but it'd be nice to keep it consistent. Perhaps assume that if an exclamation mark is in the path, then don't assume it's a TypeScript import?
The text was updated successfully, but these errors were encountered: