项目中用的是angular5.0+ionic3.0,由于现在angular现在都是用typescript写的了,虽然说typescript是Javascript的超集,但是在项目中还是会有一些问题,那就是全js写的插件怎么能引入到typescript写的模块呢?
TypeScript 的核心在于静态类型,我们在编写 TS 的时候会定义很多的类型,但是主流的库都是 JavaScript 编写的,并不支持类型系统。那么如何让这些第三方库也可以进行类型推导呢?
这篇文章我们来讲解 JavaScript 和 TypeScript 的静态类型交叉口 —— 类型定义文件。
之前在做项目的时候,老是看到这种写法,请看下面的代码:
import { ViewChild, ElementRef } from "@angular/core";
import { Company } from "../company/company";
import { Electronic } from "../sign/electronic/electronic";
import { Auth } from "../auth-pop/auth";
import { Credit } from '../credit-pop/credit';
declare let Talking: any;
declare let Push: any;
declare let cordova: any;
declare let Swiper: any;
从上面的代码我们可以看到有import的导入,还有declare的声明,为什么会这样写?下面会一一讲解
import { Electronic } from "../sign/electronic/electronic";
这行代码表示从electronic.ts引入我们定义的Electronic类,我们先看一下electronic.ts
import { Component } from "@angular/core";
import { NavController, NavParams, ModalController,Tabs, Events } from "ionic-angular";
import { CallNumber } from '@ionic-native/call-number';
import { Storage } from "@ionic/storage";
@Component({
templateUrl: "electronic.html",
providers: [CallNumber]
})
export class electronic {
constructor(
) {
}
ngOnInit() {
}
ionViewDidEnter() {
}
}
这个导入想必大家都知道,那这个这个呢?
import { ViewChild, ElementRef } from "@angular/core";
ViewChild和ElementRef都是封装好的插件,它们也都是用js写的,为什么它们可以用import的方式导入进来呢,仔细去查看了一下,发现它们都有一个.d.ts结尾的文件
ViewChild ===》di.d.ts
ElementRef ===》element_ref.d.ts
可以看到它们都有一个对应的.d.ts的文件
那么这个.d.ts的文件到底是什么样的?有什么作用呢?
在 TypeScript 中,我们可以很简单的,在代码编写中定义类型:
interface IBaseModel {
say(keys: string[] | null): object
}
class User implements IBaseModel {
name: string
constructor (name: string) {
this.name = name
}
}
但是主流的库都是 JavaScript 编写的,TypeScript 身为 JavaScript 的超集,自然需要考虑到如何让 JS 库也能定义静态类型。
TypeScript 经过了一系列的摸索,先后提出了 tsd(已废弃)、typings(已废弃),最终在 TypeScript 2.0 的时候重新整理了类型定义,提出了 DefinitelyTyped。
DefinitelyTyped 就是让你把 “类型定义文件(*.d.ts)”,发布到 npm 中,配合编辑器(或插件),就能够检测到 JS 库中的静态类型。
类型定义文件的以 .d.ts 结尾,里面主要用来定义类型。
我们来看一下element_ref.d.ts
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A wrapper around a native element inside of a View.
*
* An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
* element.
*
* @security Permitting direct access to the DOM can make your application more vulnerable to
* XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
* [Security Guide](http://g.co/ng/security).
*
* @stable
*/
export declare class ElementRef {
/**
* The underlying native element or `null` if direct access to native elements is not supported
* (e.g. when the application runs in a web worker).
*
*
* Use with caution
*
* Use this API as the last resort when direct access to DOM is needed. Use templating and
* data-binding provided by Angular instead. Alternatively you take a look at {@link Renderer}
* which provides API that can safely be used even when direct access to native elements is not
* supported.
*
*
* Relying on direct DOM access creates tight coupling between your application and rendering
* layers which will make it impossible to separate the two and deploy your application into a
* web worker.
*
*
* @stable
*/
nativeElement: any;
constructor(nativeElement: any);
}
从上面的代码我们可以提炼出最重要的一行代码
export declare class ElementRef {
从这行代码中我们也看到了declare
declare
declare 可以创建 *.d.ts 文件中的变量,declare 只能作用域最外层:
declare var foo: number;
declare function greet(greeting: string): void;
declare namespace tasaid {
// 这里不能 declare
interface blog {
website: 'http://tasaid.com'
}
}
基本上顶层的定义都需要使用 declare, class 也是:
declare class User {
name: string
}