-
Notifications
You must be signed in to change notification settings - Fork 102
Open
Description
问题
我有一个组件按照官方文档使用SFC+ts+vue-class-component
写的:
import { APlayer } from "@moefe/vue-aplayer";
// ... 组件声明
@Ref()
player!: APlayer;
audio: APlayer.Audio = {
// ...
};
编译能通过,但是编辑器audio类型检查(以及编译类型检查)报错
Cannot find namespace 'APlayer'
检查发现APlayer.Audio
的类型定义在'@moefe/vue-aplayer/types/aplayer'
,我import了一下,类型检查通过,但是cli编译报错
This dependency was not found:
@moefe/vue-aplayer/types/aplayer in ...
对于webpack来说,从一个非入口.d.ts
文件import任何内容都是无法编译的,因为根本不存在对应的模块,我引用ElementUI的时候就吃了很多亏。
相反,从入口声明文件import 接口是允许的,因为入口声明文件对应的模块存在,而进入babel-loader的时候,会跳过所有的类型检查,无视接口导入。
项目内的临时解决方案
在不改动npm包源码的情况下,要让代码工作通常只有3个方法:
- 使用jsdoc注释并包含ts专属的import,但对ts无效
- 在
tsconfig.json
中手动引入类型定义,下面这些都是这个问题
{
"compilerOptions": {
"types": [
"webpack-env",
"@types/jest",
"vue-tsx-support/enable-check",
"vue-tsx-support/options/allow-unknown-props",
"@moefe/vue-aplayer/types/aplayer"
]
}
- 定义一个新的type,从原始导入计算出正确的类型。同样由于是类型定义,没有使用import,不会被webpack处理。
type __APlayer_Type_Import__ = typeof import("@moefe/vue-aplayer/types/aplayer");
由于aplayer.d.ts
用了declare global
的方式,只需要包含类型引入,不必关心实际导入的类型。
建议
为了让这些类型定义可以正确的使用,建议修改声明文件的编写方式,可以参考vue的写法。
我个人推荐的使用方式是:
- 在
aplayer.d.ts
去除declare global 以及namespace,直接导出所有接口 - 在
index.d.ts
中导入所有接口,并重新export,这样这些接口可以单独import - 同时为了照顾原有代码,定义
namespace APlayer
包含这些接口,然后导出namespace,此时导出APlayer
既是class也是namespace
import * as APlayerType from "./aplayer";
export * from "./aplayer";
export as namespace APlayer;
export class APlayer extends Vue.Component<APlayerType.Options, APlayerType.Events> {
// ...
}
- 使用(经过测试通过)
import { APlayer, Audio, LrcType } from "@moefe/vue-aplayer";
player!: APlayer; // OK
audio1: APlayer.Audio = { }; // 可以按原来的方法用
audio2: Audio = { }; // 也可以直接用
稍后提交pr
Metadata
Metadata
Assignees
Labels
No labels