前陣子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
的童鞋能夠一塊兒來搞,方便本身也方便你們。