對於爲第三方模塊/庫寫聲明文件以前,咱們須要知道第三方模塊/庫,是否須要聲明文件,或者是否已有聲明文件。html
--declaration
配置選項來生成; 能夠在命令行中添加 --declaration(簡寫 -d),或者在 tsconfig.json 中添加 declaration:true 選項1. 與該 npm 包綁定在一塊兒,能夠經過查找該庫的`package.json`中的`types`屬性
2. 發佈到 @types 裏,能夠在官方提供的第三方聲明文件庫(http://microsoft.github.io/TypeSearch/)中查找
複製代碼
如若上面的狀況都不符合, 則須要咱們本身手寫聲明文件vue
在書寫聲明文件以前,咱們須要瞭解Typescript 相關知識, 能夠自行查閱官方文檔,或閱讀我前一篇TypeScript 總結篇, 固然有須要寫聲明文件的須要,確定是對Typescript有了解,可能已有相關實踐,在此只是友情提示。 除此以外還須要對TS中的模塊化有所瞭解,以下git
主要是解決加載依賴關係的,側重代碼的複用。跟文件綁定在一塊兒,一個文件就是一個module,模塊寫法和ES6同樣。github
同Java的包、.Net的命名空間同樣,TypeScript的命名空間將代碼包裹起來,經過export關鍵字對外暴露須要在外部訪問的對象。 主要用於組織代碼,解決命名衝突,會在全局生成一個對象,定義在namespace內部的都要經過這個對象的屬性訪問。ajax
隨着 ES6 的普遍應用,現已經不建議使用 ts 中的 namespace,而推薦使用 ES6 模塊化方案,但在聲明文件中,declare namespace 仍是比較經常使用的。typescript
namespace聲明能夠用來添加新類型,值和命名空間,只要不出現衝突。
與class/namespace等類型合併npm
///<reference types=「UMDModuleName/globalName」 />
ts 早期模塊化的標籤, 用來導入依賴, ES6普遍使用後, 在編寫TS文件中不推薦使用, 除了如下的場景使用///
, 其餘場景使用 import
代替
在聲明文件中, 依賴全局庫或被全局庫依賴, 具體:json
注意
: 三斜線指令必須放在文件的最頂端,三斜線指令的前面只容許出現單行或多行註釋。數組
模塊或一個 UMD 庫依賴於一個 UMD 庫,使用 import * as 語句引入模塊bash
第三方庫使用場景:
<script>
標籤引入第三方庫,注入全局變量import foo from 'foo'
導入,符合ES6
模塊規範<script>
標籤引入,又能夠經過 import
導入import
導入後,能夠改變另外一個模塊的結構<script>
標籤引入後,改變一個全局變量的結構。好比爲String.prototype
新增了一個方法import
導入後,能夠改變一個全局變量的結構類庫分爲三類:全局類庫、模塊類庫、UMD類庫
經過<script>
標籤引入第三方庫, 注入全局變量 全局變量的聲明文件主要有如下幾種語法:
主要看下 declare namespace
// src/jQuery.d.ts
declare namespace jQuery {
const version: number;
class Event {
blur(eventType: EventType): void
}
enum EventType {
CustomClick
}
interface AjaxSettings {
method?: 'GET' | 'POST'
data?: any;
}
function ajax(url: string, settings?: AjaxSettings): void;
}
複製代碼
declare namespace
聲明全局命名空間,去掉declare namespace
, 即從中提出代碼,再在前面加上declare
便是聲明各全局變量
// 聲明全局函數,其餘同理
declare function ajax(url: string, settings?: any): void;
複製代碼
在npm包中, 經過import foo from 'foo'
導入npm包。npm 包的聲明文件主要有如下幾種語法:
export // 導出變量
export namespace // 導出(含有子屬性的)對象
export default // ES6 默認導出
export = // commonjs 導出模塊
複製代碼
在 npm 包的聲明文件中,使用 declare 再也不會聲明一個全局變量,而只會在當前文件中聲明一個局部變量。只有在聲明文件中使用 export 導出,而後在使用方 import 導入後,纔會應用到這些類型聲明。
與非聲明文件寫法相似, 使用import導入, ES6模塊語法
使用 declare 先聲明多個變量,最後再用 export 一次性導出
注: interface 前是不須要 declare 的
注意,只有 function、class 和 interface 能夠直接默認導出,其餘的變量須要先定義出來,再默認導出
用來導出一個擁有子屬性的對象
在 commonjs 規範中, 使用exports/module.exports
導出模塊, 針對這類模塊的聲明文件,須要使用export =
導出
declare module "a" {
export let a: number
export function b(): number
export namespace c{
let cd: string
}
}
import * as A from 'a'
A.a //
A.b()
A.c.cd //
複製代碼
// 函數
declare module 'app' {
function fn(some:number):number
export = fn
}
const app = reqiure('app')
app()// 調用fn
複製代碼
// 變量/常量
declare module 'let' {
let oo:number = 2
export = oo
}
const o = reqiure('let')
o // 使用
複製代碼
既能夠經過 <script>
標籤引入,又能夠經過 import 導入的庫,稱爲 UMD 庫。相比於 npm 包的類型聲明文件,須要額外聲明一個全局變量,爲了實現這種方式,ts 提供了一個新語法 export as namespace
export as namespace
做用: 局部變量生命爲全局變量
通常使用 export as namespace 時,都是已有 npm 包的聲明文件,再基於它添加一條 export as namespace 語句,便可將聲明好的一個變量聲明爲全局變量
// types/foo/index.d.ts
export as namespace foo; // 全局導出
export = foo; // or export default foo; 導出npm模塊
declare function foo(): string;
declare namespace foo {
const bar: number;
}
複製代碼
// global.extend.d.ts
interface String {
prependHello(): string;
}
複製代碼
// src/index.ts
'xx'.prependHello()
複製代碼
對於一個 npm 包或者 UMD 庫的聲明文件,只有 export 導出的類型聲明才能被導入 導入此庫以後能夠擴展全局變量, 須要使用 declare global
// types/foo/index.d.ts
declare global {
interface String {
prependHello(): string;
}
}
export default function foo(): string;
複製代碼
// src/index.ts
import foo from './foo'
'bar'.prependHello()
複製代碼
導入一個模塊插件, 改變原有模塊結構, 原有模塊已有聲明文件, 導入的模塊插件沒有聲明文件
// types/moment-plugin/index.d.ts
import * as moment from 'moment'; // 原有模塊
declare module 'moment' {
export function foo(): moment.CalendarKey;
}
複製代碼
// src/index.ts
import * as moment from 'moment';
import 'moment-plugin';
moment.foo();
複製代碼
declare module 也可用於在一個文件中一次性聲明多個模塊的類型
// types/foo-bar.d.ts
declare module 'foo' {
export interface Foo {
foo: string;
}
}
declare module 'bar' {
export function bar(): string;
}
複製代碼
// src/index.ts
import { Foo } from 'foo';
import * as bar from 'bar';
let f: Foo;
bar.bar();
複製代碼
Ambient Declarations(通稱:外部模塊定義) ,主要爲項目內全部的 vue 文件作模塊聲明,畢竟 ts 默認只識別 .d.ts、.ts、.tsx 後綴的文件;(即便補充了 Vue 得模塊聲明,IDE 仍是無法識別 .vue 結尾的文件,這就是爲何引入 vue 文件時必須添加後綴的緣由,不添加編譯也不會報錯)
JSX 語法的全局命名空間,這是由於基於值的元素會簡單的在它所在的做用域裏按標識符查找(此處使用的是**無狀態函數組件 (SFC)**的方法來定義),當在 tsconfig 內開啓了 jsx 語法支持後,其會自動識別對應的 .tsx 結尾的文件,可參考官網 jsx
靜態類型、動態類型和弱類型、強類型
靜態類型:編譯期就知道每個變量的類型。類型錯誤編譯失敗是語法問題。如Java、C++
動態類型:編譯期不知道類型,運行時才知道。類型錯誤拋出異常發生在運行時。如JS、Python
弱類型:容忍隱式類型轉換。如JS,1+'1'='11',數字型轉成了字符型
強類型:不容忍隱式類型轉換。如Python,1+'1'會拋出TypeError
關於我對聲明文件的實踐,詳見ts-declare, 另外,關於文章中,不對/不妥之處,歡迎指出,感謝~
www.tslang.cn/docs/handbo… ts.xcatliu.com/basics/decl…
zhuanlan.zhihu.com/p/58123993
blog.poetries.top/2019/09/03/…
juejin.im/post/5d22b1…