TypeScript
TypeScript copied to clipboard
Types declared in types.d.ts not included in output of tsc --emitDeclarationOnly
Bug Report
🔎 Search Terms
emitDeclarationOnly allowJs "missing types" ".d.ts file" "declaration file"
🕗 Version & Regression Information
When did you start seeing this bug occur?
Only noticed it just now.
- This is the behavior in every version I tried (
typescript@latest
,typescript@next
,[email protected]
), and I reviewed the FAQ for entries about declaration files
⏯ Playground Link
💻 Code
// index.js
function bar () {
return 'baz';
}
/** @returns {BarFn} */
export function foo () {
return bar;
}
// types.d.ts
type BarFn = () => string;
// jsconfig.json
{
"compilerOptions": {
"target": "es2021",
"module": "es2022",
"checkJs": true,
"moduleResolution": "node",
"strictNullChecks": true
},
"include": [
"index.js",
"types.d.ts"
]
}
// package.json
{
"name": "tsc-emitdeclarationonly-js",
"type": "module",
"main": "index.js",
"types": "types/lib/index.d.ts",
"scripts": {
"gentypes": "tsc -p jsconfig.json --noEmit false --declaration --emitDeclarationOnly --outDir types"
},
"devDependencies": {
"typescript": "^4.9.3"
}
}
🙁 Actual behavior
The command tsc -p jsconfig.json --noEmit false --declaration --emitDeclarationOnly --outDir types
generates this types/index.d.ts
:
/** @returns {BarFn} */
export function foo(): BarFn;
which is missing the declaration of BarFn
.
🙂 Expected behavior
I expected the BarFn
declaration to be included in the generated types/index.d.ts
:
/** @returns {BarFn} */
export function foo(): BarFn;
export type BarFn = () => string;
... as indeed it is if I move the declaration from types.d.ts
into index.js
, expressed in JSDoc form:
/** @typedef {() => string} BarFn */
... but I don't want it there and in JSDoc form, I want it in a types.d.ts
file (visible across my codebase) and in TypeScript form. And included in the generated types/index.d.ts
.
By design. This is essentially a duplicate of #32624.
Thanks. So if I have declared some types in a .d.ts
file to make them global to my JS project, and want to also publish them as part of my project's public interface ... then that's simply out of scope for tsc
and I should just copy over that additional .d.ts
file myself. Correct?
copy over that additional .d.ts file myself
... hm, and edit the generated index.d.ts
file to explicitly import types from that types.d.ts
file? The type names referenced in the generated index.d.ts
file do not resolve unless I add an explicit import like:
import { BarFn } from "./types.d.ts";
Is that also as designed? It seems contrary to what happens inside the JS project — types in types.d.ts
are globally resolvable in all .js
files in the project, but then when referenced in the generated .d.ts
file they are not resolvable without manually editing that generated file. 😵
Sorry about the basic questions, I have the feeling I'm missing some intended step or config that makes this make sense. :-)
If you had a .d.ts file which you consumed and you published it along with your package, and someone else did the same thing, then you'd have a conflict in the global scope.
In general if you're hand-authoring something that's local to your project, it should be in a .ts file, not a .d.ts file.
[I'm almost there!]
If you had a .d.ts file which you consumed and you published it along with your package, and someone else did the same thing, then you'd have a conflict in the global scope.
Here you mean specifically a .d.ts file with no top-level imports or exports (so it isn't describing a module, so its declarations go into the global scope) ... is that correct?
In contrast, a module .d.ts. file is OK to publish and consume internally (just have to use import('...my-module').MyType
instead of MyType
) ... correct?
In general if you're hand-authoring something that's local to your project, it should be in a .ts file, not a .d.ts file.
Hm, but if that .ts file contains only type declarations, at least one of which is exported (so the file describes a module), then that is exactly the same thing — the only difference in practice is:
- if the file is named
types.d.ts
thentsc
will not emit it tooutDir
(so imports from it in files that are emitted will be broken) - if the file is named
types.ts
, thentsc
will emit it tooutDir
, with the nametypes.d.ts
and identical contents (except for possible formatting differences)
... correct? Or are there other differences?
(In my use case, this file should only contain types, no implementation, and I prefer the .d.ts name in order to both convey and enforce that.)
Then the above example becomes:
// index.js
function bar () {
return 'baz';
}
/** @returns {import("./types").BarFn} */
export function foo () {
return bar;
}
// types.d.ts
export type BarFn = () => string;
Here I can either rename types.d.ts
to types.ts
... or equivalently just copy it to the outDir
after running tsc
... and either way, that's it, I've published my types, and caused no problems. All correct?
:wave: Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript.
Issue body code block by @gthb
:x: Failed: -
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
Left side of comma operator is unused and has no side effects.
';' expected.
';' expected.
';' expected.
';' expected.
';' expected.
';' expected.
Declaration or statement expected.
';' expected.
';' expected.
';' expected.
';' expected.
';' expected.
';' expected.
';' expected.
Declaration or statement expected.
';' expected.
';' expected.
Historical Information
Version | Reproduction Outputs |
---|---|
4.5.2, 4.6.2, 4.7.2, 4.8.2, 4.9.3 |
:x: Failed: -
|
:wave: Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of this repro running against the nightly TypeScript.
Comment by @gthb
:+1: Compiled
Historical Information
Version | Reproduction Outputs |
---|---|
4.5.2, 4.6.2, 4.7.2, 4.8.2, 4.9.3 |
:+1: Compiled |
An external tool generates .d.ts and .js files, which I can't seem to get to work with tsc. I tried renaming the .d.ts file to a .ts file as suggested in this thread, and it doesn't compile:
.d.ts file has:
interface IUpdateServerService { value: string }
export const UpdateServerService: IUpdateServerService;
As a .ts file, the compiler error I get is:
error TS1155: 'const' declarations must be initialized.
It would be nice if tsc could be configured to just directly copy over the .d.ts and .js files.
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 or the TypeScript Discord community.
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 or the TypeScript Discord community.