Typescript: Type annotations for default export

Created on 23 Jan 2017  ·  18Comments  ·  Source: microsoft/TypeScript

TypeScript Version: 2.1.1

Code

import * as webpack from 'webpack';
export default: webpack.Configuration {
};

Expected behavior:
No error

Actual behavior:

[ts] Expression expected. error at default:

I couldn't find an issue for this but it's very likely it's a duplicate



Please 👍 on this issue if you want to see this feature in TypeScript and avoid adding "me too" comments. Thank you!

Awaiting More Feedback Suggestion

Most helpful comment

Yes, that's what I do know but I wish I didn't have to.

All 18 comments

Would not this be sufficient?

const config: webpack.Configuration  = { 

}
export default config;

Yes, that's what I do know but I wish I didn't have to.

related to https://github.com/Microsoft/TypeScript/issues/3792. we have tried to keep the module export as simple as possible on the syntax side.

I think it's a little more related to to the following scenario regarding function declarations.

if I want to write a decorator that is verified against the PropertyDecorator type in lib.d.ts, I can't write it easily. I have to use a function expression.

export let Encrypt: PropertyDecorator = function (obj, propName) {
};

which is case of friction whenever I want to actually implement a decorator without making a mistake.

I am trying to use a default export in the following way

readdirSync(join(__dirname, "../controllers/box"))

  .filter(f => f !== "*.spec.ts")
  .forEach(controllerFile => {
    const controllerBaseName = basename(controllerFile, ".js")
    import(`../controllers/box/${controllerBaseName}`).then((controller)=>{
      appRouter.use(
        `/box/${controllerBaseName}`, controller.default(boxServiceAccountClient))
    }).catch(error=>{
      console.log(error)
    })
  }); //end forEach

I get an error:

TypeError: controller.default is not a function at fs_1.readdirSync.filter.forEach.Promise.resolve.then.then.controller (/Users/bbendavi/Documents/cdt-box/dist/server/config/routes.js:16:71) at <anonymous> at process._tickCallback (internal/process/next_tick.js:160:7) at Function.Module.runMain (module.js:703:11) at startup (bootstrap_node.js:193:16) at bootstrap_node.js:617:3

I asked this on SO with a full file examples:
https://stackoverflow.com/questions/48696327/how-to-define-a-module-default-export-type-in-typescript

Would much appreciate your help!

import * as webpack from 'webpack'

export default {
...
} as webpack.Configuration

@IgorGee That's the proper way of doing it IMHO

The problem with

export default ... as X

is that it's a cast, so it purposely loses type safety.

@pelotom As a general matter of fact, you're completely right, I'd avoid putting this in my codebase. For the scope of this thread where this is about webpack configuration, I think we're just fine

@jlouazel leaving aside whether type safety is any less important in a webpack config... the issue is not specific to webpack, it's about annotating the type of the default export in general.

@IgorGee That's forbidden in @typescript-eslint/recommended.

const as = <T>(value: T) => value

export default as<webpack.Configuration>({
    // ...
})

Would love to see this feature for nice succinct code

If you're exporting a function, put it in parenthesis before the as.
e.g.

export default ((req, res) => {
   // Intellisense Enabled on `req` & `res`!
   return 'Hello World!';
}) as RequestHandler;

🚩Edit for downvoters: Typescript does check functions for return type & parameter compatibility when typecasting. Unlike typecasting for object types, functions retain a degree of type safety.

I have the same problem too. Need to type default export instead of cast.

could also use an iife so that the type is at the beginning of the export rather than the end

export default ((): MyType => ({
  k: v
})();

While this gives me type hints inside the function (thanks @mccallofthewild )

export default (({ withIcon, children }) => {
  return <SomeJSX withIcon={withIcon}>{children}</SomeJSX>
}) as React.FC<{withIcon: boolean}>

I would still prefer to have the type declared up front _(not sure about the syntax here though)_

export default: React.FC<{withIcon: boolean}> (({ withIcon, children }) => {
  return <SomeJSX withIcon={withIcon}>{children}</SomeJSX>
})

Maybe export const default :Type = value; export type default = Type; export interface default {} could bring us more uniformity, avoid to introduce a new set of grammars just for default?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dlaberge picture dlaberge  ·  3Comments

blendsdk picture blendsdk  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

siddjain picture siddjain  ·  3Comments

Roam-Cooper picture Roam-Cooper  ·  3Comments