-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Module/interface augmentation doesn't preserve import for declaration emit #56528
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
Comments
The issue here is not project references but how d.ts is emitted. Assigning to @weswigham who knows more about this area to see if this is working as intended or there should be error or import should be preserved and can it even be determined. For repro purposes you just need to build "app" and you will see that: // app/index.ts
import * as ReadonlyTuple from 'fp-ts/ReadonlyTuple';
export const Apply = ReadonlyTuple.getApply({ concat: a => a }); generates following d.ts // app/index.d.ts
export declare const Apply: import("fp-ts/lib/Apply").Apply2C<"ReadonlyTuple", unknown>; Error goes away if the import is preserved. |
We used to have machinery to preserve required augmentations by adding I'm not sure we have a viable remediation since we did #57681. We could add imports, but isn't that basically the same as adding |
@jakebailey thoughts? |
I see .. I forgot about that PR .. but even the. I thought this would preserve the import as needed.. instead of generating .. but given how this type materializes may be not .. |
I also think among users write these imports is better than we generating something but not biased towards either approach |
I guess we didn't think about import elision, yeah. Under ID, the imports are never erased, but obviously there's no way to force it to stay otherwise besides I'm not sure how we can do this properly; the whole point of #57681 was to explicitly not rely on whole program info for preserving imports. That implies that manual intervention could be needed, but TS is clearly removing an import too. |
What I donβt understand is why there was cannot write type or unaccessible type error at least .. is it because augmentation is not considered for writing type .. |
The augmentation is what makes the type instantiation valid to make - otherwise the type is unconstructable. (Basically, the Still dunno what we should do here. Declaration emit is defined as eliding any imports not explicitly referenced by an annotation, and we no longer have logic to add references to augmentations we think you need to make the types in the declaration file work. Is our stance "oh, whoever uses this declaration file should include the augmentation themselves"? |
I'm encountering this issue more frequently after upgrading to TypeScript 5.5. Were there any changes related to this? |
The aforementioned #57681 means that no references are generated, nor preserved unless explicitly annotated to do so. I guess if you didn't test the beta/rc, you might see it as a recent regression, but nothing has been changed on this front since that PR. Of course your issue was filed before that PR, so the old behavior was already buggy (since we couldn't accurately generate references anyway). A workaround is to explicitly write this somewhere: /// <reference types="fp-ts/ReadonlyTuple" preserve="true" /> |
@jakebailey Prior to 5.5, Typescript would include the triple slash reference path to a local // module.d.ts
declare module 'eslint-plugin-react/configs/jsx-runtime.js' {
import type { TSESLint } from '@typescript-eslint/utils';
const _default: TSESLint.FlatConfig.Config;
export default _default;
} // eslint.config.ts
export { default as jsxRuntime } from 'eslint-plugin-react/configs/jsx-runtime.js'; To be exported as /// <reference path="../modules.d.ts" />
export { default as jsxRuntime } from 'eslint-plugin-react/configs/jsx-runtime.js';
declare const _default: import("@typescript-eslint/utils/ts-eslint").FlatConfig.ConfigArray;
export default _default; However, this case breaks after your PR was merged. |
There's just no way to determine intent here without getting it wrong the opposite way around. You could have refactored your code the wrong way and that reference may not have been emitted. You can explicitly write a reference with preserve=true if you intend for that to be included in the program. |
On my observation, with preserve=true, the reference is not preserved in |
I mean to write: /// <reference path="..." preserve="true" /> This is guaranteed to be emitted in declaration files. If not, please do file a separate bug. |
Discovered it was a mistake on my end. I had the reference after my import. It is working for me after hoisting to the top. |
Ah, yeah, they have to go at the very top, and we don't exactly warn about that... |
π Search Terms
π Version & Regression Information
β― Playground Link
No response
π» Code
Full reduced test case (contents inlined below): https://github.com./OliverJAsh/ts-project-references-augmentation-bug
package.json
:app/tsconfig.json
:app/index.ts
:demos/tsconfig.json
:demos/index.ts
:π Actual behavior
A module in the "app" project imports the file
node_modules/fp-ts/lib/ReadonlyTuple.d.ts
. This file uses module and interface augmentation. Excerpt:When I later try to reference the "app" project from another project ("demos") using project references, I get a type error because the module/interface augmentation is not being applied:
π Expected behavior
No error. The module/interface augmentation should be applied in the dependant project when it consumes the type declarations of the referenced project.
Additional information about the issue
I am able to workaround the issue by adding an explicit import of
fp-ts/ReadonlyTuple
indemos/index.ts
.The text was updated successfully, but these errors were encountered: