声明语句
/* 声明语句 */
// 如果引入第三方库,则需要声明类型
// 例如JQuery
$('#button').click(); // 找不到名称 "$"。是否需要安装 jQuery 的类型定义? 请尝试使用 `npm i --save-dev @types/jquery`。
// 声明后
declare var $: any; // 使用let conts 都行
$('#button').click(); // 不报错
// 更加具体的声明
declare var $: (selector: string) => {
click(): void
width(length: number): void
};
$('#button').click(); // 此时则有了click和width语法提示
答案
解析
在类型声明文件中,可以使用 declare 关键字声明语句。
- A - 声明了变量 animal,类型为 string。用法正确。
- B - 声明了函数 setAnimal,参数为 string,返回值为 void。用法正确。
- C - 声明了类 Animal,属性 name 的类型为 string,属性 age 的属性为 number。用法正确。
命名空间
/* 命名空间 */
// namespace是早期TS为了解决module关键字
// 定义方法
declare namespace jQ_6101 {
function ajax(url: string, settings: any): void;
}
jQ_6101.ajax
// 定义属性
declare namespace jQ_6102 {
const version: number;
}
jQ_6102.version
// 定义内部方法
declare namespace jQ_6103 {
namespace fn {
function extend(obj: any): void;
}
}
jQ_6103.fn.extend({})
答案
解析
在类型声明文件中,可以使用 declare 关键字声明语句,可以使用 declare namespace 声明命名空间。
命名空间可以嵌套使用,用法如下
declare namespace A { … namespace B { … } }
选项中都声明命名空间 animal
- A - 命名空间内部声明了方法 getAnimal 和属性 name。用法正确。
- B - 在命名空间内部不需要使用 declare 声明属性或方法。用法错误。
- C - 在命名空间内部声明了命名空间 info。用法是正确的。
声明文件
答案
解析
在类型声明文件中,可以使用关键字 declare 声明语句,并且类型声明文件需要命名为 *.d.ts。在使用模块或“库”的时候,可以先查看该模块或“库”的声明文件,有助于我们快速了解模块或“库”的使用。
第三方声明文件
// 通过 npm i --save-dev @types/jquery 安装
// @types 是约定的前缀,表示第三方库的类型定义
npm npm i --save-dev @types/jquery
答案
解析
题目中安装 react 类型声明文件的命令是正确的。
// 命令模版 npm install @types/packageName —save
一般情况下,类型声明包名 ===@type
/ + npm 包名
。
npm 模块的声明文件
/* npm 模块的声明文件 */
// declare 声明是最简单,npm包则使用 import 进行导入
// 例如这里使用了 npm i --save jquery
// 还安装了 npm i --save-dev @types/jquery
/* 已声明“jQuery”,但从未读取其值。ts(6133)
模块 ""E:/w/typescript_demo/node_modules/@types/jquery/index"" 只能在使用 "esModuleInterop" 标志时进行默认导入ts(1259)
index.d.ts(34, 1): 此模块是使用 "export =" 声明的,只能在使用 "esModuleInterop" 标志时进行默认导入。
*/
//import jQuery from 'jquery'; // 因为jQ是一个commonjs风格的模块,所以对于commonjs风格的需要使用 * as
import * as jQuery from 'jquery';
jQuery.ajax // 已经有正确的类型提示,因为按照了@types/jquery的声明文件
// 假设第三方库没有类型声明,则需要自己去写类型声明
// 在根目录创建 /types/jquery/index.d.ts
// tsconfig.json 中添加 "baseUrl": "./" 和 "paths": { "*": [ "./types/*" ] }
// 所以当没有第三方声明文件的时候,就会读取根目录下的 types/jquery/index.d.ts
// 然后在index.d.ts中exports
// 此处引入
import jQuery_6101, { a, bar, abc } from 'jquery';
jQuery_6101 //则能读取到function jQuery_6101(): string
a //const a: string
bar() //bar(): string
abc.foo() //namespace abc / abc.foo(): string
答案
解析
当下载完 npm
包后。可以通过如下路径去查看该 npm 包的声明文件。
第一种
// node_modules/packageName/package.json { ... "types": "types/xxx.d.ts ... }
这种方式可以指定声明文件的入口文件。
第二种
node_modules/packageName/index.d.ts
如果该包的默认入口是 index.js,那么默认会读取声明文件 index.d.ts。
由于第二种和第一种方式都是指定声明文件入口的,所有二者选择其一即可。第三种
node_modules/@types/packageName/index.d.ts
有时候,
npm
包的发行者并没有提供该包的声明文件,后面由社区或个人独立提供声明文件。于是也就有了这种形式。
故而这三种方式都是正确的。
扩展全局变量类型
/* 扩展全局变量的类型 */
interface String { //这是后追加的声明,此处需要tsconfig.json es2017
prepenHello(): string;
}
String.prototype.prepenHello = function () {
return 'Hello, ' + this;
}
'foo'.prepenHello() // 报错, 因为没有对应的类型声明
// 如果上面这个声明是个全局变量,而且如果它是个NPM包,通过export inport是不生效的
// 此时就需要用到全局变量,才能正确引用到
// 假设有个global.d.ts,interface String 在里面, 则可以正确引用
String.prototype.prepenHello_6101 = function () {
return 'Hello, ' + this;
}
'foo'.prepenHello_6101()
// 假设在types/foo中,则无法引用
String.prototype.prepenHello_6102 = function () {
return 'Hello, ' + this;
}
'foo'.prepenHello_6102()
// 假设在types/foo中定义global,则可以正确引用
String.prototype.prepenHello_6103 = function () {
return 'Hello, ' + this;
}
'foo'.prepenHello_6103()
interface String { //这是后追加的声明,此处需要tsconfig.json es2017
prepenHello_6101(): string;
}
// 这是无法引用的
interface String {
prepenHello_6102(): string;
}
// 声明全局变量
declare global {
interface String {
prepenHello_6103(): string;
}
}
答案
解析
可以使用 declare global
方式在 npm
包或 UMD
库中扩展全局变量的类型。
所以题目中扩展 window
属性的用法是正确的。