Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is TypeScript adding .default to a globally defined import?

I have an external library thing.d.ts file with a global definition inside:

declare var thing: ThingStatic;
export default thing;

I reference npm module in my TypeScript:

import thing from 'thing';
...
thing.functionOnThing();

When I transpile the TS (targeting ES6) it looks something like this:

const thing_1 = require("thing");
...
thing_1.default.functionOnThing();

This then throws an error:

Cannot read property 'functionOnThing' of undefined

Why is TypeScript adding .default between thing_1 and functionOnThing()?

There is no property named default on ThingStatic, and no default property on the underlying JS object that the .d.ts file defines.

Why is TypeScript adding the property and how do I stop it?

like image 968
Keith Avatar asked Dec 14 '16 16:12

Keith


2 Answers

This appears to be a bug with global TS definitions and "module": "commonjs" in the tsconfig.json.

You can either use global TS definitions and stitch all your output into a single file, or you can use modules and directly import them.

The error here is due to the require returning the module context, and the name of the default being irrelevant - it always becomes default...

declare var thing: ThingStatic;
export thing; // Explicit export for thing
export default thing; // Default export for thing

Now require will return this context, so with commonjs modules:

import module from 'thing';
var thing = module.default; // From the default export
var alsoThing = module.thing; // From the named export

However, I've found this to be inconsistent, so switched to es6 modules:

import thing from './thing'; // Import default
import { thing } from './thing'; // Import named
const thing = (await import('path/to/thing.js')).default; // Import dynamic 
like image 84
Keith Avatar answered Oct 19 '22 03:10

Keith


import thing from 'thing';

This line of code means "import the default export from the module 'thing' and bind it to the local name thing".

TypeScript does as you requested and accesses the default property of the module object.

What you probably meant to write was

import * as thing from 'thing';
like image 44
Ryan Cavanaugh Avatar answered Oct 19 '22 04:10

Ryan Cavanaugh