本篇首要介绍怎么让你的组件库在Typescript项目中支撑运用,而且还会具体介绍声明文件的效果、运用办法以及怎么编写声明文件. 希望阅览完本篇的内容能够帮助你掌握编写声明文件的技能.

假如你所编写的组件库或者插件,没有增加声明文件的话? T E,那么当它被Typescript项目中引进时,如下图所示:

UI组件库从1到N开发心得-声明文件篇

找不到 owl-ui 模块的声明文件,请尝试执行 npm install @types/owln h c 0 F L 3 +-ui 增加声明文件,或者创立一个包含N i s 9 H X o declarz % . t l !e module 'owl-ui'.d.ts 文件. 编译器为开发者供给了两种解决办法,这两种办法在后面会介绍给咱们,在这之前我简单介绍一下声明文件.

什么是声明文件

根据上面过错提示剖析,声明文件就是为Javascript库供给类型声明,声明文件有必要以 .d.ts 为后缀. 假如在Typescript项目l ^ J中引进第三方库时,TS编译器会检查其声明文件内容,若没有找到则提示过错.

声明文件放在哪

在介绍声明文件怎么编写之前,罗列一般声明文件寄存的办法.

  1. 目录 src/@types/,在 src 目录新建 @types 目录,在其中编写 .d.t. $ w 1 m # t ts 声明文件,声明文件会主动被辨认,能够在此为一些没有声明文件的模块编写自己的声明文件,实际上在 tsconfig.jsoninclude 字段包含的范围内编写 .d.ts,都将被主动辨认;
  2. 与被声明的 js 文件同级目录内,创立相同称号的 .d.ts 文件,这样也会被? } Y w 主动辨认;
  3. 设置 packagt = K v ? ^ de.json 中的 typings 特点值,+ e R % ] z ( 1./index.d.ts. 这样体系会辨认该地址的声明文件. 相同当咱们把自己的js库发布到 npm 上时,依照该办法绑定声明文件;
  4. 同过 npm 模块装置,如 @type/react ,它寄存在 node$ * , Y 6 i u _modules/@types/ 途径下.

一般来讲,TS编译器会解析项目中所有的 .ts 文件,其中也包括 .d.ts 文件,所以假如你在自己的项目中为第三方插件编写声明文件的话,文件放在哪里都会被解析到.

怎么发布声明文件

假如咱们自己实现了一个js库,怎么来写声, 3 A N G ^ S +明文件呢?现在有两种办法用来= [ Z @发布声明文件到 npm 上:

  1. 与你的 npm 包一起绑缚在一起;
  2. 发布到 npm 上的 @types organization

npm包含声明文件

package.json 中,你的需求指定 npm 包的主 js 文件,那么你还需求指定主声明文件. 如下:

{
"name": "+ R S ?owl-ui",
"version":H _ T H = L "0.2= [ $ 8.6",} L q 3 m F
"description": "Ow9 f  . X l ~ ~l UI",
"ma% * 6 E 6 bin": "./lib/owlP L | 8 i W = J k-uir h w $ A m g b.common.js",
"typings": "types/index.d.ts",
}

有的 npm 包设置的 ty[ y ipes 特点,它和 ty5 m Lpings 具有相同含义.. t . ( N ^ g 假如你的 npm 包需求依靠于其他包,需求将依靠放在 depen] x . ` }dencies 中.

发布到@types

@types 下面的包j . { X : S }是从 DefinitelyTyped 里主动发布{ R H c # q –的,经过 types-publisherS r = { % # # 工具. 假如想让你的包发布为@types包,提交一个pull request到 g ` C q ! 3 e x iithub.com/DefinitelyT…. 在这里检查具体信息 contribution guidelines page.

怎么编写声明文件

现在大致s & ] + $ B / H J分为三种类型的类库,分别为大局类库模块类库UMD类库. 接下来,我会带咱们剖析 ts 引进各自类库的用法和差异.

接下来介绍的大部分内容为代码段,能够点击检查源码一起阅览.

引进jquery

jquery 是 UMD 类库,它能够大局引证,一起也能够运用模块化办法引证.

import $ from 'jquery'
// Error: Try `npm install @types/jquery` if it exists or add a new declaration (.d.ts) file containing `declare module 'jquery';`

ts 文件中引进 js 文件时,会提示上述过错,原因在于缺少声明文件.

咱们K 9 N Q z t ; ] +在运用非 ts 编写的类库时,有必要为这个类^ l * z t 0 z [ t库编写一个声明文件,对外暴露它的 API,有时候这些类库的声明文件是独自供给的,需求额外装置.j V t 8 8 & 上述比如中就提示需求装置 @types/jquery 插件.

npm inst^ F K 8 #all @types/jquery -D

装置完之后,就能够正常在 ts 文件中运用 jquery 了.

  1. 可在 http://microsoft.github.io/TypeSearch/ 中查询类库是否有声明文件
  2. 可在 http://definitelytyped.org/ 中了解怎么发布声明文件

大局类库

编写 js 文件,如下所示:Q a E F

function gloB ^ ; s V H I |balLib (options) {
coB k * q k y Znsole.log(optw I 2ions)
}
globalLib.version = '1.0.0'
globalLib.doSomething = function () {
cons& ? Zole.log('global lib do something')
}

上述代码y { u L Z . p中,界说了一个函数,为函数增加了两个元素. 接下来咱们用 script 标签引进该文件,让该函数效果在大局.

咱们在 ts 中调用该函数,如下所示:

globalLib({ a: 1 }) // Error: Cannot find name 'globalLib'.

提示未找到该函数.

解决办法为它增加一个声明文件,在同级目录下创立一个同名 d.ts 文件,如下所示:

declare f) ? i _ =unctiX E k .on gloo 3 ;balLib (options: globalLib.Options): void
declare namespace globalLib {
const version: string
functii : s mon doSomething (): void
interfm : ( Wace Options {
[key: string]: any
}
}

界说了一个同名2 z G N = ] =函数和命名空 n o 2 3 p I间,相当于为函数增加了一些默认特点. 函数参数界说了一个接口,参数指定为可索引类型,^ ` k $ = g ~承受任意特点. declare 关键字能够为外部变量供给声明.

这样一个声明文件就界说好了.& m V : , 2 H 7 Z

模块类库

以下为 CommonJS 模块编写的文件:

const version = '1.0.0'
function doSomething () {
console.log('moduleLib do something')
}
function moduleu S z # ` ? 0 h .Lib (options) {
console.log(options)
}t W Q I
moduleLib.version = version
moduleLib.doSomething = doSomething
module.exports = moduleLib

相同咱们将它引进 ts 文件中运用.

import module from './module-lib/index.js'
// Error: Could notb Q E find a declaration file for module './module-lm F m : c Lib/index.js'. M # % / 3 $ a

提示未找到该模块,相同咱们需求为它编写! ] 3 ; W s f p文件声明.

