-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Allow just generation of declarations, also allowJs #15911
Conversation
src/compiler/program.ts
Outdated
@@ -904,7 +904,13 @@ namespace ts { | |||
let declarationDiagnostics: Diagnostic[] = []; | |||
|
|||
if (options.noEmit) { | |||
return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; | |||
// Allow only emitting of declarations | |||
if (options.declaration) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense for declaration:true to override noEmit. Since it's something you have to do explicitly. I.e just having noEmit will emit nothing. If you really really want just declarations which is a valid use case then declarations:true and noEmit:true should give you the result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But are there cases where you want to ensure that declaration emit can succeed? For example, just something where you want to ensure that you won't get an error because of non-exported declarations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand what you mean? Care to give an example?
The main usecase for only declarations
is you have a pure js node project and you don't want to maintain hand typed .d.ts files. You don't care about emitting since your code is already in js.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DanielRosenwasser I don't think this overrides --noEmitOnError
, just --noEmit
. I do think we might want to have a separate compiler option for this however, as always emitting declarations could have undesired consequences.
That was the easy part :) the interesting part is what do we do with JS-specific constructors.. e.g. var x = require(".."); // should emit `import ... = require("..")`
function f() {
}
f.prototype.method = function() {} // should probably emit a class? etc.. moreover, today in the declaration emitter we do not walk expressions, but a lot of these JS constructs are expressions (assignments) and not declarations.. so how is that handled.. |
@mhegazy I expect typescript to be esnext -> es old transpiler and typechecker. I would expect it to the same thing as if you renamed the .js file into .ts file and try to run declarations:true. I think it's fair to say that it shouldn't magically understand prototype calls into classes or require calls into imports. If would expect allowJs + checkJs to treat js files with equal checks and integrity as a ts file but with types in jsdoc comments. |
TS already supports these patterns.. see https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files.. |
@mhegazy are you also okay with |
This is the easy part as i said. the hard part is emitting the declaration file. we should figure out that first. |
This would mean the declaration emitter is smart about expressions right. e.g. Can this come in as a second PR? Do you consider not making those transformations a breaking change? |
yes, and more importantlly: /**
* @typedef {Object} SpecialType - creates a new type named 'SpecialType'
* @property {string} prop1 - a string property of SpecialType
* @property {number} prop2 - a number property of SpecialType
*/
/** @type {SpecialType} */
var specialTypeObject; would look like: type SpecialType: {prop1: string, prop2: number };
declare var specialTypeObject: SpecialType; |
it is not being a breaking change or not. i am just questing the value of writing a .d.ts file that is different from what the compiler understands. to me, a .d.ts should fill in the place of a .js/.ts. so it should have the information you need to build against the file it describes. |
oh yes, I totally agree with that. so here's the declaration transforms that I see you mention. Class function X()
X.prototype.foo = function(a, b){} => declare class X {
foo(a, b);
} Interface /**
* @typedef {Object} SpecialType - creates a new type named 'SpecialType'
* @property {string} prop1 - a string property of SpecialType
* @property {number} prop2 - a number property of SpecialType
*/
/** @type {SpecialType} */
var specialTypeObject; => type SpecialType: {
prop1: string,
prop2: number
};
declare var specialTypeObject: SpecialType; Any others? I may need someone to help me out, seems pretty involved 😮 |
The complete list of things we do there can be captured by searching the code base for We have a write-up for this in https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files. For JSDoc supported patterns, you want to look at https://github.com/Microsoft/TypeScript/wiki/JSDoc-support-in-JavaScript for more details. I do not think you need to think about the whole set now. what is important is thinking of how do we add support for such things. For the function -> class transformation, i would assume we have special code in |
src/compiler/declarationEmitter.ts
Outdated
@@ -1888,7 +1888,7 @@ namespace ts { | |||
/* @internal */ | |||
export function writeDeclarationFile(declarationFilePath: string, sourceFileOrBundle: SourceFile | Bundle, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) { | |||
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFileOrBundle, emitOnlyDtsFiles); | |||
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; | |||
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhegazy Do we want to emit declaration files for --declaration --noEmit
for TypeScript (i.e. without --allowJs
)? This would be a breaking change and could have undesired consequences. Do we need to have a new compiler option for this behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhegazy Do we want to emit declaration files for
--declaration --noEmit
for TypeScript (i.e. without--allowJs
)? This would be a breaking change and could have undesired consequences. Do we need to have a new compiler option for this behavior?
I agree, we should not do that. either we emit declarations for Js files with --declaration --allowjs
, and users have to pass a --outDir tmp
, then ignore it (this is still potentially a breaking change since we did not emit these files in the past so current --allowjs
users would find this surprising), or we add a new flag --emitDeclarationsOnly
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bikeshedding here: perhaps --noEmitJs
as a looser --noEmit
that still emits declarations but not js output?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that sounds better than my proposal.
Happy to add another compiler option. May be something like noEmitJs:true.
…On Tue, May 30, 2017 at 10:24 AM, Ron Buckton ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/compiler/program.ts
<#15911 (comment)>
:
> @@ -904,7 +904,13 @@ namespace ts {
let declarationDiagnostics: Diagnostic[] = [];
if (options.noEmit) {
- return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
+ // Allow only emitting of declarations
+ if (options.declaration) {
@DanielRosenwasser <https://github.com/danielrosenwasser> I don't think
this overrides --noEmitOnError, just --noEmit. I do think we might want
to have a separate compiler option for this however, as always emitting
declarations could have undesired consequences.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#15911 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA-JVNmsbSs2Bq3uynjwH0VeOvdFdAiOks5r_FDBgaJpZM4NeOwo>
.
|
Although there seems to be already one as an /*@internal*/, I have no idea
what that does in the compiler options object though.
…On Tue, May 30, 2017 at 10:43 AM, Noj Vek ***@***.***> wrote:
Happy to add another compiler option. May be something like noEmitJs:true.
On Tue, May 30, 2017 at 10:24 AM, Ron Buckton ***@***.***>
wrote:
> ***@***.**** commented on this pull request.
> ------------------------------
>
> In src/compiler/program.ts
> <#15911 (comment)>
> :
>
> > @@ -904,7 +904,13 @@ namespace ts {
> let declarationDiagnostics: Diagnostic[] = [];
>
> if (options.noEmit) {
> - return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true };
> + // Allow only emitting of declarations
> + if (options.declaration) {
>
> @DanielRosenwasser <https://github.com/danielrosenwasser> I don't think
> this overrides --noEmitOnError, just --noEmit. I do think we might want
> to have a separate compiler option for this however, as always emitting
> declarations could have undesired consequences.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#15911 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AA-JVNmsbSs2Bq3uynjwH0VeOvdFdAiOks5r_FDBgaJpZM4NeOwo>
> .
>
|
`noEmitJs` it is. I'll make it happen.
…On Tue, May 30, 2017 at 2:01 PM, Mohamed Hegazy ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/compiler/declarationEmitter.ts
<#15911 (comment)>
:
> @@ -1888,7 +1888,7 @@ namespace ts {
/* @internal */
export function writeDeclarationFile(declarationFilePath: string, sourceFileOrBundle: SourceFile | Bundle, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFileOrBundle, emitOnlyDtsFiles);
- const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
+ const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath);
that sounds better than my proposal.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#15911 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA-JVPDmG0m6bXe2Bv0h2YCwdYOpNDDEks5r_IO1gaJpZM4NeOwo>
.
|
…g declarations on its own.
What's status of this? Since it's now possible to use only babel for TS compilation, this PR will be very helpful. |
Closing for now since it has been stale for over 6 months now. As noted earlier in #15911 (comment) the challenge here is figuring out how to emit declarations for JS declarations that come from expressions. |
I'm gonna take another stab at this. Hopefully get more time over Vacation
to work on this.
…On Tue, Nov 7, 2017 at 12:59 AM Mohamed Hegazy ***@***.***> wrote:
Closed #15911 <#15911>.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#15911 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA-JVFnnIyUCCaHu7hoBovJo8-oTSRj6ks5sz3MngaJpZM4NeOwo>
.
|
Scenario 1: Auto-Generate typings for a pure js project to be bundled with npm module
Scenario 2: Just emit typings for a project that is a hybrid of ts and js
Currently typings for js projects are manually hand maintained. A ton of typings are out of date with the actual code. Typings are kind of documentation and if they are separate from code, they will eventually get out of sync.
with --checkJs, JS lib authors get extra benefit of validating code with jsdoc typings. Being able to auto generate just .d.ts from their existing code would make life easier. This can be done as part of the build step.
Basically if declarations:true and noEmit:true, declarations should still be generated. If allowJs:true, then declarations should also be generated for the js files.
Proposal:
This would just generate a single .d.ts file from the project that you can add as part of package.json. No hand maintenance.
master
branchgulp runtests
locally (Need to fix some tests - WIP)Fixes #7546 #1866