导入其他 TypeScript 模块

3

我正在尝试从node_modules中的typescript文件进行导入。该文件未经转译,并使用typescript语法:

user.ts:

export const getUserFromToken = (token: string) => {
  return axios.get('/user', {
    headers: { authorization: `Bearer ${token}` }
  }).then(({ data }) => data)
}

我这样导入:import { getUserFromToken } from 'common-files/api/user',其中common-files是在package.json中注册的模块。
尝试编译时,我收到以下错误提示:
../commons/api/user.ts
Module parse failed: C:\Users\xxxx\Desktop\xxxx\commons\api\user.ts 
Unexpected token (9:38)
You may need an appropriate loader to handle this file type.
| export const getUserFromToken = (token: string) => {
|   return axios.get('/user', {
|     headers: { authorization: `Bearer ${token}` }

这让我相信它没有编译ts文件,因为当我移除字符串类型时,它变成了一个有效的es6文件,并且可以正确启动。
在我的tsconfig.json文件中,我有:
"exclude": [
  "node_modules",
  "build",
  "scripts",
  "acceptance-tests",
  "webpack",
  "jest",
  "src/setupTests.ts"
]

我在思考,也许可以排除node_modules,除了那个名为common-files的包,但不知道如何做到。有没有好的方法可以实现我想要的结果呢?


1
我假设这是一个自定义模块?模块需要完成自己的编译并发布 .js 和 .d.ts 文件。你在这里看到的问题确实是 tsc 没有编译文件(因为它不知道应该把它放在哪里),然后 webpack (?) 由于某种原因将导入解析到了 .ts 文件... - Adrian Leonhard
1
如果你使用 ts-node 而不是 node,你可以在不转译的情况下包含 ts 文件。 - lilezek
2个回答

2

@ShaunLuttin回答了这个问题的一般情况。我的问题是因为我使用create-react-app与typescript脚本,他们的webpack配置不允许从模块中使用原始typescript文件。我决定转译所有文件,并生成一个可以用作模块的构建。它起作用了,但是当处理前端项目时,我必须确保不包含仅在node环境下工作的任何内容。


1

旁注:您正在尝试做的是非常不寻常的。通常,Node 项目会安装已经被转译为 JavaScript 的模块。

话虽如此,这里有一个适合您的设置和GitHub 上的演示。由于您的用例是非传统的,解决方案比较复杂。

目录结构 > 注意 common-files 目录中的 index.ts 文件。它有两个作用。首先,它将列出我们想要 TypeScript 转译的文件。其次,一旦它被转译,index.js 文件将告诉 Node,common-files 文件夹是一个模块。 Node 关于文件夹作为模块的文档 解释了 Node 如何解析模块。

node_modules    
  common-files
    api
      user.ts
    index.ts     <---- This file has two primary purposes.
index.ts        
package.json    
tsconfig.json   

node_modules/common-files/api/user.ts > 这个文件包含一个声明,我们希望在你的应用程序中使用。

export const getUserFromToken = (token: string) => {
    console.log("Getting the user for token " + token);
}

根据NodeJS的默认设置,node_modules/common-files/index.ts文件是您的common-files模块的主要文件。如前所述,主文件还将导入我们想要转译的每个声明。
import "./api/user";

index.ts > 这个文件代表着你正在构建的应用程序。我们可以导入common-files模块导出的任何已编译声明。

import { getUserFromToken } from "common-files/api/user";

getUserFromToken("some-token");

package.json > 注意,您的应用程序的节点包文件中没有什么特别之处。也就是说,如果您使用npm install安装了common-files包,则我们将在dependencies部分列出common-files

{
  "dependencies": { }, 
  "devDependencies": {
    "typescript": "^2.4.2"
  }
}

tsconfig.json > TypeScript配置有些复杂,因为您的common-files模块需要进行转译,而我们希望排除node_modules中的其他所有内容。 tsconfig文档详细介绍了文件、包含和排除之间的交互作用。

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs"
  },
  "files": [
    "node_modules/common-files/index.ts"
  ],
  "include": [
    "**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

上述设置的控制台输出如下:
> .\node_modules\.bin\tsc
> node index.js
Getting the user for token some-token

你是说这种做法不太常规,也许有一种常规的方法可以实现我想要的?我想让两个独立的包共享一些代码,所以我把那些代码移到了npm包中,并在每个项目中本地导入它们。这就出现了一个问题,当在其他包中使用时,npm包没有被转译。 - Vincas Stonys
@VincasStonys 答案的旁白陈述了传统的方法。 - Shaun Luttin
@VincasStonys 很抱歉听到这些步骤对您没有用。您是否能够使用我在GitHub上发布的演示?如果是,那个演示对您有用吗? - Shaun Luttin
1
我已经单独使用了您的示例,并且它有效。我设置了一个新的项目,将使用您的建议,并且它也有效... 但是,在相关的项目中,我使用了带有TypeScript配置的create-react-app,来自这里:https://github.com/wmonk/create-react-app-typescript。看起来他们的webpack配置不会转译node_modules,并且他们在webpack配置文件的注释中明确说明必须事先转译包... 我想我将会弹出并调整该项目,因为转译和编写通用包的类型定义似乎很麻烦。 - Vincas Stonys
1
如果我是你,我会撰写第二个StackOverflow问题。不要更改第一个问题;相反,写一个使用你从第一个问题中学到的知识的第二个问题。第二个问题可能会引导你更接近你的目标。 - Shaun Luttin
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接