declare function moduleLib (options: Optioni u j r % c A qs): void
interface Options {
[key: string]: any
}
declaY t V q 8 9 p h bre namespace moduleLib {
const version: string
function doSomething(- u r E g [): void
}
export = moduleLib

上述 ts 与刚刚编写E T | – C m ~ t的大局类库声明文件大致相同,唯一的差异这里需求 export 输出.

UMD 类库

(function (root, factory) {
iJ K - C n Kf (typeof define === 'function' && define.amd) {
define(factory)
} else if (typeof modx z 7 A J Yule === 'object' && module.exports) {
module.exports = factory()
} else {
root.umdLib = factory()
}
}(this, function () {
return {
version: '1.0.0',
doSomething () {
console.log('umd libK ; n Y do something')
}
}
}))

相同咱们将它引进 ts 文件中运用,假 v 3 n ^ B # ^如没有声明文件也会提示过错,咱们直接看 ts 声明文件

declare namespace umdLib {
const version: string
funct5 ) p A w L j %ion doSomething (a A L y): void
}
export as namespace umdLib
export = umdLib

咱们u % 声明了G : L d一个命名空间,命名空间内有两个成员 v? T } G _ 4 % N SersiondoSomething,分别对应 umd 中的两个成员.

这里R m , t I @ ;与其他类库不同的是,多增加了一条句子 export as namespace umdLib,假如为 umd 库声明,这条句子必不可少.

umd 相同能够运用大局办法引证.

插件

有时候,咱们想给一个第三方类库增加一些自界说的办法. 以下介绍怎么在模块插件大局插件中增加自界说办法.

模块插件

咱们运用 moment 插件,为它增加一个自界说办法. 关键字 declare modA R A dule.

import m from 'mod 4 m } w } | hment'
declare moduE ! } _le 'moment' {
eR I & 5 D rxport function myFunction (): void
}
m.myFunctionb 9 q = () =o ` H ! * # Z> { console.log('I am a Fn') }

大局插件

在上面咱们有介绍大局类库,咱5 W { B们为它增加一个自界说办法. 关键字 declare global.

declare global {
namespaceJ h - U globalLW ] # 7 fib {
function dA i u L b oAnyting (): void
}
}
glog @ @ p  A ZbalLib.doAnyting = () => {}

UI组y V $ 5 C U * f件库增加声明文件

在项目的根目录创立 types 文件. 目录结构如下:

.
├── component.d.ts
├── iw B | [ndex.d.ts
├── owl-ui.d.ts
└── pacd / a  [ N H vkages
├── button-group.d.ts
├── button.d.ts
├── date-picker.d.ts
├── dialog.d.ts
├── drawer.d.ts
├── input-group.d.ty _ P Q Ws
├── input.d.ts
├── picker.x ] N ) * f 4d.ts
├──8 M e b 4 range.d.ts
├── select-group.d.ts
├── select.d.ts
├── switch.d.n Y E 3ts
├── tabs, J g D k q.d.ts
└── toast.d.ts

component.d.3 L bts 寄存声明组件需求的继承类:

import Vue from 'vue'
export declare class OwlUIComponent extends Vue {
stat_ ! Nic install (vue: typeof Vue): void
}z 9 ^ z
expo1 Z ( @rt declare class OwlUIPopupComponent extends OwlUICompoE a - Y ] / d ^ Pneq , I H e k ! }nt {
visible: boolean
zIndex: number
maskStyle: object
containerStyle:D g # , 2 object
shol m e ` ~ 2w (): any
hide (): any
}

packages 文件夹保存着每个组件的声明文件,如 button.V P ! ` [ Yd.ts

import { OwlUIComp X D c W jonent } from '../component'
export t2 w nype BuY = M z 3 q 0 T yttonType = 'default' | 'dig  * | I # d & Rsabled' | 'light'
export declah Z (  R g o nre class4 = z p OwlButton extends OwlUIComponent {
type: ButtonType
inline: boolean
outline: boolean
btnStyle: object
}

owl-ui.d.ts 整合所有的声明文件0 B 7 c T r Y,逐个输出:

import Vue from 'vue'
import { OwlUIComponent } from H L z ~ Y &'./component'
/**
* component commo` & Z cn definition
*/
export type Component = OwlUIComponent
export function instalc t w N 0l ($ - f A u ! +vue: typeof Vue): void
impG & & K ( p gort { OwlButton } from './packages/button'
impS c ^ q d # Port { OwlButtG P P ` * X _ ) jonGroup } from './packages/button{ = J L G e F e-group'
import { OwlDatePicker } from './packages/date-picker'R  / T 7 A
import { OwlDialog } from './packages/dialog'
import { OwlDrawer } from './packages/drawer'
import { OwlInputGroup } from './packages/input-group'
import { OwlB d e i s h j UInput } from './packages/input'
import { OwlPicker } from './packages/picker'
import { OwlRange } from './packages/range'
import { OwlSelectGroup } from './packages/select-group'
import { OwlSelect } from './packages/s$ R 5 ~ 2 ? Helect'
import { OwlSwitch } from './Y U L o + ( J [ Npackages/switch'
import { OwlTabs } from './packages/tabs a / 8 p I'
import { OwlToast } from './packages/toast'
export class Button extends OwlButton {}
export class ButtonGroupk a @ + m 7 } ; exteV @ M Z ?nds OwlButtonGroup {}9 / : k F 6 a E 
export class DatePicker exb R $ 1tends OwlDa` M S # 0 M OtePicker {}
export class Dialog extE C 3 @ O ? I X =ends OwlDialog {}
export class Drawer extends OU Y k f | e 8 3wlDraww ) Her+ w 1 z  = J w {}
export class InputGroup extends OwlInputGroup {}
export cU D class Input exte= _ U H } Ends OwlInput {}
export clasH ? + R n . j V ns Picker extends OwlPicker {}
export class Range extends Ow5 z 6 j -lRange {}
export class SelectGroup extends OwlSelectGroup {}
export class Select extends OwlSelect {}
export class Switch extends OwlSwitch {}
export class Tabs extends OwlTabs {}
export class Toast extends OwlToast {}
declare module 'vue/types/vue' {
interface Vue {
/** cre) * !  & : Iate Drawer instance */
$drawer(options: object)a z p F  +: Drawer
/** create Dialog instan3 9 V !ce */
$dialog(options0 L C: ob ( a W Y N njed 6 = pct): Dialog
/** create DatePicker instance */
$datePicker(option m = C ( Z * |s: object): DatePicker
/** create Picker instR B 5 Sance */
$picker(options: object): Picker
/** create Toast instance */
$toast(options: object | string): Toast
}
}

index.d.ts 为输入输出文件:

export * from './owl-ui'
import * as OwlUI from './owl-ui'
export default OwlUI

最后在 p p & s . 8 E ~ackage.j$ h e I n )son 中增加 typi X pings: f d e Z"types/index.d.ts".

这样组件库就支Y [ ( q撑在Typescript项目中运用了.

结语

最近 Vue3.0 已经进入 Beta 阶段了,待正式版发布之后,我会持续更新迭代组件库并把开发心得共享给咱们.

相关链接

OwlUI GitHub

Typescript 开发教程