🍳 Generate TypeScript definition files(d.ts) for Egg
A simple tool for creating
d.tsin egg application. Injecting
controller, proxy, service, etc.to definition type of egg ( such as
Context
Applicationetc. ) by Declaration Merging, and making IntelliSense works in both egg-js and egg-ts.
open your application and install.
npm i egg-ts-helper --save-dev
or
yarn add egg-ts-helper --dev
Open your egg application, executing ets by npx
$ npx ets
Watching files by
-wflag.
$ npx ets -w
egg-ts-helperhas build-in in
egg-bin, You can easily to use it by
$ egg-bin dev --dts
or add configuration
egg.declarationsin
package.json
$ ets -hUsage: bin [commands] [options]
Options: -v, --version output the version number -w, --watch Watching files, d.ts would recreated while file changed -c, --cwd [path] Egg application base dir (default: process.cwd) -C, --config [path] Configuration file, The argument can be a file path to a valid JSON/JS configuration file.(default: {cwd}/tshelper -o, --oneForAll [path] Create a d.ts import all types (default: typings/ets.d.ts) -s, --silent Running without output -i, --ignore [dirs] Ignore watchDirs, your can ignore multiple dirs with comma like: -i controller,service -e, --enabled [dirs] Enable watchDirs, your can enable multiple dirs with comma like: -e proxy,other -E, --extra [json] Extra config, the value should be json string -h, --help output usage information
Commands: clean Clean js file while it has the same name ts/tsx file init Init egg-ts-helper in your existing project
| name | type | default | description | | --- | --- | --- | --- | | cwd |
string| process.cwd | egg application base dir | | typings |
string| {cwd}/typings | typings dir | | caseStyle |
string
Function| lower | egg case style(lower,upper,camel) or
(filename) => {return 'YOUR_CASE'}| | silent |
boolean| false | ignore logging | | watch |
boolean| false | watch file change or not, default to
truein
register| | watchOptions |
object| undefined | chokidar options | | autoRemoveJs |
boolean| true | auto remove same name js on startup | | configFile |
string| {cwd}/tshelper.(js|json) | configure file path | | watchDirs |
object| | generator configuration |
You can configure the options above in
./tshelper.js
./tshelper.jsonor
package.json.
In
tshelper.js
// {cwd}/tshelper.jsmodule.exports = { watchDirs: { model: { enabled: true, generator: "function", interfaceHandle: "InstanceType" }, } }
In
tshelper.json
// {cwd}/tshelper.json{ "watchDirs": { "model": { "enabled": true, "generator": "function", "interfaceHandle": "InstanceType" }, } }
In
package.json
// {cwd}/package.json{ "egg": { "framework": "egg", "tsHelper": { "watchDirs": { "model": { "enabled": true, "generator": "function", "interfaceHandle": "InstanceType" } } } } }
or use
dot-prop
// {cwd}/package.json{ "egg": { "framework": "egg", "tsHelper": { "watchDirs.model": { "enabled": true, "generator": "function", "interfaceHandle": "InstanceType" } } } }
Also you can pass options by env ( support since 1.22.0 )
ETS_CWD: cwd
ETS_FRAMEWORK: framework
ETS_TYPINGS: typings
ETS_CASE_STYLE: caseStyle
ETS_AUTO_REMOVE_JS: autoRemoveJs
ETS_THROTTLE: throttle
ETS_WATCH: watch
ETS_SILENT: silent
ETS_CONFIG_FILE: configFile
Support since 1.24.0
egg-ts-helpersupport customLoader configuration of egg. see https://github.com/eggjs/egg/issues/3480
Configure in
config.default.ts
'use strict';import { EggAppConfig, PowerPartial } from 'egg';
export default function(appInfo: EggAppConfig) { const config = {} as PowerPartial;
config.keys = appInfo.name + '123123';
config.customLoader = { model: { directory: 'app/model', inject: 'app', caseStyle: 'upper', }, };
return { ...config as {}, ...bizConfig, }; }
egg-ts-helperwill auto create the d.ts for files under
app/model
// This file is created by [email protected] // Do not modify this file!!!!!!!!!import 'egg'; type AutoInstanceType any ? ReturnType : T> = U extends { new (...args: any[]): any } ? InstanceType : U; import ExportCastle from '../../../app/model/Castle'; import ExportUser from '../../../app/model/User';
declare module 'egg' { interface Application { model: T_custom_model; }
interface T_custom_model { Castle: AutoInstanceType; User: AutoInstanceType; } }
And you can easily to use it in your code.
If you are using
loader.loadToAppor
loader.loadToContextto load the instance, you should use generator config.
Creating
d.tsfor files under
app/model. You should add config
watchDirs.modelin your config file.
// ./tshelper.jsmodule.exports = { watchDirs: { model: { directory: 'app/model', // files directory. // pattern: '*/.(ts|js)', // glob pattern, default is */.(ts|js). it doesn't need to configure normally. // ignore: '', // ignore glob pattern, default to empty. generator: 'class', // generator name, eg: class、auto、function、object interface: 'IModel', // interface name declareTo: 'Context.model', // declare to this interface // watch: true, // whether need to watch files // caseStyle: 'upper', // caseStyle for loader // interfaceHandle: val =>
ReturnType<typeof>
, // interfaceHandle // trigger: ['add', 'unlink'], // recreate d.ts when receive these events, all events: ['add', 'unlink', 'change'] } } }
The configuration can create d.ts as below.
Attention, The type will merge into egg without any pre handling if the generator field is
class, If you dont know how it works, just usinggenerator: 'auto'instead.
import Station from '../../../app/model/station';//Effect of different options
interface
stringinterfaceset toIOther.interface IOther { Station: Station; }It will use random interface if
interfaceis not set.interface T100 { Station: Station; }Attentions: Must set
declareToifinterfaceis not set.generator
stringThe name of generator, available value is
classfunctionobjectauto.generator: 'class'the types created by
classgenerator as belowinterface IModel { Station: Station; }It's suitable for module wrote like this
export default class XXXController extends Controller { }generator: 'function'( Support since1.16.0)the types created by
functiongenerator as belowinterface IModel { Station: ReturnType; // Using ReturnType to get return type of function. }It's suitable for module like this
export default () => { return {}; }generator: 'object'( Support since1.16.0)the types created by
objectgenerator as below.interface IModel { Station: typeof Station; }It's suitable for module like this
export default {}generator: 'auto'( Support since1.19.0)the types created by
autogenerator as below. It will check types automatically.type AutoInstanceType any ? ReturnType : T> = U extends { new (...args: any[]): any } ? InstanceType : U;interface IModel { Station: AutoInstanceType; }
It's suitable for every module in above.
interfaceHandle
function|stringIf you cannot find suitable generator in above, you can config the type by this field.
module.exports = { watchDirs: { model: { ...interfaceHandle: val => `${val} & { [key: string]: any }`, }
} }
The generated typings.
interface IModel { Station: Station & { [key: string]: any }; }The type of
interfaceHandlecan bestring( Support since1.18.0)module.exports = { watchDirs: { model: { ...interfaceHandle: '{{ 0 }} & { [key: string]: any }', }
} }
The generated typings are the same as above.
{{ 0 }}means the first argument in function.caseStyle
function|stringcaseStylecan set tolower、upper、camelor functiondeclareTo
stringDeclaring interface to definition of egg. ( Support since
1.15.0)declareToset toContext.model, and you can get intellisense byctx.model.xxximport Station from '../../../app/model/station';declare module 'egg' { interface Context { model: IModel; }
interface IModel { Station: Station; } }
declareToset toApplication.model.subModel, and you can get intellisense byapp.model.subModel.xxximport Station from '../../../app/model/station';declare module 'egg' { interface Application { model: { subModel: IModel; } }
interface IModel { Station: Station; } }
Defining custom generator
// ./tshelper.js// custom generator function myGenerator(config, baseConfig) { // config.dir dir // config.dtsDir d.ts dir // config.file changed file // config.fileList file list console.info(config); console.info(baseConfig);
// return type can be object or array { dist: string; content: string } | Array // egg-ts-helper will remove dist file when content is undefined. return { dist: 'd.ts file url', content: 'd.ts content' } }
module.exports = { watchDirs: { model: { directory: 'app/model', generator: myGenerator, trigger: ['add', 'unlink'], } } }
or define generator to other js.
// ./my-generator.jsmodule.exports.defaultConfig = { // default watchDir config }
// custom generator module.exports = (config, baseConfig) => { // config.dir dir // config.dtsDir d.ts dir // config.file changed file // config.fileList file list console.info(config); console.info(baseConfig);
// return type can be object or array { dist: string; content: string } | Array // egg-ts-helper will remove dist file when content is undefined. return { dist: 'd.ts file url', content: 'd.ts content' } }
configure in
tshelper.jsorpackage.json// ./tshelper.jsmodule.exports = { watchDirs: { model: { directory: 'app/model', generator: './my-generator', trigger: ['add', 'unlink'], } } }
Demo
egg-ts-helpercan works in bothtsandjsegg project.TS demo: https://github.com/whxaxes/egg-boilerplate-d-ts
JS demo: https://github.com/whxaxes/egg-boilerplate-d-js