admin管理员组文章数量:1287621
I have a TypeScript class that's part of an npm package. For maintenance, I broke up the class into multiple classes, and I built up the ultimate exported class through inheritance. I don't think this matters to my question, but I figure it's better to disclose this bit of information. I defined the class in ChildClass.ts
like this:
export default ChildClass extends ParentClass{…}
Tsc has an outDir
of "build."
The package.json
file has a property "main": "build/ChildClass.js"
Using both npm link
and npm pack
and I can deploy the package and consume it with no problem in a TypeScript demo package. However, if I try to use the package in a JavaScript demo,
const ChildClass = require('my-package')
const childClass = new ChildClass()
I get the error
Cannot use 'new' with an expression whose type lacks a call or construct signature.ts(2351)
If I change the new
statement by adding .default
like so:
const childClass = new ChildClass.default()
It works. I figured this out by looking at the piled Javascript. Having to use .default
struck me as an unreasonable thing to expect (the hypothetical) JavaScript consumers of my package to know. I also discovered that if I avoided export default
and just used export
then the package works more predictably, so that's what I did. Now I can use
const {ChildClass} = require('my-package')
const childClass = new ChildClass()
and the similar syntax
import {ChildClass} from 'my-package'
const childClass = new ChildClass()
in typescript.
Still, I would like to know what this magic .default
property is and why I need it.
Also, all other references I found to this error didn't seem relevant to what I was seeing; I thought documenting this might help someone else that runs across a similar error.
I have a TypeScript class that's part of an npm package. For maintenance, I broke up the class into multiple classes, and I built up the ultimate exported class through inheritance. I don't think this matters to my question, but I figure it's better to disclose this bit of information. I defined the class in ChildClass.ts
like this:
export default ChildClass extends ParentClass{…}
Tsc has an outDir
of "build."
The package.json
file has a property "main": "build/ChildClass.js"
Using both npm link
and npm pack
and I can deploy the package and consume it with no problem in a TypeScript demo package. However, if I try to use the package in a JavaScript demo,
const ChildClass = require('my-package')
const childClass = new ChildClass()
I get the error
Cannot use 'new' with an expression whose type lacks a call or construct signature.ts(2351)
If I change the new
statement by adding .default
like so:
const childClass = new ChildClass.default()
It works. I figured this out by looking at the piled Javascript. Having to use .default
struck me as an unreasonable thing to expect (the hypothetical) JavaScript consumers of my package to know. I also discovered that if I avoided export default
and just used export
then the package works more predictably, so that's what I did. Now I can use
const {ChildClass} = require('my-package')
const childClass = new ChildClass()
and the similar syntax
import {ChildClass} from 'my-package'
const childClass = new ChildClass()
in typescript.
Still, I would like to know what this magic .default
property is and why I need it.
Also, all other references I found to this error didn't seem relevant to what I was seeing; I thought documenting this might help someone else that runs across a similar error.
Share Improve this question asked May 1, 2019 at 17:22 TodTod 8,2526 gold badges55 silver badges95 bronze badges 1-
6
Because CommonJS (Node's
require()
andexports
) is not patible with ES6 default exports. The solution to down-pile but still allow ES6 spec pliant module loaders to work is to emit__esModule
on the exported value. Babel does the same thing. IMO just avoid default exports, they aren't very useful and create problems. – Aaron Beall Commented May 1, 2019 at 17:38
1 Answer
Reset to default 13Background:
The ECMAScript Language Specification specified that the exported name of export default
is just "default"
. So you can think about it as an ordinary export named "default"
.
Compiling a ES6 module to CommonJS only has a de facto standard, as the ECMAScript Language Specification never mentioned about it. Currently transpilers (TypeScript and Babel) just put all exports to module.exports
, where default export bees not special anymore.
Only when the consumers also understand the above "standard" (e.g. TypeScript, Babel and Webpack), they will transform import ChildClass from 'my-package
statements to const ChildClass = require('my-package').default
for you. Of course, Node.js deals with CommonJS and ES6 modules separately, and not doing this.
(Actually it's more plicated because Babel mixed import DefaultExport from 'some-package'
and import * as AllExports from 'some-package
, modern module consumers has to try both)
Solutions:
TypeScript has a special syntax export =
to work with tranditional CommonJS consumers (It's not in JavaScript). If you change your export default class ChildClass...
to export = class ChildClass...
, it should work as you expected.
本文标签: Why does using TypeScript class in JavaScript require defaultStack Overflow
版权声明:本文标题:Why does using TypeScript class in JavaScript require `.default`? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741316959a2371969.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论