TypeScript常用语法之函数与泛型

函数

函数是 JavaScript 应用程序的基础,它帮助你实现抽象层,模拟类,信息隐藏和模块。在 TypeScript 里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义行为的地方。TypeScript 为 JavaScript 函数添加了额外的功能,让我们可以更容易地使用。

// 封装了一些重复使用的代码,在需要的时候直接调用即可
(()=>{
    // js书写方式,ts也可以书写
    // 函数声明,命名函数
    // function add(x, y){ 
        // return x + y
    // }
    // 函数表达式,匿名函数
    // const add2 = function (x, y){
        // return x + y
    // }
    
    // ts书写方式
    // 函数声明,命名函数
    // 函数中的x,y的参数的类型都是string,小括号后面的:string代表的是该函数的返回值也是string类型的
    function add(x:string, y:string):string{ 
        return x + y
    }
    const result1:string = add('10','20')
    console.log(result1)
    // 函数表达式,匿名函数
    // 函数中的x,y的参数的类型都是number,小括号后面的:number代表的是该函数的返回值也是number类型的
    const add2 = function (x:number, y:number):number{
        return x + y
    }
    console.log(add2(10,20))
    
    // 函数的完整写法
    // add3===>变量名===>函数add3
    // (x:number,y:number) => number 当前这个函数的类型
    // function (x:number,y:number):number{return x + y} 就相当于符合上面的这个函数类型的值
    const add3:(x:number,y:number) => number = function (x:number,y:number):number{
        return x + y
    }
    console.log(add3(10,100))
})()

可选参数和默认参数

可选参数:函数在声明的时候,内部的参数使用了?进行修饰,那么就表示该参数可以传入也可以不传入,叫做可选参数

默认参数:函数在声明的时候,内部的参数有自己的默认值,此时的这个参数就可以叫默认参数

(()=>{
    const getFullName = function(firstName:string='爱蜜莉雅',lastName?:string):string{
        // 判断名字是否传入了
        if(lastName){
            return firstName + '-' lastName
        }else{
            return firstName
        }
    }
    // 什么也不传
    console.log(getFullName())
    // 只传入姓氏
    console.log(getFullName('诸葛'))
    // 传入姓氏和名字
    console.log(getFullName('樱岛','麻衣'))
})()

剩余参数(rest参数)

是放在函数声明的时候所有的参数的最后

(()=>{
    // args:string[] 剩余的参数,放在了一个字符串的数组中,args里面
    function showMsg(str:string,...args:string[]){
        console.log(str) // a
        console.log(args) // b c d e
    }
    showMsg('a','b','c','d','e')
})()

函数重载

函数名字相同,函数的参数及个数不同

(()=>{
    // 函数重载
    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('爱蜜莉雅','糖糖'))
    console.log(add(10,100))
    // 非法的,报红
    // console.log(add('真好',10))
    // console.log(add(100,'棒棒的'))
})()

泛型

指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。

(()=>{
    // 传入两个参数,第一个参数是数据,第二个参数是数量,函数的作用:根据数量产生对应个数的数据,存放在一个数组中
    function getArr1(value:number,count:number):number[]{
        const arr:number[] = []
        for(let i = 0, i < count, i++){
            arr.push(value)
        }
        return arr
    }
    const arr1 = getArr1(100.123,3)
    console.log(arr1)
    // 同上,类型是string
    function getArr2(value:string,count:number):string[]{
        const arr:string[] = []
        for(let i = 0, i < count, i++){
            arr.push(value)
        }
        return arr
    }
    const arr2 = getArr2('abc',3)
    console.log(arr2)
    // 可以传入任意类型,返回出来的是任意类型的数组
    function getArr3(value:any,count:number):any[]{
        const arr:any[] = []
        for(let i = 0, i < count, i++){
            arr.push(value)
        }
        return arr
    }
    const arr3 = getArr3('abc',3)
    const arr4 = getArr3(100.123,3)
    console.log(arr3)
    console.log(arr4)
    // 没有任何的智能提示信息
    console.log(arr3[0].split(''))
    console.log(arr4[0].toFixed(2))
    function getArr4<T>(value:T,count:number):T[]{
        // const arr:T[] = [] 或者
        const arr:Array<T> = []
        for(let i = 0, i < count, i++){
            arr.push(value)
        }
        return arr
    }
    const arr5 = getArr4<number>(200.12345,5)
    const arr6 = getArr4<string>('abc',5)
    console.log(arr5)
    console.log(arr6)
    // 有智能提示信息
    console.log(arr5[0].toFixed(2))
    console.log(arr6[0].split(''))
})()

泛型的多个参数

一个函数可以定义多个泛型参数

(()=>{
    function getMsg<K,V>(value1:K,value2:V):[K,V]{
        reuturn [value1,value2]
    }
    const arr1 = getMsg<string,number>('jack',100.123)
    console.log(arr1[0].split(''))
    console.log(arr1[1].toFixed(2))
})()

泛型接口

在定义接口时, 为接口中的属性或方法定义泛型类型
在使用接口时, 再指定具体的泛型类型

(() => {
  // 定义一个泛型接口
  interface IBaseCRUD<T> {
    data: Array<T>
    // t函数参数 :T参数类型 =>T返回值
    add: (t: T) => T
    getUserId: (id: number) => T
  }
  // 定义一个用户信息的类
  class User {
    id?: number
    name: string
    age: number
    constructor(name: string,age: number) {
      this.name = name
      this.age = age
    }
  }
  // 定义一个类,针对用户的信息对象进行增加及查询的操作
  class UserCRUD implements IBaseCRUD<User>{
    // 用来保存多个User类型的用户信息对象
    data: Array<User> = []
    // 用来存储用户信息对象
    add(user: User): User {
      user.id = Date.now() + Math.random()
      // 把用户信息对象添加到data数组
      this.data.push(user)
      return user
    }
    // 根据id查询指定的用户信息对象
    getUserId(id: number): User {
      return this.data.find(user => user.id === id)
    }
  }
  // 实例化
  const userCRUD: UserCRUD = new UserCRUD()
  // 调用添加数据方法
  userCRUD.add(new User('jack',20))
  userCRUD.add(new User('tom',21))
  const { id } = userCRUD.add(new User('tom',21))
  console.log(userCRUD.data)
  // 根据id查询用户信息对象数据
  const user = userCRUD.getUserId(id)
  console.log(user)
})()

泛型类

在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型

(() => {
  // 定义一个泛型类
  class GenericNumber<T> {
      // 默认的属性值的类型是泛型类
    defalutValue: T
    add: (x: T,y: T) => T
  }
   // 在实例化对象的时候在确定泛型的类型
  const g1: GenericNumber<number> = new GenericNumber<number>()
  // 设置属性值
  g1.defalutValue = 100
  // 相加的方法
  g1.add = function (x,y) {
    return x + y
  }
  console.log(g1.add(10,100))

  const g2: GenericNumber<string> = new GenericNumber<string>()
  g2.defalutValue = 'abc'
  g2.add = function (x,y) {
    return x + y
  }
  console.log(g2.add('爱蜜莉雅','糖糖'))
})()

泛型约束

如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性

(() => {
  // 定义一个接口用来约束将来的某个类型中必须要有length这个属性
  interface ILength {
    // 接口中有一个属性length
    length: number
  }
  function getLength<T extends ILength>(x: T): number {
    return x.length
  }
  console.log(getLength<string>('爱蜜莉雅糖糖'));
})()

声明文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能

什么是声明语句

假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过 <script> 标签引入 jQuery,然后就可以使用全局变量 $jQuery 了。

但是在 ts 中,编译器并不知道 $ 或 jQuery 是什么东西

安装jQuery

npm install jquery
/* 
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
  declare var jQuery: (selector: string) => any;
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
*/

下载声明文件

npm install @types/jquery --save-dev

创建一个jQuery.d.ts文件

declare var jQuery: (selector: string) => any
// 引入第三方jQuery库
import jQuery from 'jquery'
// 使用jQuery
jQuery('选择器')

内置对象

JavaScript 中有很多内置对象,它们可以直接在 TypeScript 中当做定义好了的类型。

内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准。

(() => {
  /* 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 
  /*BOM 和 DOM 的内置对象 */
  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 在社区的流行度越来越高,它非常适用于一些大型项目,也非常适用于一些基础库,极大地帮助我们提升了开发效率和体验。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值