With Node v11.6.0, and TSC, 3.2.2, I am getting
node_modules/rxjs/internal/Observable.d.ts:82:59 - error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
82 toPromise<T>(this: Observable<T>, PromiseCtor: typeof Promise): Promise<T>;
~~~~~~~
Found 1 error.
When I run
type P = typeof Promise;
Using @types/node
This is a bug push up from rxjs https://github.com/ReactiveX/rxjs/issues/4448
You can see the issue documented at https://stackoverflow.com/questions/54014405/ts2585-promise-only-refers-to-a-type-but-is-being-used-as-a-value-here
The error message says you should be targeting lib: "es2015â
. Are you? Note that lib
and target
are distinct because of polyfills (you can polyfill builtins but not syntax)
@fatcerberus I have a sample repo with it, in that repo i'm doing es2018 for lib, but you can try es2015 same thing.
Just a hunch, have you tried using lowercase for es2018
? I know the docs show uppercase but I think that might be a mistake as Iâve always seen it lowercase in practice. Otherwise I have no clue whatâs wrong here, it seems bizarre.
It is lower case, no joy. It's also confirmed by the rxjs guys and the stackoverflow commenter. Nothing that uses promises works on node 11
What I donât understand is what the node version has to do with this - typescript and node are completely separate tools.
oh okay - I see, the issue is when the typescript compiler is run on node 11, not when targeting node 11. My bad.
So I tried to reproduce this using the exact tsconfig, dependencies, and sample code as in the SO question... and it seems to work fine on my end. Node.js version is 11.6.0.
npm install typescript
npm install rxjs
npm install @types/node
npm install ts-node
D:\temp>npx tsc
D:\temp>type main.js
import { range } from 'rxjs';
import { map, filter } from 'rxjs/operators';
range(1, 200).pipe(filter(x => x % 2 === 1), map(x => x + x)).subscribe(x => console.log(x));
Did you pull down my repository run npm install and then try to tsc the file? I'm confused, you say this
oh okay - I see, the issue is when the typescript compiler is run on node 11
Which is true, and then you say " it seems to work fine on my end. Node.js version is 11.6.0."
Yeah, that was before I tested it - that was just stating I understood why you mentioned the node version.
I don't know what else to say, I got the prob. Guy on SO and on RXJS question got the prob. Repo is simple works (to show the problem) with the latest version of all tools. It's giving that error on running tsc on my box (running Linux).
This is the line that's problematic for you, this is working?
type P = typeof Promise;
Yeah, that works, as does:
C:\temp>git clone https://github.com/EvanCarroll/rxjsissue4448
Cloning into 'rxjsissue4448'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), done.
C:\temp>cd rxjsissue4448
C:\temp\rxjsissue4448>npm install
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
added 3 packages from 39 contributors and audited 3 packages in 1.825s
found 0 vulnerabilities
C:\temp\rxjsissue4448>npx tsc
C:\temp\rxjsissue4448>node -v
v11.5.0
v11.5 because I switched machines--still Node 11 though. Tested on both Windows and Linux (Ubuntu 16.04, Node.js installed from snap).
Only thing I can think of is you're somehow picking up a stale tsconfig.json from elsewhere.
no idea what npx does, or what it's doing differently can you just run tsc runme.tsc
?
It's the same thing - tsc
by itself requires typescript installed globally, npx
is when it's installed locally (in node_modules). Works either way.
No idea, all I know is it's erroring with me and I'm not using any special layer so I'm trying to keep it simple and figure out why it's not erroring for you, and I'm thinking your npx is doing something.
tsc runme.ts
Nope, here's the exact issue - you're telling tsc to transpile a single file. In that case it ignores the tsconfig.json and just transpiles the file in a vacuum, using all defaults for the tsconfig fields. Since there is no ///<reference>
tag in the source for the es2015 lib you get the Promise error.
What you want to do is just run tsc
. You can include/exclude files as necessary by specifying them in the tsconfig (which is your project file).
This behavior, by the way, is documented:
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
When input files are specified on the command line, tsconfig.json files are ignored.
Nope, here's the exact issue - you're telling tsc to transpile a single file. In that case it ignores the tsconfig.json and just transpiles the file in a vacuum, using all defaults for the tsconfig fields. Since there is no ///
tag in the source for the es2015 lib you get the Promise error.
Wow, even if documented that's extremely counter intuitive. I can't think of any program that ignores the configuration file when given an argument that isn't explicitly either conflicting with the configuration file, or demanding to override it. That's not a good user interface at all. Git and NPM being two examples that don't behave in that way that typescript users are likely to be using in the same project.
The use case here being
tsc file.ts
which they believe runs Typescript on the file.tsc file.ts
again and get the same errorAt the absolute least I would expect tsc
to be verbose by default and tell us it's ignoring the configuartion file which specifies the values of lib
needed. I imagine many of your users are doing the above. I use TSC regularly but I've never used it with Rx.js outside of a project that had tsc. So now I'm just wanting to use tsc for Rx.js.
It makes sense to me at least - you either tell it to compile a whole project file, or you pass one or more source files and specify the options on the command line. Everything you can specify in tsconfig.json has a corresponding command-line option.
It would be probably be bad if it used the tsconfig when specifying files on the command line - since then if you used tsc in, say, a shell script, the behavior of the script would change depending on whether the CWD contained a tsconfig.
Essentially the tsconfig is a âbuild scriptâ - you tell tsc to use that instead of specifying everything you want to do on the command line. Itâs not a âcompiler preferencesâ file (admittedly the naming of âtsconfigâ is a bit confusing in that regard), itâs a self-contained project in itself, like what .vcproj is for MSVC.
Basically: think of tsconfig.json as a makefile, and tsc
as a make tool + compiler in one.
since then if you used tsc in, say, a shell script, the behavior of the script would change depending on whether the CWD contained a tsconfig.
Isn't that how everything works though?
make
reads .Makefile in the current directorynpm
reads package.json
in the current directorygit
reads .gitignore
in the current directoryNone of them forget about their config file when you provide an option. They simply override that option and use the config file to create the execution environment for the command. I understand what you're talking about but this is the only utility that works in this fashion -- where providing an argument means it forgets about the config file.
I want the config file to configure TSC for the project. Not to specify the exact item i'm wanting to compile. It just intuitive to me that the working directory be significant, especially if there is a config file inside it and not only if there are no arguments provided to the program.
Let me make it clear: What youâre essentially asking for is analogous to wanting gcc
to honor options in a makefile even when invoked directly. It just so happens that tsc
combines these two functions into one program.
What you may be able to do is (not tested):
tsc --project ./tsconfig.json runme.ts
Let me make it clear: What youâre essentially asking for is analogous to wanting gcc to honor options in a makefile even when invoked directly. It just so happens that tsc combines these two functions into one program.
Not exactly, because GCC and make are separate; there is a distinction there so I would never expect gcc to accept a configuration file anyway. But tsc does with the --project
command you've provided which makes it similar to make
, and npm
, and git
.
So with make if you have a basic Makefile,
.PHONY: ALL
CFLAGS="COMPILER FLAGS"
ALL: foo bar
.DEFAULT:
@echo "${CFLAGS}" caught target $@
And you run make
it builds foo
and bar
, now if you run
make baz
It still uses the make file. It doesn't forget it and act like a compiler. It just builds instead baz
. And it does it with the CFLAGS
. The same applies btw if you want to run one specific rule or compile one file outside. For example if you run make foo.c
inside of a build directory it will use the Makefile to build that one file.
Does it seem intuitive to you to say that the default for --project
is ./tsconfig.json
in all instances except when you provide it arguments? In which case if you want to use tsconfig.json
you have to manually supply it?
Using the above analogy:
tsc file.ts
is gcc.
tsc --project
is make.
It just so happens that, for convenience, the specific case of tsc
with no arguments implies --project
. The alternative would be an error because you didnât provide any input files.
I understand how things are, now that you've explained them and did immediately on my first response here. I just find that entirely unintuitive and I imagine I'm in the majority here. You've severed tsc into two modes, neither of which are apparent to the user and used those two modes to justify a different user interface. I wasn't aware that I was supposed to
tsc file.ts
as a compilertsc
as a make system./tsconfig.json
as a default configuration for the make system, but also an acceptable and optional configuration file for the compiler environment via --project
tsc file.ts
as an invocation of the compiler, rather than tsc file.ts
as being a directive to build the file with the configuration file.I'll just leave it off with this, because I'm honestly just trying to provide some guidance to build a better system. Ask some people who do NOT know the default behavior this question
"If tsc builds a project by reading from tsconfig.json, would you expect
tsc file.ts
to build that file with the configuration in tsconfig.json, or to ignore tsconfig.json and compile the file?"
Just for fun https://twitter.com/TheEvanCarroll/status/1080899909522477061 (maybe I am in the minority)
Iâll agree with you that the âproject builderâ should probably be a separate tool (tsmake or something), but practically speaking, since I assume it was a conscious design decision not to have two distinct tools, how would you make tsc
fully scriptable like a command line compiler (without the risk of picking up stray config filesâjust look to eslint for how many headaches that can cause) but still get the make-like functionality? Given those constraints, I would probably set up things up the same way.
Wouldn't you want to follow the lead of most all the other tools (eslint, babel, etc) and have an explicit CLI opt-out for avoiding the config file? In other words, "gcc" usage is nowhere near the common case, and seems surprising to most users, so it seems like a poor choice of default.
In any case, I donât think this can be changed now without breaking peoplesâ build environments, which would be bad considering how TypeScriptâs release cycle seems to work (every major or minor version supersedes the last). But Iâll duck out at this point and let actual TypeScript team members chime in if they want before I accidentally make a fool of myself. :smile:
Would you consider changing the title of the issue to better reflect the ongoing conversation, to provide a better summary and be more convenient to find? For an example, âInconsistent tsc behavior with and without file parametersâ. @EvanCarroll @weswigham
Another use case: we have a pre-commit hook which runs tsc
for all changed files, and as soon we can't mix --project
with files list we wrote a code to convert compilerOptions
to CLI args. Everything works fine until today when we want to use paths
compiler option, which cannot be passed via CLI đ
Even without implicit using tsconfig.json
for compiler options why we can't use --project
arg and files list together?
_(maybe this isn't that issue where I should post this comment, but my opinion is that tsc should use compiler options from a config while compiling only one file)_
Thanks for your help all. Problem solved here.
This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.
@DanielRosenwasser @RyanCavanaugh It is very disappointing this hasn't been taken further into consideration. This is how 98% of javascript developers expect tsc
to behave and would make tsc
consistent with every other node tool out there.
Please reopen; nonhumans closing issues is exceedingly user-hostile.
Allowing to override tsconfig.json
by passing a file path with tsc --noEmit -p tsconfig.json
would be really useful and would avoid having multiple config files. Please reopen. Thank you!
Allowing to override tsconfig.json by passing a file path with tsc --noEmit -p tsconfig.json would be really useful and would avoid having multiple config files. Please reopen. Thank you!
This is already supported!
Please reopen; nonhumans closing issues is exceedingly user-hostile.
I will close this myself to help đ
This is the intended behavior because we don't want to break thousands of msbuild
-based compilations where people are using .csproj
settings for one compilation and tsconfig.json
for something else. Even issuing a warning when a tsconfig.json
is present has the potential to break these builds because people might have warnings-as-errors turned on.
people are using .csproj settings for one compilation and tsconfig.json for something else
You can add --no-project
flag for them (it's joke, don't bear on me đ).
Even issuing a warning when a tsconfig.json is present has the potential to break these builds because people might have warnings-as-errors turned on.
What about allowing to pass a list of files along with --project
to override files to compile? It seems that it shouldn't break case you've described above.
Also, what's about compiler options which cannot be passed via CLI such paths
(see https://github.com/microsoft/TypeScript/issues/29241#issuecomment-459789340)?
@RyanCavanaugh
What about allowing to pass a list of files along with --project to override files to compile?
See also #27379. I think there's also another issue where people expect to be able to augment the file list in this manner.
Also, what's about compiler options which cannot be passed via CLI
I think allowing some way of specifying additional tsconfig files (probably in a "config only" mode) would be a very reasonable suggestion. I know some teams are effectively doing this by auto-generating tsconfig files in their build scripts; it'd be nice to make that kind of automation unnecessary.
What about allowing to pass a list of files along with --project to override files to compile? It seems that it shouldn't break case you've described above.
Also, what's about compiler options which cannot be passed via CLI such paths (see #29241 (comment))?
This is exactly what I was trying to do and it doesn't work for me. I will look at versions for a new update if you're saying this is supported already.
Most helpful comment
Wow, even if documented that's extremely counter intuitive. I can't think of any program that ignores the configuration file when given an argument that isn't explicitly either conflicting with the configuration file, or demanding to override it. That's not a good user interface at all. Git and NPM being two examples that don't behave in that way that typescript users are likely to be using in the same project.