question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support for all type features in declaration files.

See original GitHub issue

I’m on TS 3.7.3 at time of writing this.

It seems like this issue should simply be focused on and fixed before continuing to add more and more features to the language and widening the source vs declaration gap. This is quite a problem!

Search terms

“typescript declaration file limitations” “has or is using private name” “exported class expression may not be private or protected” “Property ‘foo’ of exported class expression may not be private or protected. ts(4094)” “Return type of exported function has or is using private name ‘foo’. ts(4060)”

Related issues (a small fraction of the results on Google) in no particular order:

Workaround

One way to work around all of the above issues, for libraries, is to have library authors point their types field in package.json to their source entrypoint. This will eliminate the problems in the listed issues, but has some big downsides:

  1. If a downstream consumer of a library without declaration files (f.e. without dist/index.d.ts) but with types pointing to a source file (f.e. src/index.ts) then if the consumer’s tsconfig.json settings are not the same as the library’s, this may cause type errors (f.e. the library had strict set to false while being developed, but the consumer sets strict to true and TypeScript picks up all the strict type errors in the library code).
  2. If skipLibCheck is set to true, the consumer project’s compilation will still type-check the (non-declaration) library code regardless.

With those two problems detailed, if you know you will be working in a system where you can guarantee that all libraries and consumers of those libraries will be compiled with the same compiler (tsconfig.json) settings (i.e. similar to Deno that defines compiler options for everyone), then pointing the package.json types field to a source file (because declaration output is not possible) is currently the workaround that allows all the unsupported features of declaration files to be usable. But this will fail badly if a library author does not know what compiler settings library consumers will have: everything may work fine during development and testing within external examples, but a downstream user will eventually report type errors if they compile their program with different settings while depending on the declaration-less libraries!

Suggestion

Support for all type features in declaration files.

Please. 🙏 I love you TS team, you have enabled so much better code dev with TypeScript. ❤️ 😊 TS just needs declaration love for support of all features of the language.

Some work is being done, f.e. https://github.com/microsoft/TypeScript/issues/23127, but overall I feel that too much effort is being put onto new language features while declaration output is left behind.

This creates a poor developer experience when people’s working code doesn’t work (the moment they wish to publish it as a library and turn on declaration: true).

I hope the amazing and wonderful TS team realize how frustrating it may feel for someone to work on a project for months, only to end with un-fixable type errors the moment they want to publish the code as a library with declaration: true, then having to abandon features and re-write their code, or try to point package.json "types" to .ts files only to face other issues.

I wish every new feature of the language came paired with working tests for equivalent declaration emit. Can this be made a requirement for every new language feature, just like unit tests are a requirement?

Use Case

Use any language feature, publish your code, then happily move along, without facing issues like

src/html/DeclarativeBase.ts:25:10 - error TS4094: Property 'onChildSlotChange' of exported class expression may not be private or protected.

25 function makeDeclarativeBase() {
            ~~~~~~~~~~~~~~~~~~~

src/html/WebComponent.ts:32:10 - error TS4060: Return type of exported function has or is using private name 'WebComponent'.

32 function WebComponentMixin<T extends Constructor<HTMLElement>>(Base: T) {
            ~~~~~~~~~~~~~~~~~

I worked hard for months to get the typings in the above code working, then I turned on "declaration": true and TypeScript said “today’s not the day!”.

I hope you the team can see that these issues are a pain, and realize the need to bring declaration emit to parity with language features and not letting the gap between language features and declaration output widen.

Examples

The issue that sparked me to write this was https://github.com/microsoft/TypeScript/issues/35744.

In that issue there’s an example of what implicit return types might look like:

export declare function AwesomeMixin<T extends Constructor>(Base: T) {
  type Foo = SomeOtherType<T> // only types allowed in here.
  
  // only special return statements allowed, or something.
  return declare class Awesome extends Base {
    method(): Foo
  }
}

We’d need solutions for other problems like the protected/private error above, etc.

Of course it’ll take some imagination, but more importantly it will take some discipline: disallow new features without declaration parity.

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:72
  • Comments:29 (8 by maintainers)

github_iconTop GitHub Comments

8reactions
frank-weindelcommented, Aug 10, 2021

@RyanCavanaugh I have to say, I’m also disheartened by this. A team could spend a long time building a library and assuming that “if it compiles, it’ll work!” only to find out after turning declarations on that they have a ton of very difficult to solve errors. It’s not intuitive and not very much documented that there are such limitations. I’m happy I’m finding this out now by chance.

6reactions
canonic-epicurecommented, Jun 1, 2021

Keeping the discussion going, copied from #44360:

I found it very discouraging, that TypeScript is currently fragmented into 2 languages. The 1st one is TypeScript itself and 2nd is TypeScript+declaration files. The program, valid in the 1st language, is not valid in the 2nd. This means, the TypeScript is a superset of TypeScript+declarations.

You can express more logic in TypeScript, however the TypeScript+declarations is a standard for distributing code (to avoid recompilation of the source files).

Despite being a well-known issue, this fragmentation is not documented anywhere, and TS development team does not provide much feedback about it. It is a hushed up thing, nobody wants to talk about this. This issue should, at the very least, be described in details, on the documentation website.

The solution is simple - a design decision should be made, that *.d.ts files should create exactly the same internal compilation data, as regular source files. For that, probably a different format of the declaration files is needed, *.d2.ts

Its very discouraging, when you have to spent hours, mingling your code (that compiles just fine in TypeScript), reducing type-safety, to make it work in the TypeScript+declarations language. In many cases its not possible at all.

Read more comments on GitHub >

github_iconTop Results From Across the Web

A quick introduction to “Type Declaration” files and adding ...
In this lesson, we are going to take a closer look at type declaration files which are one of the key ingredients of...
Read more >
Documentation - Introduction - TypeScript
The Declaration Files section is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume basic familiarity...
Read more >
TypeScript — Type Declaration Files | by Makesh Kumar
TypeScript itself comes with a bunch of type declaration files to support all JavaScript features. After installing TypeScript, navigate to ...
Read more >
Writing Declaration Files for @types - TypeScript
DefinitelyTyped is just a simple repository on GitHub that hosts TypeScript declaration files for all your favorite packages.
Read more >
import - JavaScript - MDN Web Docs - Mozilla
In order to use the import declaration in a source file, the file must ... tags without type="module" , eval , new Function...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found