Skip to content
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

5.3.2 adds broken "reference" comment #56571

Closed
rchl opened this issue Nov 28, 2023 · 19 comments
Closed

5.3.2 adds broken "reference" comment #56571

rchl opened this issue Nov 28, 2023 · 19 comments

Comments

@rchl
Copy link
Contributor

rchl commented Nov 28, 2023

🔎 Search Terms

reference types error

🕗 Version & Regression Information

  • This changed between versions 5.2.2 and 5.3.2

⏯ Playground Link

No response

💻 Code

My code does a type import like:

import type { ModuleOptions } from '../../module/module';

and in 5.3.2 this adds a type reference in the compiled output:

/// <reference types="dist/module/module" />

which is an invalid path from the point of the user of this package and result in an error:

node_modules/foo-package/dist/lib/dir/file.d.ts:4:23 - error TS2688: Cannot find type definition file for 'dist/module/module'.

4 /// <reference types="dist/module/module" />

🙁 Actual behavior

Adds a broken reference:

/// <reference types="dist/module/module" />

🙂 Expected behavior

5.2.2 didn't add a reference in this case.

Additional information about the issue

No response

ef4 added a commit to embroider-build/embroider that referenced this issue Nov 28, 2023
@NullVoxPopuli
Copy link

NullVoxPopuli commented Nov 28, 2023

I've noticed this, too:

mainly, here:
image

that whole reference line should not be present.
and its referencing a private file that the referenced package does not expose.
the typesVersions of that package is:

  "typesVersions": {
    "*": {
      "types": [
        "types/stable"
      ],
      "types/preview": [
        "types/preview"
      ]
    }
  },

the main thing through, is that as a library author, I've declared ember-source as a peer dependency so I know that consumers will have it available and the reference isn't needed.

AS IS

the triple slash reference behavior lends itself to libraries "breaking" during patch releases because typescript is exposing stuff it shouldn't.

Work-around

After generating declarations, remove triple slash directives

grep -r -l '///' declarations/ | sort | uniq | xargs perl -e \"s/\\/\\/\\/.*$//\" -pi

@rchl
Copy link
Contributor Author

rchl commented Nov 28, 2023

Likely caused by #55636

@andrewbranch
Copy link
Member

I think you’re probably using baseUrl and/or paths and shouldn’t be. The triple-slash reference is necessary. As a library author, you’ll need to make sure you use module resolution settings that are strict and portable enough that paths in your code (whether written by you or generated, based on your settings) also resolve for users. https://www.typescriptlang.org/docs/handbook/modules/guides/choosing-compiler-options.html#im-writing-a-library

@NullVoxPopuli
Copy link

@andrewbranch my tsconfig settings are already strict, and I don't use paths or baseUrl.

tsc with declaration: true is what is emitting the triple slash.

@andrewbranch
Copy link
Member

@NullVoxPopuli I was addressing that comment to @rchl. Your case looks like a bug where the generated path isn’t respecting typesVersions. Do you have repro steps for me?

the main thing through, is that as a library author, I've declared ember-source as a peer dependency so I know that consumers will have it available and the reference isn't needed.

The reference is needed. Knowing the consumers will have ember-source in their node_modules is a totally different thing from knowing that a consumer will have ember-source/types/preview/@ember/whatever in their TS program. Without the reference, there is no guarantee that the consumer will have those files in their compilation, which means something in that file (either globals or module specifiers registered with declare module '@ember/whatever') will not resolve.

@rchl
Copy link
Contributor Author

rchl commented Nov 28, 2023

I think you’re probably using baseUrl and/or paths and shouldn’t be.

Looks like you are right.

I have baseUrl: "." set in package's root, the input source is in /src and the output goes to /dist. When I remove baseUrl setting then the reference looks like:

/// <reference path="../../module/module.d.ts" />

