Skip to content

Different Declaration output for same code from js and ts fileΒ #51622

Closed

Description

@daKmoR

Bug Report

πŸ”Ž Search Terms

  • declaration import rewrite
  • declaration import change

πŸ•— Version & Regression Information

  • Probably has always been like that (verified it in 4.9, 4.8, 4.7)

⏯ Playground Link

Sadly not possible as it's about importing of "nested" dependencies.

So I created a reproduction repository

  1. Clone https://github.com/daKmoR/tsbug-declaration-output
  2. Run npm install
  3. Run npm run types
  4. Inspect the output in dist-types

πŸ’» Code

When creating types from a ts source file it keeps the import pathes as is. (which is expected)

πŸ‘‰ Source: src/ElementA.ts

import { LitElement } from "lit";
export class ElementA extends LitElement {}

πŸ‘‰ Output: dist-types/src/ElementA.d.ts

import { LitElement } from "lit";
export declare class ElementA extends LitElement {}

When creating types from "the exact same file" but as a js it changes the import pathes by "resolving" them.

πŸ‘‰ Source: src/ElementB.js

import { LitElement } from "lit";
export class ElementB extends LitElement {}

πŸ™ Actual behavior

πŸ‘‰ Output: dist-types/src/ElementB.d.ts

export class ElementB extends LitElement {}
import { LitElement } from "lit-element/lit-element.js";

πŸ™‚ Expected behavior

export class ElementB extends LitElement {}
import { LitElement } from "lit";

Consequences

Because of the miss match between the "location" of LitElement TS believes those are different LitElement types.

Activity

  1. RyanCavanaugh commented on Nov 30, 2022

    @RyanCavanaugh
    Member

    I think I understand why this is happening, but it seems super undesirable.

  2. fatcerberus commented on Dec 4, 2022

    @fatcerberus

    Why is TS changing the import specifier? That should never happen.

  3. daKmoR commented on Dec 7, 2022

    @daKmoR
    Author

    Is there anything we can do to help? is the reproduction good enough?

    in the meantime we found a "worse" example

    // 
    // input (simplified)
    // 
    import { Constructor } from '@open-wc/dedupe-mixin';
    import { LitElement } from 'lit';
    import { LocalizeMixinHost } from '@lion/ui/types/localize.js';
    
    export declare class IngFieldHost { /* ... */ } 
    
    declare function IngFieldMixinImplementation<T extends Constructor<LitElement>>(
      superclass: T,
    ): T &
      Constructor<IngFieldHost> &
      Pick<typeof IngFieldHost, keyof typeof IngFieldHost> &
      Constructor<LocalizeMixinHost> &
      Pick<typeof LocalizeMixinHost, keyof typeof LocalizeMixinHost> &
      Pick<typeof LitElement, keyof typeof LitElement>;
    export type IngFieldMixin = typeof IngFieldMixinImplementation;  
    
    // 
    // output (simplified)
    // 
    export type IngFieldMixin = import('./types/IngFieldMixinTypes.js').IngFieldMixin;
    export const IngFieldMixin: <
      T extends import('@open-wc/dedupe-mixin').Constructor<import('lit').LitElement>,
    >(
      superclass: T,
    ) => T &
      import('@open-wc/dedupe-mixin').Constructor<
        import('./types/IngFieldMixinTypes.js').IngFieldHost
      > &
      Pick<typeof import('./types/IngFieldMixinTypes.js').IngFieldHost, 'prototype' | 'properties'> &
      import('@open-wc/dedupe-mixin').Constructor<
        import('../../../../node_modules/@lion/ui/dist-types/exports/types/localize.js').LocalizeMixinHost
      > &
      Pick<
        typeof import('../../../../node_modules/@lion/ui/dist-types/exports/types/localize.js').LocalizeMixinHost,
        'prototype' | 'localizeNamespaces' | 'waitForLocalizeNamespaces'
      > &
      Pick<
        typeof import('lit').LitElement,
        | 'prototype'
       // [...]
      >;

    seems potentially related as its resolving a path again... but as it's a monorepo it does go pretty badly πŸ˜…

    e.g. to highlight the issue

    // input
    Constructor<LocalizeMixinHost> 
    
    // expected
    import('@open-wc/dedupe-mixin').Constructor<
      import('@lion/ui/types/localize.js').LocalizeMixinHost
    >
    
    // actual
    import('@open-wc/dedupe-mixin').Constructor<
      import('../../../../node_modules/@lion/ui/dist-types/exports/types/localize.js').LocalizeMixinHost
    >

    we currently "postprocess" the generated *.d.ts files to "fix" it πŸ˜… would be nice if we could get rid of this "workaround" πŸ™

    again if there is anything we can do to prepare this more please let us know πŸ€—

  4. okadurin commented on Jan 21, 2026

    @okadurin

    The issue is still valid and the actual behaviour part is reproducible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions