Search code examples
typescript

How do I declare the type of an imported variable without assigning it to a new variable?


I have a file with a default object export:

export default {
  pages: "./app/client/pages",
  // routes: "./app/server/routes",
  // plugins: [],
} satisfies Config;

In my module, I am importing this file to do things with it:

import zapConfig from "../../../../config/zap.config";

// do things with zapConfig

The problem is that the type of zapConfig is not Config from the import.

How do I type the imported var as Config without assigning it to a new const?

I've tried using declare e.g.:

declare const zapConfig: Config

Which gives me this error:

Import declaration conflicts with local declaration of 'zapConfig'.

I know this works:

const config = zapConfig as Config;
const config = <Config>zapConfig;

I can also use this:

export default {
  pages: "./app/client/pages",
  // routes: "./app/server/routes",
  // plugins: [],
} satisfies Config as Config;

Which looks disgusting, quite frankly.

I'm wondering if this can be done without assigning to a new const.


Solution

  • There is currently no concise way to annotate the type of the default export. There's a longstanding open issue requesting this at microsoft/TypeScript#13626. The discussion in that issue goes over various workarounds and approaches. I don't see anything in there much better than what you've already discovered. I'd say the most correct ways are either to create a new variable like

    const v: Type = ⋯; // annotate
    export default v; // and then export
    

    Or to use satisfies together with a type assertion:

    export default ⋯ satisfies Type as Type;
    

    Note that the satisfies Type as Type construction is redundant but is currently the "standard" way to safely widen an expression. There are less redundant ways to do that, but they involve a helper function like

    const widen = <T,>(t: T): T => t;
    export default widen<Type>(⋯);
    

    and so it's not obviously better unless you use widen a lot.

    So if you want you can give microsoft/TypeScript#13626 a 👍, or subscribe to notifications for updates to it, and maybe someday something better will show up. For now, though, you'll have to just pick a workaround you're not very happy with.