Skip to content
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

Don't allow .ts to appear in an import #9646

Merged
10 commits merged into from
Aug 19, 2016
Merged

Don't allow .ts to appear in an import #9646

10 commits merged into from
Aug 19, 2016

Conversation

ghost
Copy link

@ghost ghost commented Jul 12, 2016

Fixes #9538

I'd like for us to issue an error specific to this issue, because people will be confused if we just output that we can't find ./foo.ts and they see that it's right there.
Unfortunately I'm not sure how to hook up loadModuleFromFile to the error diagnostics system (as opposed to resolution tracing), can anyone help with this?

@ghost ghost force-pushed the no_ts_extension branch from 6df731d to f59b3a5 Compare July 12, 2016 17:01
@vladima
Copy link
Contributor

vladima commented Jul 12, 2016

I would not put error reporting into module resolution but instead report error in program if resolved module ended up to be .ts file

@ghost ghost force-pushed the no_ts_extension branch from adc7aa2 to c6d91f9 Compare July 12, 2016 18:21
@ghost
Copy link
Author

ghost commented Jul 13, 2016

@vladima See c6d91f9

@ghost ghost assigned vladima Jul 14, 2016
@ghost ghost force-pushed the no_ts_extension branch from c6d91f9 to a8c05a9 Compare July 21, 2016 20:51
@@ -1943,6 +1943,10 @@
"category": "Error",
"code": 2689
},
"Module name should not include a '.ts' extension: '{0}'.": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try making this

An import path should not include a '.ts' extension. Consider importing '{0}' instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An import path should not end with a '{0}' extension. Consider importing '{1}' instead.

Since this error is being used for .tsx as well.

return forEach(supportedTypeScriptExtensionsNonDts, extension => fileExtensionIs(fileName, extension));
/** Return ".ts" or ".tsx" if that is the extension. */
export function tryExtractTypeScriptExtensionNonDts(fileName: string): string | undefined {
return find(supportedTypeScriptExtensionsNonDts, extension => fileExtensionIs(fileName, extension));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you want to give the same error if you use .d.ts as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, can you add a test that imports from a file ending in .d.ts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If people add a .d.ts extension they may be doing unnecessary work, but it won't cause runtime errors because declaration references don't translate to imports in the output. In contrast, a .ts extension will either fail to import (because the output file has a .js extension) or ask the JS engine to load typescript code.

Copy link
Member

@DanielRosenwasser DanielRosenwasser Aug 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If people add a .d.ts extension they may be doing unnecessary work, but it won't cause runtime errors because declaration references don't translate to imports in the output.

.d.ts imports don't just get elided. If you use any imported entities as values, then we still emit the import itself. Try it out:

foo.d.ts

export declare var foo;

bar.ts

import * as v from "./foo.d.ts";

v.foo;

The current emit for bar.js is

"use strict";
var v = require("./foo.d.ts");
v.foo;

@ghost
Copy link
Author

ghost commented Aug 3, 2016

The latest commit would mean we no longer allow a package.json "typings" to specify "foo" when the typings are in "foo.d.ts". We have no tests that relied on that behavior, and it doesn't seem to be a style we've recommended, but still, it's a breaking change.

According to the spec at #2338, it looks like it requires that the package.json "typings" not have an extension — LOAD_AS_DIRECTORY simply calls LOAD_AS_FILE, which always adds an extension. The spec has gotten out-of-date, though, as it doesn't include anything about stripping JS extensions (added by #8895).

@ghost ghost assigned sandersn Aug 15, 2016
@@ -109,6 +109,17 @@ namespace ts {
return undefined;
}

/** Works like Array.prototype.find, returning `undefined` if no element satisfying the predicate is found. */
export function tryFind<T>(array: T[], predicate: (element: T, index: number) => boolean): T | undefined {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I expected find to have the type that tryFind has right now. Why does find take callback and not predicate?
I forgot to mention it when I ran into it last week while trying to use find.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we rename tryFind to find, what should we call find? mustFind?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findMap? Let me go see if this function is in hoogle...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the equivalent of bind (>>=) or something like Data.Foldable.concatMap except that it takes Array<T> to Exception<T>. So, yeah, findMap is not bad, or mapFirst or mapSingle.

@sandersn
Copy link
Member

👍

@@ -2713,6 +2713,13 @@ namespace ts {
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
}

/** Return ".ts" or ".tsx" if that is the extension. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

".d.ts"?

@ghost ghost merged commit d2d5d42 into master Aug 19, 2016
@ghost ghost deleted the no_ts_extension branch August 19, 2016 13:49
@rbuckton
Copy link
Member

rbuckton commented Aug 22, 2016

The latest commit would mean we no longer allow a package.json "typings" to specify "foo" when the typings are in "foo.d.ts". We have no tests that relied on that behavior, and it doesn't seem to be a style we've recommended, but still, it's a breaking change.

@andy-ms This change in 359c8b1 breaks vscode extensions as vscode uses an extensionless path for "typings" in the vscode-languageserver, vscode-languageserver-types, vscode-languageclient, and vscode-jsonrpc packages. This could be a problem for anyone depending on specific versions of these packages.

@rbuckton
Copy link
Member

I filed microsoft/vscode-languageserver-node#76 to track this issue for vscode.

This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants