Closed 10229428 closed 5 years ago
Take a look at how I do it in https://github.com/AlCalzone/virtual-tsc (in /src/server.ts
)
@AlCalzone seems like your solution is partially to disable declaration emit. @sheetalkamat, any idea if this is the most optimal way?
@AlCalzone This is what I tried and seems to work correctly:
const typescript = require("typescript");
const options = {
module: typescript.ModuleKind.CommonJS,
target: typescript.ScriptTarget.ES2015,
strict: true,
suppressOutputPathCheck: false
};
const file = {fileName: 'test.ts', content: "let test = 'aa';"};
const compilerHost = typescript.createCompilerHost(options);
const originalGetSourceFile = compilerHost.getSourceFile;
compilerHost.getSourceFile = (fileName) => {
console.log(fileName);
if (fileName === file.fileName) {
file.sourceFile = file.sourceFile || typescript.createSourceFile(fileName, file.content, typescript.ScriptTarget.ES2015, true);
return file.sourceFile;
}
else return originalGetSourceFile.call(compilerHost, fileName);
};
compilerHost.writeFile = (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
console.log('writeFile =====> fileName: ', fileName, ', data: ', data);
};
const program = typescript.createProgram([file.fileName], options, compilerHost);
let emitResult = program.emit();
The result was:
test.ts
c:/temp/test2/node_modules/typescript/lib/lib.es6.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es5.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.core.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.collection.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.generator.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.promise.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.iterable.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.symbol.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.proxy.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.reflect.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.dom.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.dom.iterable.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
c:/temp/test2/node_modules/typescript/lib/lib.scripthost.d.ts
writeFile =====> fileName: test.js , data: "use strict";
let test = 'aa';
@sheetalkamat Looks like I can simplify my code a bit. Thanks!
Take a look at how I do it in https://github.com/AlCalzone/virtual-tsc (in
/src/server.ts
)
Thank you very much! It works perfectly! But, I have an other question.
The compile process is in a project which based Angular running in browser. The code what I want to compile to javascript is :
import {Component, ViewChild, EventEmitter, ElementRef, NgZone} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {EventBus, DataBus, LogService, util, LoadingService} from '@rdkmaster/uid-sdk';
import {TranslateHelper, JigsawBox, TimeGr, TimeService, JigsawButton} from '@rdkmaster/jigsaw';
export class AppComponent {
test($event: any) {
this.aaaa = 'aaaa';
}
}
There are some imported modules and errors in function test. The output js code is my wanted. The diagnostics are:
[
{"sourceLine":"import {Component, ViewChild, EventEmitter, ElementRef, NgZone} from '@angular/core';","description":"Cannot find module '@angular/core'."},
{"sourceLine":"import {HttpClient} from '@angular/common/http';","description":"Cannot find module '@angular/common/http'.",
{"sourceLine":"import {EventBus, DataBus, LogService, util, LoadingService} from '@rdkmaster/uid-sdk';","description":"Cannot find module '@rdkmaster/uid-sdk'.",
{"sourceLine":"import {TranslateHelper, JigsawBox, TimeGr, TimeService, JigsawButton} from '@rdkmaster/jigsaw';","description":"Cannot find module '@rdkmaster/jigsaw'.",
{"sourceLine":" this.aaaa = 'aaaa';","description":"Property 'aaaa' does not exist on type 'AppComponent'."
]
The first four diagnostics are about the imported modules, the last one is the semantic diagnostic which I want. How can I resolve the diagnostics about "import .... Cannot find module '....' "? I don't konw how to handle the imported module for the compile ts code.
In your project, I notices that you write some ambient declarations files into virtual file system. Is this what I want?
// provide all ambient declaration files
for (const ambientFile of Object.keys(ambientDeclarations)) {
if (!/\.d\.ts$/.test(ambientFile)) throw new Error("Declarations must be .d.ts-files");
fs.writeFile(ambientFile, ambientDeclarations[ambientFile], true);
}
In your project, I notices that you write some ambient declarations files into virtual file system. Is this what I want?
Probably that is what you want and should be the easiest to accomplish. Or you need to somehow put the node_modules directories of all imported modules into the virtual fs aswell, so TypeScript can locate it. (Although I'm not sure right now if I added a special case to avoid looking those up)
In your project, I notices that you write some ambient declarations files into virtual file system. Is this what I want?
Probably that is what you want and should be the easiest to accomplish. Or you need to somehow put the node_modules directories of all imported modules into the virtual fs aswell, so TypeScript can locate it. (Although I'm not sure right now if I added a special case to avoid looking those up)
Thanks! I will try it later.
@sheetalkamat or anyone else, do you have an idea of how to get the simple solution above working inside a create-react-app
context? I seem to get errors with properties on ts.sys
being undefined, such as:
Cannot read property 'useCaseSensitiveFileNames' of undefined
at this line: https://github.com/microsoft/TypeScript/blob/1cbace6eee8257309e5e8dc5a2389a20077a5c08/src/compiler/program.ts#L77
Here's an example on CodeSandbox:
https://codesandbox.io/s/create-react-app-v3-with-tscreatecompilerhost-cielb
I have a hunch that this is because running ts.createProgram
in the create-react-app
context is not exactly the same as running in the Node context, from this Stack Overflow question/answer:
https://stackoverflow.com/questions/52969177/typescript-createprogram-throwing-ts-sys-is-undefined
By playing around a little bit, I got something working today (by declaring the compilerHost
as an object instead):
https://github.com/codesandbox/codesandbox-client/issues/2090#issuecomment-505500573 https://twitter.com/karlhorky/status/1143817823342551040
I want to compile ts code to js code in the browser. I use 'transpileModule ' firstly, but I found that through this API I can't get semantic diagnostics, only some syntactic diagnostics. So I change to 'createProgram' API. Unfortunately, I found that I only can get the declaration code, '.d.ts', not js code.
this.typescript
isnode_modules\typescript\lib\typescript.js
.By the function
writeFile
in my host, the content of data is the declare code, not js code.