microsoft/TypeScript

Supporting type annotations and type checking in JavaScript files

robertknight opened this issue ยท 7 comments

Given that there is substantial overlap between Flow and TypeScript syntax for type annotations and support in the Babel transpiler for stripping Flow annotations, it is now possible to write source files which are both valid type-annotated TypeScript and Babel-parsable ES2015 JavaScript, except for the restriction of type annotations and type checking to .ts files.

I think it could lower the perceived barrier to entry for TypeScript significantly if it could be used with existing Babel/JS codebases (at least those using ES2015 imports), as a type-checker (or "super linter") and IntelliSense/refactoring provider, just by dropping in a suitable tsconfig.json file.

Salsa/JSDoc/--allowJs are welcome steps but JSDoc is much more verbose, especially for the common task of defining interfaces. Documentation on how to describe interfaces precisely is also much better with TypeScript, since JSDoc is often written only to the standards of documentation, not as something that a machine can actually use.

As a concrete proposal, this might mean:

  • Allowing type annotations, including interfaces, in JS files if --allowJs is enabled
  • Providing a way to enable type checking within JS files, possibly via a //@flow style comment or project-wide via a tsconfig flag.
evmar commented

Could you elaborate on why you want to add annotations/interfaces to JS files? Isn't that just the different behavior you'd get anyway if you renamed them to .ts files?

No, as far as I know, Typescript files need to be compiled and all the codebase has to be Typescript if one file is Typescript. I think he means something like allowing per-file typechecking like Flow is doing, but with Typescript's type system and definitions instead of reinventing something from scratch.

My perception is that the perceived barrier to trying out TypeScript is higher than it needs to be. TypeScript solves two problems - it serves as a type checker and transpiler. Many projects already have a perfectly working solution for transpiling JS though in the form of Babel and probably a growing additional set of tooling which supports the same syntax (ESLint etc.)

Enabling TypeScript to be used just as a type checker only, without disrupting the existing build process (or tooling like linters) by renaming source files, would enable it to be used initially like a much smarter linter. For a project that is happily using Babel for its transpilation needs and already using ES2015 module syntax, the process could be like this:

  1. Drop in a tsconfig.json file, perhaps initially configured to type-check only a subset of files.
  2. Run tsc to type-check files.
  3. Gradually add type annotations to JS files, using the subset of syntax that is compatible with Babel/Flow, so there is no disruption to the existing build / linting toolchain.
  4. Perhaps eventually switch to TypeScript for the whole pipeline (less tooling to manage) or perhaps not.

You can achieve something like the above today via say, a Gulp task that copies the files to a different directory, renames the extension in the process and pipes the result through TypeScript with the noEmit flag - but it isn't a well documented workflow that someone can easily try.

More broadly, I think having two tools support the same syntax (and preferably in at least strong agreement on semantics) for type annotations in .js files would help promote the value of type annotations and interface documentation across the JavaScript ecosystem as a whole.

all the codebase has to be Typescript if one file is Typescript.

This is untrue, we have the --allowJS flag which allows you to compile your ES6 down to ES5 or ES3 while also including it in your general TypeScript project.

Flow adds things to .js files that need to be removed before native execution even on fully feature compliant runtimes. The same is true when jsx markup is included in a plain .js file. The difference between this and say native es6 code that has not been transpiled is that the latter is actually JavaScript. I think this is a terrible idea

More arguments in favor of adding this feature in the discussion here: #7926 (comment)

There has been multiple requests around this area. I have files a new issue to consolidate all the requests along with a proposal for a fix, see #10939. Let's use #10939 to track this change.
closing in favor of #10939.