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

Proposal: Easier Migration with Types in JavaScript Files #23906

Open
DanielRosenwasser opened this issue May 4, 2018 · 4 comments
Open

Proposal: Easier Migration with Types in JavaScript Files #23906

DanielRosenwasser opened this issue May 4, 2018 · 4 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented May 4, 2018

This issue is the dual of #22665.

Background

In last week's design meeting, we discussed #22665 and it seemed like we had some positive sentiment around the proposal. Specifically, issues where users hit an expressivity wall or mismatch in .js when migrating to .ts files provide a compelling case.

However, there are certain issues with the proposal:

  • It still requires users to make a file extension change from .js to .ts, which usually implies some change in build steps.
  • It provides no easy migration path from other type systems with annotation syntax used in .js files (see Using typescript babel to transition from flow TypeScript-Babel-Starter#1).
  • It introduces the concept of a "diluted/loose" TypeScript experience which can make things more confusing.

Proposal

We can introduce a new mode that enables TypeScript-specific constructs in .js files. This new mode would allow things like type annotations, interfaces, class property annotations, etc. to be declared in .js files. Users would have to explicitly opt-in to this mode for transitionary purposes, with the end goal of migrating to TypeScript.

Supported constructs

The following constructs from TypeScript would be supported:

  • Type annotations (: Foo)
  • Interfaces (interface Foo { /*...*/ })
  • Type alias (type Foo = "hello" | "world")
  • as-style type assertions (xyz as SomeType)
  • Non-nullable type assertions (x!.bar)
  • Definite assignment assertions (let x!: number)
  • Enums (enum E { /*...*/ })
  • Import aliases and export aliases:
    • `import

Unsupported constructs

The following would not be supported to encourage users to write ECMAScript modules and standard enums that utilize late-binding.

  • Namespaces
  • const enums

Existing typed .js file semantics

A JavaScript file still has the same specialized semantics including understanding things like CommonJS modules, JSDoc type annotations, ES5-style constructor functions, object literals potentially being open-ended, etc. However, in the presence of an analogous TypeScript construct, the TypeScript construct always wins. For example, the following declares x as type number, and potentially issues an error on the JSDoc.

/**
 * @type {string}
 */
var x: number;

Drawbacks

This proposal avoids the aforementioned issues with #22665, but has some new drawbacks.

For one, it seems like there's little-to-no advantage to moving from a .js file to a .ts file, even though TypeScript is easier to reason about and make assumptions on (whereas much of our JavaScript semantics are more "best-effort").

The other issue, which is likely much bigger, is that this conflates where JavaScript ends and TypeScript begins. While the intent here is to make migration easier, enabling this functionality could be perceived poorly as an attempt to extend the language inappropriately. While we hope users understand this is not the case, we are extremely open to feedback from the community on this issue.

If this flag was called something like --jsMigrationMode, perhaps we could be explicit on the intent and also signal to users that having this flag on is not ideal.

Existing Precedent

Common usage of JSX and Flow in .js files in the Babel ecosystem (as opposed to using the .jsx file extensions) provides a reasonable precedent for supporting TypeScript constructs in .js files.

@mhegazy
Copy link
Contributor

mhegazy commented May 4, 2018

The following would not be supported to encourage users to write ECMAScript modules and standard enums that utilize late-binding.

Why would we make the distinction any ways.. You have listed tools in the existing precedents section that have added syntax that are not on the ES-standards track to .js file. I would say just enable all TS syntax in a .js file.

@DanielRosenwasser DanielRosenwasser added the Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature label Jul 25, 2018
@sibelius
Copy link

I think this could now be done using babel 7 to strip typescript types

@rbiggs
Copy link

rbiggs commented Jul 26, 2018

With JSDoc, type information is isolated from the JavaScript by standard JavaScript comments. This means you can use the JavaScript file directly in the browser, NodeJS or any other context that would only assume standard JavaScript.

With this proposal there would be TypeScript type definitions directly in the JavaScript as if it were TypeScript. This means that it has to have some kind of build step to remove that information. I'm afraid users may not realize this distinction and think that, like with JSDoc type information, a file with such TypeScript types could be used in any possible JavaScript context (browser, NodeJS, etc.).

@mihailik
Copy link
Contributor

mihailik commented Aug 1, 2018

For projects that don't use TS yet, this feature adds little value. You'd have to refactor your build process anyway (as old JS-based tools blow up on TS syntax). Comparing to that renaming .js to .ts takes no effort really.

It may only help to those who already run their .js through TSC for some reason, and want to use more TS goodness, but not ready to rename files into .ts.

Sounds like too little benefit for too narrow audience. On the other hand, the amount of confusion it might create is massive. People will lose their stuff because they didn't realise they're deleting source file instead of build product.

And just think about where this would put the resulting file?

tsc --jsMigrationMode  small-file.js

@RyanCavanaugh RyanCavanaugh removed the In Discussion Not yet reached consensus label Jul 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants