草庐IT

TypeScript详解十六:类型声明(declare)

剑九 六千里 2024-07-16 原文

目录


前言

在日常开发中几乎所有的项目都会应用许多第三方库来完成任务需求。
这些第三方库不管是否是用 TS 编写的,最终都要编译成 JS 代码,才能发布给开发者使用。
我们知道是 TS 提供了类型,才有了代码提示和类型保护等机制。
但在项目开发中使用第三方库时,你会发现它们几乎都有相应的 TS 类型,这些类型都是通过类型声明文件完成的。


一、类型声明的作用?

  • 用来为已存在的 JS 库提供类型信息。
  • 声明文件可以让我们不需要将JS重构为TS,只需要加上声明文件就可以使用系统。
  • 在 TS 项目中使用第三方库时,就像在用 TS 一样,都会有代码提示、类型保护等机制,极大的提高了开发效率,降低了心智负担。
  • 类型声明在编译的时候都会被删除,不会影响真正的代码。

1.1 declare 关键字

  • 关键字 declare 表示声明的意思,我们可以用它来做出各种声明
  • declare 是给编译器读取用的,可以暂时不调用

1.2 示例

declare var // 声明全局变量
declare function // 声明全局方法
declare class // 声明全局类
declare enum // 声明全局枚举类型
declare namespace // 声明(含有子属性的)全局对象
interface  type // 声明全局类型

二、常见的几种类型声明

2.1 普通类型声明

declare let age: number;
declare function getAge(): number | string;
declare class Person { };
  • 使用普通类型声明
console.log(age);
getAge();
new Person()

2.2 外部枚举

declare enum Seasons {
  Spring,
  Summer,
  Autumn,
  Winter
}
  • 使用枚举 Seasons
let seasons = [
  Seasons.Spring,
  Seasons.Summer,
  Seasons.Autumn,
  Seasons.Winter
]

2.3 命名空间

  • 如果一个全局变量有很多子属性,就可以使用namespace
  • 声明文件里的namespace表示一个全局变量,包含很多个子属性
  • 在命名空间内部不需要再使用declare
// 模拟 jQuery 的 $
declare namespace $ {
  function ajax(url: string, method: string, data: object): void;
  let userName: string;
  namespace getName {
    function onClick(): void;
  }
}
  • 使用 $
$.ajax('/login', 'post', {});
$.userName;
$.getName.onClick();

三、类型声明文件

  • 一般来说会将类型声明文件放在单独的文件中,通过观察声明文件来进行库的使用
  • 文件名一般约定以 xxx.d.ts 结尾

3.1 模拟类型声明文件,以 jquery 为例

  • 新建一个 typings 文件夹
  • 新建一个 jquery.d.ts 声明文件
// jquery.d.ts 中示例代码如下
declare const $:(selector: string) => {
  click(): void;
  dbClick(): void;
  width(length: number): void;
  height(length: number): void;
}

3.2 使用手动实现的jquery.d.ts声明文件

  • 在tsconfig.json配置文件中增加include属性
"include": [
//   补充:此处采用glob模式,* 表示匹配任意字符,不包括路径分隔符;** 表示匹配任意字符,也包括路径分隔符
//   此处的 step1  step2  typings 表示自己需要使用此声明文件的目录
  "step1/**/*",
  "step2/**/*",
  "typings/**/*"
]
  • 在自己的代码中就可以使用这个声明文件了
$('#button').click();
$('#button').dbClick();
$('#button').width(200);
$('#button').height(200);

3.3 第三方声明文件(以jquery为例)

  • 安装jquery包
npm install jquery -s
  • 下图就是jquery的声明文件所在位置

  • 导入jquery

import * as jQuery from 'jquery'
// 注意:
// 此处需要采用上面这种导入方式
// 因为 typeScript\node_modules\@types\jquery\index.d.ts 这个文件下采用了export = jQuery的写法;
// export = jQuery; 这是一种TS的语法,表示要导出jQuery
// 支持es6导出,也支持 common.js导出

// 如果要用es6的导入
// import jQuery from 'jquery'
// 那么需要在tsconfig.json文件中将 "esModuleInterop": true 开启


// 注意此处会报错,找不到声明文件
// 需要执行下面这行命令,安装jquery的声明文件
npm i --save-dev @types/jquery
  • 使用jquery
jQuery.ajax(); // 此处可以调用

3.4 npm声明文件可能存在的位置

  • node_modules/jquery/package.json
    • “types”: “types/xxx.d.ts”
  • node_modules/jquery/index.d.ts
  • node_modules/@types/jquery/index.d.ts
  • typings/jquery/index.d.ts

补充知识点

  • 三斜杠语法:来源于C#写法,表示引用的意思,引用其他文件。更多可搜索ts三斜杠语法
/// <reference types="sizzle" />
/// <reference path="JQueryStatic.d.ts" />
/// <reference path="JQuery.d.ts" />
/// <reference path="misc.d.ts" />
/// <reference path="legacy.d.ts" />

总结

本文主要介绍了ts中的类型声明,下次再见。

有关TypeScript详解十六:类型声明(declare)的更多相关文章

  1. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  2. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  3. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  4. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  5. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  6. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  7. ruby - 如何使用 method_missing 动态声明方法? - 2

    我有一个ruby​​程序,我想接受用户创建的方法,并使用该名称创建一个新方法。我试过这个:defmethod_missing(meth,*args,&block)name=meth.to_sclass我收到以下错误:`define_method':interningemptystring(ArgumentError)in'method_missing'有什么想法吗?谢谢。编辑:我以不同的方式让它工作,但我仍然很好奇如何以这种方式做到这一点。这是我的代码:defmethod_missing(meth,*args,&block)Adder.class_evaldodefine_method

  8. ruby-on-rails - Rails 迁移中的 PostgreSQL 点类型 - 2

    我想使用PostgreSQL中的point类型。我已经完成了:railsgmodelTestpoint:point最终的迁移是:classCreateTests当我运行时:rakedb:migrate结果是:==CreateTests:migrating====================================================--create_table(:tests)rakeaborted!Anerrorhasoccurred,thisandalllatermigrationscanceled:undefinedmethod`point'for#/hom

  9. ruby-on-rails - 我可以用鸭子类型(duck typing)改进这种方法吗? - 2

    希望我没有误解“ducktyping”的含义,但从我读到的内容来看,这意味着我应该根据对象如何响应方法而不是它是什么类型/类来编写代码。代码如下:defconvert_hash(hash)ifhash.keys.all?{|k|k.is_a?(Integer)}returnhashelsifhash.keys.all?{|k|k.is_a?(Property)}new_hash={}hash.each_pair{|k,v|new_hash[k.id]=v}returnnew_hashelseraise"CustomattributekeysshouldbeID'sorPropertyo

  10. ruby-on-rails - 如何在 ActionController::TestCase 请求中设置内容类型 - 2

    我试图像这样在我的测试用例中执行获取:request.env['CONTENT_TYPE']='application/json'get:index,:application_name=>"Heka"虽然,它失败了:ActionView::MissingTemplate:Missingtemplatealarm_events/indexwith{:handlers=>[:builder,:haml,:erb,:rjs,:rhtml,:rxml],:locale=>[:en,:en],:formats=>[:html]尽管在我的Controller中我有:respond_to:html,

随机推荐