which looks like should work fine (haven't tested to consume that yet).

@rchl
Copy link
Contributor Author

rchl commented Nov 28, 2023

Though I wonder if Typescript could do a "better" job when baseUrl is set and still use relative path in that case? The original import type path is relative so I don't fully get why it would produce non-relative path when baseUrl is set instead of using a relative one.

@NullVoxPopuli
Copy link

knowing that a consumer will have ember-source/types/preview/@ember/whatever in their TS program. Without the reference, there is no guarantee that the consumer will have those files in their compilation,

It's an incorrect reference though -- TS made the wrong call.
Even on the basis that it's private API -- e.g.: not exposed through typesVersions, and subject to change in a refactor. Thus, as semver floats patches / minors of the library, TypeScript is creating unneeded breakage because the /preview/sub/path no longer exists.

@andrewbranch
Copy link
Member

@NullVoxPopuli again, the path is incorrect, indicating a bug, but the reference is necessary. If there’s no way to write a path to the globals you’re implicitly referencing during your own compilation of the library, we should be giving you an error during declaration emit. If you have a repro for this, please open a new issue.

@rchl yeah, I think we could explore skipping paths/baseUrl for these paths that get generated in TypeScript-only constructs like triple-slash references. But that kind of hides the underlying misconfiguration here—the reality is that you could have written import "dist/module/module" in your own source code and TS would have thought that was going to be valid, and consumers would then have an issue both at runtime and compile time.

@rchl
Copy link
Contributor Author

rchl commented Nov 28, 2023

Just an extra note that TS is adding:

/// <reference path="../../module/module.d.ts" />

even though there also exists a related type import, importing from the same file:

import type { ModuleOptions } from '../../module/module';

So in that case at least the reference looks redundant.

While I don't disagree that using baseUrl is wrong in this case, it feels like the breaking change could have been avoided if the resolved paths in references would be more consistent with actual type imports those were generated from/for.

@andrewbranch
Copy link
Member

Hm, that import does make the triple-slash reference redundant. I would consider it an improvement if we could get rid of it, but not sure I’d classify its presence as a bug, or at least not a high priority one.

it feels like the breaking change could have been avoided if the resolved paths in references would be more consistent with actual type imports those were generated from/for.

Well, that’s exactly the issue—the triple-slash reference didn’t appear because of your import; on the contrary, it appeared because we failed to notice you already had an import resolving to the same thing, making the reference redundant. The triple-slash references appear when you access a global (or ambient module declaration, or export of a module augmentation). So we’re not taking the path you wrote and mangling it; we’re generating a path from scratch.

If you can make a minimal repro of this happening, I can at least open it up to community PRs.

@NullVoxPopuli
Copy link

NullVoxPopuli commented Nov 28, 2023

Can we have an option in compilerOptions for declaration emitting to not ever emit triple slash directives?

@andrewbranch
Copy link
Member

No, we don’t add options that intentionally break declaration emit 🤨

@rchl
Copy link
Contributor Author

rchl commented Nov 29, 2023

@andrewbranch if you want to investigate my case, even though it's technically invalid, I've created this minimal repro: https://github.com/rchl/ts-reference-test (includes compiled dist to easily see how it looks).

@chriskrycho
Copy link

Just so everyone has all the relevant context (and we should be super clear that the emit issue here is almost certainly something wacky we are doing on the Ember side, not a TS bug!)—

The mechanics of how Ember’s stable types are currently published are (as has been very typical for us) doing horrible things to deal with Ember’s “We implemented ESM ourselves!” decision back in 2015–2016, which in turn our type publishing mechanics have to account for and try to “translate” to something resolveable by TS (ultimately: by the standard Node resolution algorithm). The key constraint here was: Ember users import from specifiers like @ember/object, but there is no @ember/object package on disk. Ember users instead depend on the ember-source package, which bundles along the runtime and type dependencies for the @ember packages, and Ember CLI is responsible to resolve the module specifiers during the build.1

To enable a phased transition out of DefinitelyTyped, we took a two-step process of providing first “preview” and then “stable” types. In each case, users get access to the types by writing a side-effect-style import:

import 'ember-source/types/preview';

or

import 'ember-source/types';

The “preview” types were copied over from DefinitelyTyped, and written as a set of declare module declarations. The “stable” types are generated from Ember's own source. The distinction was: preview types were subject to lots of churn and change as we identified issues both in Ember and across the Ember ecosystem, while the stable types are reliable because they come out of Ember and are therefore the real source of truth. Accordingly, they should only change in SemVer-compatible ways along with Ember’s public API. We used the same type tests for both, which allowed us to make incremental progress as we finished converting Ember’s internals to TS, and to backport fixes to earlier versions of the hand-authored types.

We also began publishing types from source incrementally, and so recommended that libraries and apps use this as the way of getting both simultaneously:

import 'ember-source/types/preview';
import 'ember-source/types';

Libraries depend on ember-source in devDependencies (and lately also peerDependencies), expecting the host application to provide a specific version for runtime.

The contents of the ember-source/types/preview/index.d.ts file was a hand-authored set of side-effect imports to make the declare modules visible (see e.g. the declaration for @ember/object). The contents for the stable types are similar, though in that case using /// <reference path="./@ember/object/index.d.ts" > instead of import "./@ember/object/index.d.ts";.

Stable types are published from Ember’s own source, using a custom build script which:

This is a very weird way to have to make things visible, and it is possible that it is not playing nicely with how tsc expects things to line up in terms of what is a global or not. It is also possible that it is specifically an interaction around different packages depending on the preview vs. the stable types via their imports, since in some cases both may be present in the module graph? Last but not least, as @dfreeman pointed out in the Ember Discord, it is very possible that there is something specifically about the types for @ember/object or the mixin system and how they are being surfaced which is driving this.

It is not clear to me how or why any specific one of those would be at issue, and as I am no longer actively contributing to Ember or its types, I will not be able to dig in further, but I am happy to answer questions, provide further info, etc. here to help as I can.

Since they are not available in the repo but exist only as part of the build:

The generated index.d.ts for stable types
/**
  *Provides **stable** type definitions for Ember.js.*

  This module is generated automatically as part of Ember's publishing process and
  should never be edited manually.

  To use these type definitions, add this import to any TypeScript file in your
  Ember app or addon:

  ```ts
  import 'ember-source/types';
  import 'ember-source/types/preview';
  ```

  @module
 */

// This works because each of these modules presents `declare module` definition
// of the module and *only* that, so importing this file in turn makes those
// module declarations "visible" automatically throughout a consuming project.
// Combined with use of `typesVersions` (or, in the future, possibly `exports`)
// in `package.json`, this allows users to import the types without knowing the
// exact layout details.
//
// Somewhat annoyingly, every single module in the graph must appear here. For
// now, while we are publishing ambient types, that means we must maintain this
// by hand. When we start emitting types from the source, we will need to do the
// same work, but automatically.

// STATUS NOTE: this does not yet include Ember's full public API, only the
// subset of it for which we have determined the types are ready to stabilize.
//
// Over time, it will come to include *all* of Ember's types, and the matching
// `preview` types will become empty. This is means that someone who writes the
// import we recommend--
//
// ```ts
// import 'ember-source/types';
// import 'ember-source/types/preview';
// ```
//
// --will always get the most up-to-date mix of preview and stable types, with
// no extra effort required.

/// <reference path="./@ember/-internals/bootstrap/index.d.ts" />
/// <reference path="./@ember/-internals/browser-environment/index.d.ts" />
/// <reference path="./@ember/-internals/browser-environment/lib/has-dom.d.ts" />
/// <reference path="./@ember/-internals/container/index.d.ts" />
/// <reference path="./@ember/-internals/container/lib/container.d.ts" />
/// <reference path="./@ember/-internals/container/lib/registry.d.ts" />
/// <reference path="./@ember/-internals/environment/index.d.ts" />
/// <reference path="./@ember/-internals/environment/lib/context.d.ts" />
/// <reference path="./@ember/-internals/environment/lib/env.d.ts" />
/// <reference path="./@ember/-internals/environment/lib/global.d.ts" />
/// <reference path="./@ember/-internals/error-handling/index.d.ts" />
/// <reference path="./@ember/-internals/glimmer/index.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/component-managers/curly.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/component-managers/mount.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/component-managers/outlet.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/component-managers/root.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/component.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/components/abstract-input.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/components/input.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/components/internal.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/components/link-to.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/components/textarea.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/dom.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/environment.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/glimmer-component-docs.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/glimmer-tracking-docs.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helper.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/-disallow-dynamic-resolution.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/-in-element-null-check.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/-normalize-class.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/-resolve.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/-track-array.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/action.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/array.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/component.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/concat.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/each-in.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/fn.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/get.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/hash.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/helper.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/if-unless.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/internal-helper.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/log.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/modifier.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/mut.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/page-title.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/readonly.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/unbound.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/helpers/unique-id.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/modifiers/action.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/modifiers/internal.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/modifiers/on.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/renderer.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/resolver.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/setup-registry.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/syntax/in-element.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/syntax/let.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/syntax/mount.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/syntax/outlet.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/syntax/utils.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/template_registry.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/template.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/templates/empty.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/templates/input.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/templates/link-to.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/templates/outlet.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/templates/root.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/templates/textarea.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/bindings.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/curly-component-state-bucket.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/debug-render-message.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/iterator.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/managers.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/outlet.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/process-args.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/serialization-first-node-helpers.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/string.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/utils/to-bool.d.ts" />
/// <reference path="./@ember/-internals/glimmer/lib/views/outlet.d.ts" />
/// <reference path="./@ember/-internals/meta/index.d.ts" />
/// <reference path="./@ember/-internals/meta/lib/meta.d.ts" />
/// <reference path="./@ember/-internals/metal/index.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/alias.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/array_events.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/array.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/cache.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/cached.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/chain-tags.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/change_event.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/computed_cache.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/computed.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/decorator.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/dependent_keys.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/deprecate_property.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/each_proxy_events.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/events.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/expand_properties.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/get_properties.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/injected_property.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/libraries.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/namespace_search.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/observer.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/path_cache.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/properties.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/property_events.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/property_get.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/property_set.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/set_properties.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/tags.d.ts" />
/// <reference path="./@ember/-internals/metal/lib/tracked.d.ts" />
/// <reference path="./@ember/-internals/owner/index.d.ts" />
/// <reference path="./@ember/-internals/routing/index.d.ts" />
/// <reference path="./@ember/-internals/runtime/index.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/ext/rsvp.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/mixins/-proxy.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/mixins/action_handler.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/mixins/comparable.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/mixins/container_proxy.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/mixins/registry_proxy.d.ts" />
/// <reference path="./@ember/-internals/runtime/lib/mixins/target_action_support.d.ts" />
/// <reference path="./@ember/-internals/string/index.d.ts" />
/// <reference path="./@ember/-internals/utility-types/index.d.ts" />
/// <reference path="./@ember/-internals/utils/index.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/cache.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/dictionary.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/get-debug-name.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/guid.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/intern.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/invoke.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/is_proxy.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/lookup-descriptor.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/mandatory-setter.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/name.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/spec.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/super.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/symbol.d.ts" />
/// <reference path="./@ember/-internals/utils/lib/to-string.d.ts" />
/// <reference path="./@ember/-internals/views/index.d.ts" />
/// <reference path="./@ember/-internals/views/lib/compat/attrs.d.ts" />
/// <reference path="./@ember/-internals/views/lib/compat/fallback-view-registry.d.ts" />
/// <reference path="./@ember/-internals/views/lib/component_lookup.d.ts" />
/// <reference path="./@ember/-internals/views/lib/mixins/action_support.d.ts" />
/// <reference path="./@ember/-internals/views/lib/mixins/child_views_support.d.ts" />
/// <reference path="./@ember/-internals/views/lib/mixins/class_names_support.d.ts" />
/// <reference path="./@ember/-internals/views/lib/mixins/view_state_support.d.ts" />
/// <reference path="./@ember/-internals/views/lib/mixins/view_support.d.ts" />
/// <reference path="./@ember/-internals/views/lib/system/action_manager.d.ts" />
/// <reference path="./@ember/-internals/views/lib/system/event_dispatcher.d.ts" />
/// <reference path="./@ember/-internals/views/lib/system/utils.d.ts" />
/// <reference path="./@ember/-internals/views/lib/views/core_view.d.ts" />
/// <reference path="./@ember/-internals/views/lib/views/states.d.ts" />
/// <reference path="./@ember/application/index.d.ts" />
/// <reference path="./@ember/application/instance.d.ts" />
/// <reference path="./@ember/application/lib/lazy_load.d.ts" />
/// <reference path="./@ember/application/namespace.d.ts" />
/// <reference path="./@ember/array/-internals.d.ts" />
/// <reference path="./@ember/array/index.d.ts" />
/// <reference path="./@ember/array/lib/make-array.d.ts" />
/// <reference path="./@ember/array/mutable.d.ts" />
/// <reference path="./@ember/array/proxy.d.ts" />
/// <reference path="./@ember/canary-features/index.d.ts" />
/// <reference path="./@ember/component/helper.d.ts" />
/// <reference path="./@ember/component/index.d.ts" />
/// <reference path="./@ember/component/template-only.d.ts" />
/// <reference path="./@ember/controller/index.d.ts" />
/// <reference path="./@ember/controller/owner-ext.d.ts" />
/// <reference path="./@ember/debug/container-debug-adapter.d.ts" />
/// <reference path="./@ember/debug/data-adapter.d.ts" />
/// <reference path="./@ember/debug/index.d.ts" />
/// <reference path="./@ember/debug/lib/capture-render-tree.d.ts" />
/// <reference path="./@ember/debug/lib/deprecate.d.ts" />
/// <reference path="./@ember/debug/lib/handlers.d.ts" />
/// <reference path="./@ember/debug/lib/inspect.d.ts" />
/// <reference path="./@ember/debug/lib/testing.d.ts" />
/// <reference path="./@ember/debug/lib/warn.d.ts" />
/// <reference path="./@ember/deprecated-features/index.d.ts" />
/// <reference path="./@ember/destroyable/index.d.ts" />
/// <reference path="./@ember/engine/index.d.ts" />
/// <reference path="./@ember/engine/instance.d.ts" />
/// <reference path="./@ember/engine/lib/engine-parent.d.ts" />
/// <reference path="./@ember/enumerable/index.d.ts" />
/// <reference path="./@ember/enumerable/mutable.d.ts" />
/// <reference path="./@ember/helper/index.d.ts" />
/// <reference path="./@ember/instrumentation/index.d.ts" />
/// <reference path="./@ember/modifier/index.d.ts" />
/// <reference path="./@ember/object/-internals.d.ts" />
/// <reference path="./@ember/object/compat.d.ts" />
/// <reference path="./@ember/object/computed.d.ts" />
/// <reference path="./@ember/object/core.d.ts" />
/// <reference path="./@ember/object/evented.d.ts" />
/// <reference path="./@ember/object/events.d.ts" />
/// <reference path="./@ember/object/index.d.ts" />
/// <reference path="./@ember/object/internals.d.ts" />
/// <reference path="./@ember/object/lib/computed/computed_macros.d.ts" />
/// <reference path="./@ember/object/lib/computed/reduce_computed_macros.d.ts" />
/// <reference path="./@ember/object/mixin.d.ts" />
/// <reference path="./@ember/object/observable.d.ts" />
/// <reference path="./@ember/object/observers.d.ts" />
/// <reference path="./@ember/object/promise-proxy-mixin.d.ts" />
/// <reference path="./@ember/object/proxy.d.ts" />
/// <reference path="./@ember/owner/index.d.ts" />
/// <reference path="./@ember/renderer/index.d.ts" />
/// <reference path="./@ember/routing/-internals.d.ts" />
/// <reference path="./@ember/routing/hash-location.d.ts" />
/// <reference path="./@ember/routing/history-location.d.ts" />
/// <reference path="./@ember/routing/index.d.ts" />
/// <reference path="./@ember/routing/lib/cache.d.ts" />
/// <reference path="./@ember/routing/lib/controller_for.d.ts" />
/// <reference path="./@ember/routing/lib/dsl.d.ts" />
/// <reference path="./@ember/routing/lib/engines.d.ts" />
/// <reference path="./@ember/routing/lib/generate_controller.d.ts" />
/// <reference path="./@ember/routing/lib/location-utils.d.ts" />
/// <reference path="./@ember/routing/lib/query_params.d.ts" />
/// <reference path="./@ember/routing/lib/route-info.d.ts" />
/// <reference path="./@ember/routing/lib/router_state.d.ts" />
/// <reference path="./@ember/routing/lib/routing-service.d.ts" />
/// <reference path="./@ember/routing/lib/utils.d.ts" />
/// <reference path="./@ember/routing/location-ext.d.ts" />
/// <reference path="./@ember/routing/location.d.ts" />
/// <reference path="./@ember/routing/none-location.d.ts" />
/// <reference path="./@ember/routing/owner-ext.d.ts" />
/// <reference path="./@ember/routing/route-info.d.ts" />
/// <reference path="./@ember/routing/route.d.ts" />
/// <reference path="./@ember/routing/router-service.d.ts" />
/// <reference path="./@ember/routing/router.d.ts" />
/// <reference path="./@ember/routing/service-ext.d.ts" />
/// <reference path="./@ember/routing/transition.d.ts" />
/// <reference path="./@ember/runloop/-private/backburner.d.ts" />
/// <reference path="./@ember/runloop/index.d.ts" />
/// <reference path="./@ember/service/index.d.ts" />
/// <reference path="./@ember/service/owner-ext.d.ts" />
/// <reference path="./@ember/template-compilation/index.d.ts" />
/// <reference path="./@ember/template-factory/index.d.ts" />
/// <reference path="./@ember/template/index.d.ts" />
/// <reference path="./@ember/test/adapter.d.ts" />
/// <reference path="./@ember/test/index.d.ts" />
/// <reference path="./@ember/utils/index.d.ts" />
/// <reference path="./@ember/utils/lib/compare.d.ts" />
/// <reference path="./@ember/utils/lib/is_blank.d.ts" />
/// <reference path="./@ember/utils/lib/is_empty.d.ts" />
/// <reference path="./@ember/utils/lib/is_none.d.ts" />
/// <reference path="./@ember/utils/lib/is_present.d.ts" />
/// <reference path="./@ember/utils/lib/is-equal.d.ts" />
/// <reference path="./@ember/utils/lib/type-of.d.ts" />
/// <reference path="./@ember/version/index.d.ts" />
/// <reference path="./@glimmer/tracking/index.d.ts" />
/// <reference path="./@glimmer/tracking/primitives/cache.d.ts" />
/// <reference path="./ember-template-compiler/index.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/assert-against-attrs.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/assert-against-named-outlets.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/assert-input-helper-without-block.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/assert-reserved-named-arguments.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/assert-splattribute-expression.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/index.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-action-syntax.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-each-in-into-each.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-each-track-array.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-in-element.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-resolutions.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/transform-wrap-mount-and-outlet.d.ts" />
/// <reference path="./ember-template-compiler/lib/plugins/utils.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/bootstrap.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/calculate-location-display.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/compile-options.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/compile.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/dasherize-component-name.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/initializer.d.ts" />
/// <reference path="./ember-template-compiler/lib/system/precompile.d.ts" />
/// <reference path="./ember-template-compiler/lib/types.d.ts" />
/// <reference path="./ember-testing/index.d.ts" />
/// <reference path="./ember-testing/lib/adapters/adapter.d.ts" />
/// <reference path="./ember-testing/lib/adapters/qunit.d.ts" />
/// <reference path="./ember-testing/lib/ext/application.d.ts" />
/// <reference path="./ember-testing/lib/ext/rsvp.d.ts" />
/// <reference path="./ember-testing/lib/helpers.d.ts" />
/// <reference path="./ember-testing/lib/helpers/and_then.d.ts" />
/// <reference path="./ember-testing/lib/helpers/current_path.d.ts" />
/// <reference path="./ember-testing/lib/helpers/current_route_name.d.ts" />
/// <reference path="./ember-testing/lib/helpers/current_url.d.ts" />
/// <reference path="./ember-testing/lib/helpers/pause_test.d.ts" />
/// <reference path="./ember-testing/lib/helpers/visit.d.ts" />
/// <reference path="./ember-testing/lib/helpers/wait.d.ts" />
/// <reference path="./ember-testing/lib/initializers.d.ts" />
/// <reference path="./ember-testing/lib/setup_for_testing.d.ts" />
/// <reference path="./ember-testing/lib/test.d.ts" />
/// <reference path="./ember-testing/lib/test/adapter.d.ts" />
/// <reference path="./ember-testing/lib/test/helpers.d.ts" />
/// <reference path="./ember-testing/lib/test/on_inject_helpers.d.ts" />
/// <reference path="./ember-testing/lib/test/pending_requests.d.ts" />
/// <reference path="./ember-testing/lib/test/promise.d.ts" />
/// <reference path="./ember-testing/lib/test/run.d.ts" />
/// <reference path="./ember-testing/lib/test/waiters.d.ts" />
/// <reference path="./ember/index.d.ts" />
/// <reference path="./ember/version.d.ts" />
/// <reference path="./loader/lib/index.d.ts" />
/// <reference path="./require.d.ts" />
The emitted and rewritten @ember/object/index.d.ts
declare module '@ember/object' {
  import type { ElementDescriptor, ExtendedMethodDecorator } from '@ember/-internals/metal';
  import type { AnyFn } from '@ember/-internals/utility-types';
  import CoreObject from '@ember/object/core';
  import Observable from '@ember/object/observable';
  export {
    notifyPropertyChange,
    defineProperty,
    get,
    set,
    getProperties,
    setProperties,
    computed,
    trySet,
  } from '@ember/-internals/metal';
  /**
    @module @ember/object
    */
  /**
      `EmberObject` is the main base class for all Ember objects. It is a subclass
      of `CoreObject` with the `Observable` mixin applied. For details,
      see the documentation for each of these.

      @class EmberObject
      @extends CoreObject
      @uses Observable
      @public
    */
  interface EmberObject extends Observable {}
  const EmberObject_base: Readonly<typeof CoreObject> &
    (new (owner?: import('@ember/owner').default | undefined) => CoreObject) &
    import('@ember/object/mixin').default;
  class EmberObject extends EmberObject_base {
    get _debugContainerKey(): false | `${string}:${string}`;
  }
  export default EmberObject;
  export function action(
    target: ElementDescriptor[0],
    key: ElementDescriptor[1],
    desc: ElementDescriptor[2]
  ): PropertyDescriptor;
  export function action(desc: PropertyDescriptor): ExtendedMethodDecorator;
  type ObserverDefinition<T extends AnyFn> = {
    dependentKeys: string[];
    fn: T;
    sync: boolean;
  };
  /**
      Specify a method that observes property changes.

      ```javascript
      import EmberObject from '@ember/object';
      import { observer } from '@ember/object';

      export default EmberObject.extend({
        valueObserver: observer('value', function() {
          // Executes whenever the "value" property changes
        })
      });
      ```

      Also available as `Function.prototype.observes` if prototype extensions are
      enabled.

      @method observer
      @for @ember/object
      @param {String} propertyNames*
      @param {Function} func
      @return func
      @public
      @static
    */
  export function observer<T extends AnyFn>(
    ...args:
      | [propertyName: string, ...additionalPropertyNames: string[], func: T]
      | [ObserverDefinition<T>]
  ): T;
}

There are plenty more; you can poke at the package on npm or clone ember-source, run pnpm install, then pnpm build:types to get the output locally.

Footnotes

  1. There are a bunch of ideas about how to solve this in the future, including “just” actually publishing those packages, using import maps, and other approachs, but for now this is how things are.

@andrewbranch
Copy link
Member

I was under the impression that those triple-slash paths don’t resolve at all because they were ignoring typesVersions, but it turns out they do resolve as long as a version of ember-source is present that actually includes the types/preview folder.

it's private API -- e.g.: not exposed through typesVersions

typesVersions is not the same as exports. It does not block resolution of subpaths not explicitly listed. It could have achieved a blocking effect if it wanted to like this:

  "types": [
    "types/stable"
  ],
  "types/preview": [
    "types/preview"
  ],
+ "types/*": [],
+ "types/preview/*": []

I agree, there is no TypeScript bug here. I opened #56614 to address #56571 (comment). Closing this out.

@NullVoxPopuli
Copy link

NullVoxPopuli commented Jan 10, 2024

Made a tool to help out for my use case
https://github.com/NullVoxPopuli/fix-bad-declaration-output

not a TS bug

I guess it's my opinion 🤷‍♂️ , but anytime a /// reference is generated for a peer dependency, that's a bug.

it is expected that the consumer of your library will provide the types

@NullVoxPopuli
Copy link

NullVoxPopuli commented Feb 1, 2024

Now more generically, https://github.com/NullVoxPopuli/fix-bad-declaration-output will remove all /// <reference, if you want.

And as an inline rollup plugin:

plugins: [
  {
    name: "generate declarations",
    closeBundle: async () => {
       await execaCommand('tsc --declaration', { stdio: 'inherit' });
    }  
  },
  {
    name: 'fix declaration output',
    closeBundle: async () => {
      await fixBadDeclarationOutput(
        `declarations/**/*.d.ts`, 
        ['TypeScript#56571']
      );
    }      
  }
]

@jakebailey
Copy link
Member

As of #57681, TS will no longer synthesize reference directives, nor preserve reference directives unless explicitly annotated with preserve="true". I believe that this should fix this issue and negate the need for plugins to fixup declaration files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants