上一篇文章讲了一下TypeScript的一些语法,这一篇讲剩下的
函数
函数封装了一些重复使用的代码,在需要的时候直接调用
函数是 JavaScript 应用程序的基础,它帮助你实现抽象层,模拟类,信息隐藏和模块。在 TypeScript 里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义行为的地方。
js中书写方式
命名函数
function aa(){
console.log('hello')
}
aa() //hello
匿名函数
(function(){
console.log('hello')
})()
ts中书写方式
命名函数
//函数中的a,b都是string类型,小括号后面的string代表函数的返回值是string
function aa(a:string,b:string):sting{
return a+b
}
console.log(aa('11','22')) //1122
匿名函数
//函数中的a,b都是number类型,小括号后面的number代表函数的返回值是number
const add=function(a:number,b:number):number{
return a+b
}
console.log(add(11,22)) //33
完整写法
//add是函数变量名
//(a:number,b:number)=>number当前这个函数的类型
//function(a:number,b:number):number{return a+b} 函数类型的值
const add:(a:number,b:number)=>number=function(a:number,b:number):number{
return a+b
}
console.log(add(10,20)) //30
可选参数和默认参数
可选参数:代表这个函数可以传参也可以不传参
在ts中,函数在声明的时候,在形参后加 ? 进行修饰,那么久代表该参数是可选参数
function aa(a:string,b?:string):string{
//判断b是否传值
if(b){
return a+b
}{
return a
}
}
console.log(aa('11')) //11
console.log(aa('11','22')) //1122
默认参数:在函数没有传参的情况下,函数有自己的默认值,那么这个参数就叫默认参数
function aa(a:string,b?:string='相如'):string{
return a+b
}
console.log(aa('司马')) //司马相如
console.log(aa('司马','懿')) //司马懿
剩余参数(rest参数)
必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在 JavaScript 里,你可以使用 arguments
来访问所有传入的参数。
在 TypeScript 里,你可以把所有参数收集到一个变量里:
剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。
//剩余的参数放在数值的数组c内
function aa(a:number,b:number,...c:number[]){
console.log(a) //1
console.log(b) //2
console.log(c) //[3,4,5,6,7]
}
aa(1,2,3,4,5,6,7)
函数重载
函数重载:函数名字相同,函数的参数以及个数不同
//需求: 我们有一个add函数,它可以接收2个string类型的参数进行拼接,也可以接收2个number类型的参数进行相加
// 重载函数声明
function add (x: string, y: string): string
function add (x: number, y: number): number
// 定义函数实现
function add(x: string | number, y: string | number): string | number {
if (typeof x === 'string' && typeof y === 'string') {
return x + y
} else if (typeof x === 'number' && typeof y === 'number') {
return x + y
}
}
console.log(add(1, 2)) //3
console.log(add('a', 'b')) //ab
泛型
指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。
函数泛型
// t,传入的是number就是number,传入string就是string,<>里面的值随意起,但是和函数的类型要一致
function aa<t>(a: any, b: any):t[] {
return a+b
}
console.log(aa<number>(1,2)) //3
console.log(aa<string>('司马','相如')) //司马相如
多个泛型参数的函数
函数中有多个泛型的参数
function aa<t,v>(a: t, b: v):[t,v] {
return [a,b]
}
const bb=aa<string,number>('司马',2)
泛型接口
在定义接口时,为接口中的属性或方法定义泛型类型,
在使用接口是,在指定具体的泛型类型
interface person <T> {
data: T[]
add: (t: T) => void
}
class aa {
id?: number; //id主键自增
name: string; //姓名
age: number; //年龄
constructor (name, age) {
this.name = name
this.age = age
}
}
class bb implements person <aa> {
data: aa[] = []
add(aa: aa): void {
aa = {...aa, id: Date.now()}
this.data.push(aa)
console.log(aa.id)
}
}
const cc = new bb()
cc.add(new aa('tom', 12))
cc.add(new aa('tom2', 13))
console.log(cc.data)
泛型类
在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型
定义泛型类
class aa<T> {
default: T
add:(x:T,y:T) =>T
}
number类型
let bb = new aa<number>()
bb.default = 10
bb.add = function(x, y) {
return x + y
}
console.log(bb.add(bb.default, 12)) //22
string类型
let cc = new aa<string>()
cc.default = '司马'
cc.add = function(x, y) {
return x + y
}
console.log(cc.add(cc.default, '相如')) //司马相如
泛型约束
有了泛型之后,一个函数或容器类能处理的类型一下子扩到了无限大,似乎有点失控的感觉。所以这里又产生了一个约束的概念。我们可以声明对类型参数进行约束
如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性
我们可以使用泛型约束来实现
interface aa {
length: number;
}
// 指定泛型约束
function bb <T extends aa>(x: T): void {
console.log(x.length)
}
bb('abc')
注意我们需要传入符合约束类型的值,必须包含必须 length 属性,如number没有length属性,string有
声明文件
TypeScript 作为 JavaScript 的超集,在开发过程中不可避免要引用其他第三方的 JavaScript 的库。虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript 诸如类型检查等特性功能。为了解决这个问题,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述 JavaScript 库和模块信息的声明文件。通过引用这个声明文件,就可以借用 TypeScript 的各种特性来使用库文件了。
以jquery库为例
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
下载声明文件
npm install @types/jquery --save-dev
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
使用 declare var 来定义它的类型
declare var jQuery: (selector: string) => any;
jQuery('#foo');
declare var 并没有真的定义一个变量,只是定义了全局变量 jQuery 的类型,仅仅会用于编译时的检查,在编译结果中会被删除。它编译结果是:
jQuery('#foo');
一般声明文件都会单独写成一个 xxx.d.ts
文件
创建 01_jQuery.d.ts
, 将声明语句定义其中, TS编译器会扫描并加载项目中所有的TS声明文件
declare var jQuery: (selector: string) => any;
内置对象
JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中当做定义好了的类型。
内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准。
1.ECMAScript 的内置对象
Boolean、Error、Date、RegExp 、Error
/* 1. ECMAScript 的内置对象 */
let b: Boolean = new Boolean(1)
let n: Number = new Number(true)
let s: String = new String('abc')
let d: Date = new Date()
let r: RegExp = /^1/
let e: Error = new Error('error message')
b = true
// let bb: boolean = new Boolean(2) // error
注意:声明的类型和new的对象大小写要一致,不然会报错
2.BOM 和 DOM 的内置对象
Document、HTMLElement、Event、NodeList 等。
const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()
TypeScript核心库的定义文件
TypeScript核心库的定义文件中定义了所有浏览器环境需要用到的类型,并且是预置在 TypeScript中的。
当你在使用一些常用的方法的时候, TypeScript市级上已经帮你做了很多类型判断工作了。
Math.round('3.4') // 类型“string”的参数不能赋给类型“number”的参数
math.round的参数数量必须是一个,而且必须是number类型
内置对象想要了解更多的可以访问官网:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
vscode自动编译代码
1)生成配置文件tsconfig.json
tsc --init
2)修改tsconfig.json配置
"outDir":"./js" // 把ts文件最终编译后放在js的目录中
"strict":false // 不使用严格模式
3)启动监视任务
终端 ----运行任务----监视tsconfig.json
在vscode中点击终端 →运行任务→显示所有任务→监视tsconfig.json
error不用管
这样就可以实现实时更新,自动编译代码
效果:创建index.ts文件会自动生成js文件,
ts文件修改,js文件会自动修改
类型注解
类型注解:是一种轻量级的为函数或者变量添加的约束
TypeScript提供了静态的代码分析,它可以分析代码结构和提供的类型注释
注意:因为ts比js严格,所有在某些情况下,代码在ts有错误,但是在js里可以运行,
虽然你的ts文件有错误,但是它依然会给你转换为js文件,但是在这种情况下,ts会警告你代码可能不会按预期执行
ts文件
注意:这个代码函数里规定了参数是string类型,但传的参是number类型,它会给你提供错误信息
总结
TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript。编译出来的 JavaScript 可以运行在任何浏览器上。TypeScript 编译工具可以运行在任何服务器和任何系统上。TypeScript 是开源的。
好处:
- 增加了代码的可读性和可维护性
- 非常包容
- 拥有活跃的社区
注意:
- 声明类型string表示字符串,而String表示String对象
- null undefined 是所有类型的子类型