preface

Before writing a declaration file for a third party module/library, we need to know whether the third party module/library needs a declaration file or whether it already has one.

  • If a third party module/library is written by TS and has no declaration file, it can be used--declarationConfigure options to generate; You can add –declaration (-d for short) to the command line or add the declaration:true option to tsconfig.json
  • If a third-party module/library is written in JS, it is divided into two cases:
1. Bind to the NPM package by looking for the 'types' property in the library's' package.json '. Released into the @ types and can provide third party statement on the official document (http://microsoft.github.io/TypeSearch/)Copy the code

If none of the above is true, we need to write our own declaration document

Front knowledge

Before writing a Typescript declaration file, you need to be familiar with Typescript. Check out the official Typescript documentation, or read my previous Typescript summary. If you’re familiar with Typescript, you probably already have some practice in Typescript. In addition to this, you need to have an understanding of modularity in TS, as follows

modular

Module (module)

Mainly to solve the loading dependency, focus on the reuse of the code. Bound to files, a file is a module, just like in ES6.

Namespace (namespace)

Like Java packages and.NET namespaces, TypeScript namespaces wrap code around objects that need to be accessed externally through the export keyword. It is mainly used to organize code and resolve naming conflicts. An object is generated globally. All objects defined inside a namespace are accessed through the properties of this object.

As ES6 is widely used, namespaces in TS are not recommended. ES6 modular solution is recommended. However, namespace declaration is still commonly used in declaration files.

Namespace declarations can be used to add new types, values, and namespaces, as long as no conflicts occur. Merges with types such as class/namespace

/// three slash command

//

Other scenarios use import instead of relying on or being relied on by the global library in the declaration file:

  1. Libraries depend on global libraries because global libraries cannot be imported using import
  2. The global library depends on a CERTAIN UMD module, because import/export cannot be present in the global library, NPM /UMD is present

Note: the triple slash directive must be placed at the top of the file. Only one or more lines of comments are allowed before the triple slash directive.

Modules, or a UMD library, depend on a UMD library and import modules using the import * AS statement

Written declaration document

Third-party library usage scenarios:

  • Global variables: Pass<script>The tag brings in third-party libraries and injects global variables
  • NPM package: Yesimport foo from 'foo'Import, conform toES6The module specification
  • UMD library: Both can be passed<script>Tags are introduced, and can be passedimportThe import
  • Module plug-in: PassimportAfter importing, you can change the structure of another module
  • Expand global variables directly: Pass<script>When the tag is introduced, it changes the structure of a global variable. Such asString.prototypeA method has been added
  • Extend global variables by importing: PassimportAfter importing, you can change the structure of a global variable

The class library is divided into three types: global class library, module class library and UMD class library

The global variable

A global variable declaration file has the following syntax:

  • Declare var Declares global variables
  • Declare Function declares global methods
  • Declare Class Declares the global class
  • Declare enum Specifies the global enumeration type
  • Declare namespace Declares a global object (with child attributes)
  • Interface and type declare global types

Focus on declare namespace

// src/jQuery.d.ts

declare namespace jQuery {
    const version: number;
    class Event {
        blur(eventType: EventType): void
    }
    enum EventType {
        CustomClick
    }
    interfaceAjaxSettings { method? :'GET' | 'POST'data? :any;
    }
    function ajax(url: string, settings? : AjaxSettings) :void;
}
Copy the code

Declare namespace: Declare namespace: declare namespace: declare namespace: declare namespace: declare namespace: declare namespace

// Declare a global function
declare function ajax(url: string, settings? :any) :void;
Copy the code

NPM package

In the NPM package, import the NPM package by importing foo from ‘foo’. NPM package declaration file has the following syntax:

export// Export variablesexportNamespace // Exports objects (with child attributes)exportDefault // ES6 Exports data by defaultexport= // commonJS export moduleCopy the code

export

In the declaration file of the NPM package, using DECLARE no longer declares a global variable, but only a local variable in the current file. These type declarations are applied only after export is exported in the declaration file and then imported by the user import.

