前阵子koa2
发布了,一些中间件也增长了对koa2
的支持,这固然是大大的好事了。可是,像我这样喜欢用typescript
+koa2
写node
的人来讲,某个中间件没对应的.d.ts
文件会是件很蛋疼的事。javascript
没人写只能本身来了,写过以后会发现其实很简单,还能对那些中间件有更深刻的了解。下面介绍下怎么找到支持koa2
的中间件以及怎么写对应的.d.ts
文件:java
koa
的中间件能够在koa
的wiki上看到,里面列出了哪些中间件支持koa2
,咱们直接在上面找就好了。node
为了方便,我写了个命令行工具koa2-middlewares来查看这些中间件(固然是用typescript
写的啦)。全局安装后,经过命令行koams list
能够查看全部的koa2
中间件,koams list -i
会过滤掉已经有.d.ts
文件的中间件。具体用法参见该工具的README。git
知道有哪些koa2
中间件了就能够挑一个开始写了。以koa-compress
为例:github
经过koams open koa-compress
命令打开koa-compress
的github主页,切到v2.x
分支,能够看到它的用法以下:typescript
var compress = require('koa-compress') var Koa = require('koa') var app = new Koa() app.use(compress({ filter: function (content_type) { return /text/i.test(content_type) }, threshold: 2048, flush: require('zlib').Z_SYNC_FLUSH }))
从用法上看知道koa-compress
这个模块导出的是一个函数,接受一个options
参数,options
有三个属性,因此单从readme
上的代码示例来看,koa-compress.d.ts
的架子就是这样的:npm
/// <reference path="../node/node.d.ts" /> /// <reference path="../koa/koa.d.ts" /> declare module "koa-compress" { import * as Koa from "koa"; function compress(options: { filter: (content_type: string) => boolean; threshold: number; flush:number; }) export = compress; }
咱们再看下koa-compress
的源码:json
'use strict'; /** * Module dependencies. */ var compressible = require('compressible') var isJSON = require('koa-is-json') var status = require('statuses') var Stream = require('stream') var bytes = require('bytes') var zlib = require('zlib') /** * Encoding methods supported. */ var encodingMethods = { gzip: zlib.createGzip, deflate: zlib.createDeflate } /** * Compress middleware. * * @param {Object} [options] * @return {Function} * @api public */ module.exports = (options) => { options = options || {} var filter = options.filter || compressible var threshold = !options.threshold ? 1024 : typeof options.threshold === 'number' ? options.threshold : typeof options.threshold === 'string' ? bytes(options.threshold) : 1024 return function compress(ctx, next) { ctx.vary('Accept-Encoding') return next().then(() => { var body = ctx.body if (!body) return if (ctx.compress === false) return if (ctx.request.method === 'HEAD') return if (status.empty[ctx.response.status]) return if (ctx.response.get('Content-Encoding')) return // forced compression or implied if (!(ctx.compress === true || filter(ctx.response.type))) return // identity var encoding = ctx.acceptsEncodings('gzip', 'deflate', 'identity') if (!encoding) ctx.throw(406, 'supported encodings: gzip, deflate, identity') if (encoding === 'identity') return // json if (isJSON(body)) body = ctx.body = JSON.stringify(body) // threshold if (threshold && ctx.response.length < threshold) return ctx.set('Content-Encoding', encoding) ctx.res.removeHeader('Content-Length') var stream = ctx.body = encodingMethods[encoding](options) if (body instanceof Stream) { body.pipe(stream) } else { stream.end(body) } }); }; }
代码一共就76行,经过源码咱们能够得出如下结论:api
options
为非必须参数app
options.filter
和options.threshold
都为非必须属性
options
参数最后传给了zlib
模块的方法,因此这个options
是继承于zlib.ZlibOptions
的
koa-compress
导出的函数执行后返回一个函数,这个函数是能够做为koa
实例的use
方法的参数
因此往koa-compress.d.ts
中填内容后会是下面这个样子:
/// <reference path="../node/node.d.ts" /> /// <reference path="../koa/koa.d.ts" /> declare module "koa-compress" { import * as Koa from "koa"; import * as zlib from "zlib"; interface ICompressOptions extends zlib.ZlibOptions { filter?: (content_type: string) => boolean; threshold?: number } function compress(options?: ICompressOptions): { (ctx: Koa.Context, next?: () => any): any }; export = compress; }
到这里koa-compress.d.ts
基本就算是写好了,再加点注释什么的就能够用得很爽了,最终版本能够看下koa-compress.d.ts。
写一个.d.ts
文件就是这么简单,写完咱们还要发布出去给别人用。具体步骤以下:
fork
DefinitelyTyped这个仓库到你的github
在本身fork
过来的DefinitelyTyped
添加对应中间件目录
目录里放对应.d.ts
文件和-tests.ts
文件。
提交代码,发起pull request
,等待合并。
编写和发布一个.d.ts
文件就是这么简单。目前我已经添加了koa-router
、koa-static
、koa-bodyparser
、koa-favicon
。
喜欢typescript
+koa2
的童鞋能够一块儿来搞,方便本身也方便你们。