eggjs / egg-ts-helper Goto Github PK
View Code? Open in Web Editor NEW🍳 Generate TypeScript definition files(d.ts) for Egg
License: MIT License
🍳 Generate TypeScript definition files(d.ts) for Egg
License: MIT License
Hi!, We're trying to use egg.js in production with mongoose, but we notice a problem about the typing for Mongoose with egg-ts-mongoose
plugin.
Mongoose itself has the typing solution(separate interface declaration or use ts-mongoose
), and the egg-ts-helper
also generated a correct type file of model files(interface IModel
), Awesome!
But when using the model in service by this.ctx.model
, the model type is referred to the egg.Context.model
in egg-ts-mongoose/index.d.ts
(https://github.com/eggjs/egg-mongoose/blob/master/index.d.ts#L28), which type is [key: string]: mongoose.Model<any>
.
So in the service, the model type is Model<any>
, it's very stupid! and the solution also very easy, just override the type of context.model
to IModel
, by edit typing/index.d.ts
as below:
import 'egg';
declare module 'egg' {
// add below lines
interface Context {
model: IModel
}
}
(Edit the typing/model/index.d.ts
should has same result)
I think this job can not be done by egg-mongoose
, because the interface IModel
is a generated file.
I'm using WebStorm 2020.2, but I think the VSCode should has the same problem, because the context.model
type refer to egg-mongoose
seems a correct behavior or maybe I wrong :D
Thanks!
import Home from '......\app\controller\home';
if it contains sub controller,it will generate
import Home from '..\..\..\app\controller\home';
import Posts from '..\..\..\app\controller\posts';
import Sub/index from '..\..\..\app\controller\sub\index';
declare module 'egg' {
interface IController {
home: Home;
posts: Posts;
sub/index: Sub/index;
}
}
which is a syntax error.
Can egg-ts-helper support -linux
argument?
目前 ets clean
只支持清除了由 ts 产生的同名 js 文件,是否考虑把 tsx 产生同名 js 文件也清除呢?
毕竟现在越来越多 同构/SSR 项目了 😄
// This file is created by egg-ts-helper
// Do not modify this file!!!!!!!!!
import 'egg';
import ExportHome = require('../../../app/controller/home');
declare module 'egg' {
interface IController {
home: ExportHome;
}
}
import ExportHome = require('../../../app/controller/home');
这个感觉好怪啊。。 是不是应该用import ExportHome from '../../../app/controller/home';
如下指定 portNumber
时,实际调试时需要 attach 的端口为 portNumber + 1
egg-bin debug --inspect=<portNumber> -r egg-ts-helper/register
export default abstract class Bill extends Service{
}
抽象的Service,会导致 this.service.bill类型为Function,而不是对象。
> egg-bin dev -r 'egg-ts-helper/register'
2018-11-22 17:46:28,246 INFO 82507 [master] node version v8.12.0
2018-11-22 17:46:28,247 INFO 82507 [master] egg version 2.11.2
[egg-ts-helper] /Users/wangpeng/resp/wt-hulk/back-end/typings/app/controller/index.d.ts created
[egg-ts-helper] /Users/wangpeng/resp/wt-hulk/back-end/typings/app/middleware/index.d.ts created
[egg-ts-helper] /Users/wangpeng/resp/wt-hulk/back-end/typings/app/model/index.d.ts created
[egg-ts-helper] /Users/wangpeng/resp/wt-hulk/back-end/typings/config/index.d.ts created
[egg-ts-helper] /Users/wangpeng/resp/wt-hulk/back-end/typings/config/plugin.d.ts created
[egg-ts-helper] /Users/wangpeng/resp/wt-hulk/back-end/typings/app/service/index.d.ts created
2018-11-22 17:46:29,422 INFO 82507 [master] agent_worker#1:82509 started (1171ms)
/Users/wangpeng/resp/wt-hulk/back-end/node_modules/ts-node/src/index.ts:261
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: [egg-core] load file: /Users/wangpeng/resp/wt-hulk/back-end/app/service/TeamService.ts, error: [egg-core] load file: /Users/wangpeng/resp/wt-hulk/back-end/app/service/activityService.ts, error: ⨯ Unable to compile TypeScript:
app/service/activityService.ts(6,22): error TS2348: Value of type 'Model<any>' is not callable. Did you mean to include 'new'?
at createTSError (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/ts-node/src/index.ts:261:12)
at getOutput (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/ts-node/src/index.ts:367:40)
at Object.compile (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/ts-node/src/index.ts:558:11)
at Module.m._compile (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/ts-node/src/index.ts:439:43)
at Module._extensions..js (module.js:664:10)
at Object.require.extensions.(anonymous function) [as .ts] (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/ts-node/src/index.ts:442:12)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Object.loadFile (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/egg-core/lib/utils/index.js:19:19)
at getExports (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/egg-core/lib/loader/file_loader.js:199:23)
at ContextLoader.parse (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/egg-core/lib/loader/file_loader.js:158:25)
at ContextLoader.load (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/egg-core/lib/loader/file_loader.js:67:24)
at AppWorkerLoader.loadToContext (/Users/wangpeng/resp/wt-hulk/back-end/node_modules/egg-core/lib/loader/egg_loader.js:407:28)
[2018-11-22 17:46:33.457] [cfork:master:82507] worker:82516 disconnect (exitedAfterDisconnect: false, state: disconnected, isDead: false, worker.disableRefork: true)
[2018-11-22 17:46:33.457] [cfork:master:82507] don't fork, because worker:82516 will be kill soon
2018-11-22 17:46:33,457 INFO 82507 [master] app_worker#1:82516 disconnect, suicide: false, state: disconnected, current workers: ["1"]
[2018-11-22 17:46:33.458] [cfork:master:82507] worker:82516 exit (code: 1, exitedAfterDisconnect: false, state: dead, isDead: true, isExpected: false, worker.disableRefork: true)
// typings
declare module 'egg' {
interface IModel {
Console: {
CrmImportRecord: ReturnType<typeof ConsoleCrmImportRecord>;
};
Lesschat: {
CrmContact: ReturnType<typeof LesschatCrmContact>;
CrmCustomer: ReturnType<typeof LesschatCrmCustomer>;
Department: ReturnType<typeof LesschatDepartment>;
Tag: ReturnType<typeof LesschatTag>;
Team: ReturnType<typeof LesschatTeam>;
User: ReturnType<typeof LesschatUser>;
};
}
}
when code has some global error, eg: require('noneexist') , egg-ts-helper would swallow the error, make the egg-bin dev just halt. I think it should throw error
chokidar@2 依赖 fsevents 1 版本, 在 node 14 会报错
npm WARN deprecated [email protected]: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
项目tsconfig.json配置如下
{
"extends": "@tsconfig/tsconfig.node.json",
"compilerOptions": {
"module": "CommonJS",
"declaration": true,
},
}
extends里的配置包含了"skipLibCheck": true
,因为extends里的内容没有被加载,从而导致config.default.ts的声明没有被输出到typings/config中。
await this.ctx.model.Orders.findByPk(id);
findByPk会标红,提示找不到该方法
设置git项目到npm package.json 中,方便学习
RT
now i am using version 1.17.1 , when i execute command "ets clean", the error "ets-clean(1) does not exist, try --help " occurred
项目路径为:/Volumes/Macintosh HD/xxxxxx
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module '/Volumes/Macintosh'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
比如项目以feature-base的方式建立了多个模块:
期望可以生成 app.controller.session.main 和 app.controller.student.main 的声明,但由于目录结构是自定义的,实际只能生成 app.controller.session.controller.main 和 app.controller.student.controller.main
希望通过caseStyle的方式可以生成期望的声明
从 egg-watcher 的源码:https://github.com/eggjs/egg-watcher/blob/master/lib/watcher.js#L31 看,可以通过 agent.watcher.watch('{filePath}', (file) => {});
watch 文件变更,想问一下为什么 register 没用这种方式?因为我们也有一个类似的功能需要在文件变更时做一些其他的事情
node version v14.19.0
egg version 2.33.1
现在看生成的d.ts文件还是空的类
import 'egg';
import ExtendResponse = require('../../../app/extend/response');
type ExtendResponseType = typeof ExtendResponse;
declare module 'egg' {
interface Response extends ExtendResponseType { }
}
我试了下这个,发现在 webstorm 中始终无法跳转到 service 下的方法上。在 vs code 里是可用的。想请教下是我姿势不对还是确实和 webstrom 的提示不兼容。
假设在service目录下有一个文件为
service/application.ts
import { Context, Service } from 'egg'
export default class ApplicationService extends Service {
getData () {
return 'hello world'
}
}
自动生成的typing文件如下:
typing/app/service/index.d.ts
import 'egg'; // Make sure ts to import egg declaration at first
import Application from '../../../app/service/application';
declare module 'egg' {
interface IService {
application: Application; // 这里的Application会被只想到egg下的Application,不能正确解析
}
}
如果此时在controller中访问 ctx.service.application.getData()
,getData
这个方法并没有真正的被解析道ctx.service.application
对象上。
个人的建议能否在生成的时候添加prefix配置,使得生成的typing文件如下
typing/app/service/index.d.ts
import 'egg'; // Make sure ts to import egg declaration at first
import PrefixApplication from '../../../app/service/application';
declare module 'egg' {
interface IService {
application: PrefixApplication; // 生成的prefix
}
}
这样处理完之后就可以正确解析了。
添加 egg-socket.io 和 egg-graphql 支持,不然手写太蛋疼了
// This file is created by [email protected]
// Do not modify this file!!!!!!!!!
老版本不含版本号,所以不同机器与环境下这里的comment都是一致的。
新版本发现带上版本号,导致使用新老版本的开发者之间一直提示代码差异
诸如Sequelize、Mongoose等框架会使用 app/model
目录,建议开放对其他目录监听的支持
就算不做自动添加d.ts
当做监听编译也好,现在egg typescript下,sequelize是完全不可用的
场景是这样的:
我们内部封装的插件内使用到了 Egg 的 FileLoader
,其中 caseStyle
参数传入的是一个 function
用于自定义挂载的节点名。
翻阅 egg-ts-helper
的源码,发现并不支持函数传入。
不知是否有支持的考虑,可以提 PR
egg/index.d.ts 中声明如下:
export interface IService extends PlainObject { }
export class Service extends BaseContextClass { }
但是 egg-ts-helper 中却声明了名为 Service 的接口
导致以下代码无法通过类型检查
import { Service } from '@ali/my-egg';
class MyService extends Service {}
异常信息:
error TS2689: Cannot extend an interface 'Service'. Did you mean 'implements'?
It will be more official, and the user can find the package more conveniently.
目前 @types/sequelize
中类型定义落后官方新版 API 非常多。其替代仓库 types/sequelize 提供了更加准确的类型定义。
目前我的项目中使用的是后者的定义,而 egg-sequelize 目前使用的是前者的定义,两者互不兼容,而 helper 默认直接扩展 Sequelize,导致现有代码类型冲突。
目前我的代码中是这样扩展 Sequelize 的
// typings/index.d.ts
// node_modules 中安装的是后者的类型定义
import { Sequelize } from 'sequelize';
declare module 'egg' {
// 重新声明一个继承于 Sequelize 的接口,用于添加 Model
interface MixSequelize extends Sequelize { }
// 由于 egg-sequlize 中声明的 model 类型使用的是前者的定义,两者不兼容
// 如果直接使用 Sequelize 类型会导致类型定义冲突
// 所以将 app.model 的类型重定义为 MixSequelize,覆盖原定义
export interface Application {
model: MixSequelize;
}
export interface Context {
model: MixSequelize;
}
}
// app/model/my-model.ts
import { Model } from 'sequelize';
export class MyModel extends Model { }
export default app => {
MyModel.init({});
return MyModel;
}
declare module 'egg' {
// 在此处扩展 MixSequelize 属性
interface MixSequelize {
MyModel: typeof MyModel;
}
}
之前一直工作的很好,直到今天自动生成了 model.d.ts
打印如下内容:
❯ npx ets
[egg-ts-helper] WARN loader.loadPlugin() error: /Users/myself/Develops/mock/config/plugin.ts:1
import path from 'path';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1029:16)
at Module._compile (internal/modules/cjs/loader.js:1078:27)
at Module.m._compile (/Users/myself/Develops/mock/node_modules/ts-node/src/index.ts:1618:23)
at Module._extensions..js (internal/modules/cjs/loader.js:1143:10)
at Object.require.extensions.<computed> [as .ts] (/Users/myself/Develops/mock/node_modules/ts-node/src/index.ts:1621:12)
at Module.load (internal/modules/cjs/loader.js:979:32)
at Function.Module._load (internal/modules/cjs/loader.js:819:12)
at Module.require (internal/modules/cjs/loader.js:1003:19)
at require (internal/modules/cjs/helpers.js:107:18)
at loadFile (/Users/myself/Develops/mock/node_modules/egg-core/lib/utils/index.js:27:19), cwd: /Users/myself/Develops/mock, framework: egg
[egg-ts-helper] create typings/app/controller/index.d.ts (3ms)
[egg-ts-helper] create typings/app/middleware/index.d.ts (2ms)
[egg-ts-helper] create typings/config/index.d.ts (23ms)
[egg-ts-helper] create typings/app/service/index.d.ts (2ms)
[egg-ts-helper] create typings/app/index.d.ts (1ms)
我的系统环境是:
我的项目是中途换到ts的,所以项目里混合了js和ts,更新到新版本后,对于js导出的controller或service或用import xx = require(xxx)
引入,但我的js代码里也统一使用了export default,导致获取引入的对象是一个{ default: [controller|service] }
报错了,这个有办法配置解决吗?
tsconfig.json中配置如下:
{
compilerOptions : {
"baseUrl": ".",
"paths": {
"@/*": [ "app/*" ]
},
}
}
然后我在代码中引用模块使用的方式为:
import {ErrCode} from "@/library/common/errcode";
编译时报错:
[egg-core] load file: E:\SourceCode\QinggerSource\MicroService\ali-express-sms-service\app\controller\baseController.ts, error: Cannot find module '@/library/common/errcode'
egg-ts-helper 自动生成的 jsconfig.json格式检测错误:
“File 'f:/myWebSpace/egg-template/node_modules/socks/typings' not found.”
"egg": "^2.15.1",
"egg-bin": "^4.11.0",
"egg-ci": "^1.11.0",
"egg-mock": "^3.21.0",
"eslint": "^5.13.0",
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.