Similar to non-declaration file writing, use import, ES6 module syntax

Mix DECLARE and export

Declare multiple variables first and export all at once. Note: Interface does not require DECLARE

export default

Note that only function, class, and interface can be exported by default. Other variables need to be defined before they are exported by default

export namespace

Used to export an object with child attributes

export =

Exports /module.exports in the commonJS specification, export = export is used for declarations of such modules

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 // 
Copy the code
/ / functiondeclare module 'app' {
  function fn(some:number):number 
  export = fn
}

const app = reqiure('app') app()// call fnCopy the code
// Variable/constantdeclare module 'let' {
  let oo:number = 2
  export = oo
}

const o = reqiure('let') o // UseCopy the code

UMD library

Libraries that can be imported either through the

Export as namespace Function: Local variables are global variables. Generally, export as namespace is the declaration file of the existing NPM package. Then add an export as namespace statement based on it to declare a declared variable as a global variable

// types/foo/index.d.ts
exportas namespace foo; // Global exportexport = foo; // or exportdefault foo; Export the NPM moduledeclare function foo(): string;
declare namespace foo {
    const bar: number;
}
Copy the code

Expand global variables directly

// global.extend.d.ts
interface String {
    prependHello(): string;
}
Copy the code
// src/index.ts
'xx'.prependHello()
Copy the code

Extend global variables in NPM /UMD

For an NPM package or UMD library declaration file, only type declarations exported by export can be imported. After importing the library, you can extend global variables by using DECLARE Global

// types/foo/index.d.ts

declareglobal { interface String { prependHello(): string; }}export default function foo(): string;
Copy the code
// src/index.ts

import foo from './foo'
'bar'.prependHello()
Copy the code

Module plug-ins

Import a module plug-in, change the original module structure, the original module has a declaration file, the imported module plug-in does not have a declaration file

// types/moment-plugin/index.d.ts

import * as moment from 'moment'; // The original moduledeclare module 'moment' {
    export function foo(): moment.CalendarKey;
}
Copy the code
// src/index.ts

import * as moment from 'moment';
import 'moment-plugin';

moment.foo();
Copy the code

Single file multiple modules

The Declare Module can also be used to declare multiple module types at once in a file

// types/foo-bar.d.ts

declare module 'foo' {
    exportinterface Foo { foo: string; }}declare module 'bar' {
    export function bar(): string;
}
Copy the code
// src/index.ts

import { Foo } from 'foo';
import * as bar from 'bar';

let f: Foo;
bar.bar();
Copy the code

other

shims-vue.d.ts

Ambient Declarations are used to declare all vue files in a project. By default, ts only recognizes files with the.d.ts,.ts, and.tsx extensions. (Even if the module declaration of Vue is added, the IDE will not recognize the.vue ending file, which is why the suffix must be added when importing Vue files, and no errors will be reported without adding the build.)

shims-jsx.d.ts

The global namespace of the JSX syntax. This is because value-based elements are simply looked up by their identifiers in the scope in which they are located (defined using the ** stateless function component (SFC) method). When the JSX syntax is enabled in tsconfig, It will automatically recognize the corresponding.tsx ending file, please refer to JSX website

Classification of language types

Static, dynamic and weakly and strongly typed Static typing: The type of each variable is known at compile time. Type error compile failure is a syntax problem. For example, Java and C++ dynamic typing: the type is not known at compile time, but only at runtime. Type errors throw exceptions that occur at run time. Weak typing, such as JS and Python, tolerates implicit type conversions. For example, JS, 1+’1’=’11’, numeric converted to character strong: implicit type conversions are not tolerated. In Python, 1+’1′ raises TypeError

summary

See TS-Declare for more details on my practice with declaration files, and please point out any inaccuracies/inaccuracies in the article. Thank you

reference

www.tslang.cn/docs/handbo… Ts.xcatliu.com/basics/decl… Zhuanlan.zhihu.com/p/58123993 blog. Poetries. Top / 2019/09/03 /… Juejin. Cn/post / 684490…