typescript学习

前言

JavaScript是一门弱类型语言,无需编译就能运行,没有类型检查,无法提前预知错误,并且没有类型约束增加了沟通成本。我们知道,在开发时,越早发现错误越好。TypeScript是拥有类型的JavaScript超集,相当于JavaScript的加强版,它可以编译成完整的JavaScript代码。

JavaScript所拥有的特性,TypeScript全部都是支持的,并且它紧随ECMASript的标准,所以ES6、ES7、ES8等新语法标准,它都是支持的;TypeScript在语言层面上,不仅仅增加了类型约束,而且包括一些语法的扩展,比如枚举类型,元组类型等。

变量的声明

// var/let/const 标识符: 数据类型 = 值;
let message: string = '张三';
//当我们给 message 赋值其他类型的值,那么就会报错
message = 123   //不能将类型“number”分配给类型“string”。ts(2322)

变量的类型推导

  // 有时候我们开发时不需要每次声明变量都要事先定义好数据类型,而是可以通过ts的类型推导来推断出变量类型
    let age = 123
    age = '123'  // 不能将类型“string”分配给类型“number”。ts(2322)

数据类型

 /* JavaScript的数据类型 */
    let age: number = 22			//number
    let name: string = 'zhangsan'	//string
    let isReload: boolean = true	//boolean
    let arr: number[] = [1, 2, 3]	//Array
    let arr1: Array<number> = [4, 5, 6]
    let obj: object = {				//object
      name: 'zhangsan',
      age: 12,
      gender: 'male'
    }
    let s1: symbol = Symbol('zhangsan')		//symbol
    let s2: symbol = Symbol('zhangsan')
    let person = {
      [s1]: 'male',
      [s2]: 'female'
    }
    let n: null = null				// null
    let u: undefined = undefined       //undefined
    
    /* TypeScript */
    let a: any = 'why'      // any 任意类型,宽松的(无约束)
    a = 123  // 可以
    let result: unknown;    // unknown 类型不确定的变量
    function sum(num1: number, num2: number): void {	// void 通常用于指定函数没有返回值
      console.log(num1 + num2)
    }
    function loopErr(): never {				//never 表示永远不会发生值的类型,比如函数的死循环或者抛出异常(中断),无法  返回值
      throw new Error()
    }
    let student: [string, number, string] = ['zhangsan', 12, 'male'];        // tuple元组类型,即多种数据类型组合的数组

函数的参数类型

函数是JavaScript非常重要的组成部分,TypeScript允许我们指定函数的参数和返回值的类型。

   function delete(id: string): object{       // 这里指定传入的参数必须为 string 返回值是一个对象
      let res = {}
      return res
    }
    function search(searchInfo: {name: string, age: number}): object{       // 这里指定传入的参数必须为对象且属性,属性值需要对应符合
      let res = {}
      return res
    }
    search({name: 'zhangsan', age: 2})  

可选类型

  • 对象类型也可以指定哪些属性是可选的,可以在属性的后面添加一个?:
  • 注意可选类型后面不能有必选类型,即可选类型一般放最后,类似于…rest(剩余参数)
function search(id: string, name?: string) {
  console.log(id)
  if(name) console.log(name)
}
search('123','zhangsan')      // 123,zhangsan
search('123')      // 123

联合类型

TypeScript的类型系统允许我们使用多种运算符,从现有类型中构建新类型

function printId(id: number | string) {
  if(typeof id === 'number') return id		
  else return id.length
}
console.log(printId(10))    //10
console.log(printId('abc'))   // 3

到这里其实可以看出,可选类型是某一类型与 undefined 的联合类型,如:

 function printId(id?: number){
      console.log(id)
    }
    printId()
    printId(123)  // 123

类型别名

在前面,我们通过在类型注解中编写 对象类型 和 联合类型,但是当我们想要多次在其他地方使用时,就要编写多次。 比如我们可以给对象类型起一个别名:

type Point = {x: number, y: number}

function printPoint(point:Point) {
  console.log(Point.x, Point.y)
}
printPoint({x: 1, y: 2})

类型断言as

有时候TypeScript无法获取具体的类型信息,这个我们需要使用类型断言

   // 不使用断言
    function printLength(n: string | number) {
      console.log(n.length);    //类型“string | number”上不存在属性“length”。类型“number”上不存在属性“length”。ts(2339)
    }
    
    // 使用断言
    function printLength(n: string | number) {
      console.log((n as string).length);
    }

函数的默认参数

从ES6开始,,JavaScript是支持默认参数的,TypeScript也是支持默认参数的:

function getInfo(id: string, status: number = 2) {
  console.log(id, status)
}
foo('213')   // 213, 2
// 这个时候y的类型其实是 undefined 和 number 类型的联合。

函数的剩余参数

从ES6开始,JavaScript也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。

 function sum(...nums: number[]) {
      let total = 0
      for(let num of nums) {
        total += sum
      }
      console.log(total)
    }
    sum(1, 2, 3)   // 6

函数的重载

   function sum(num1: number, num2: number): number;    
    function sum(num1: string, num2: string): string;   //重载外部不可见
    function sum(num1: any, num2: any): any {
    	return num1 + num2
    }
    console.log(sum(1, 2))    // 3
    console.log(sum('zhang', 'san'))  // zhangsan

接口的声明

interface People = {
  name: string
  age: number
}
  • 接口中的可选属性
 interface Person {
      name: string
      age: number
      gender?: string
    }
    const person: Person = {
      name: 'zhangsan',
      age: 15,
      gender: 'female'
    }
    console.log(person.name)   // zhangsan
    console.log(person?.gender) // female
  • 接口中的只读属性
  interface Person {
      readonly name: string
      readonly age: number
      gender?: string
    }
    const person: Person = {
      name: 'zhangsan',
      age: 12,
      gender: 'male'
    }
    person.age = 14  //无法分配到 "age" ,因为它是只读属性。ts(2540)

可以发现,readonly 和 const 有像似之处

  • 同:用于约束数据的修改属性
  • 异:const用于定义常量,而 readonly用于修饰属性

索引类型

  interface Game {
      [index: string]: string
    }
    const game: Game = {
      'first': '天天酷跑''second': '五子棋''third': '象棋'
    }
    console.log(game.first)  //天天酷跑

接口继承

接口和类一样是可以进行继承的,也是使用extends关键字:

   interface Person {
      name: string,
      eating: () => void
    }
    
    interface Animal {
      running: () => void
    }
    
    interface Student extends Person, Animal {
      gender: string
    }
    
    const student: Student = {
      gender: 'male',
      name: 'zhangsan',
      eating: function() {},
      running: function() {}
    }

接口的实现

接口定义后,也是可以被类实现的:

  • 如果被一个类实现,那么在之后需要传入接口的地方,都可以将这个类传入
  • 这就是面向接口开发
 interface ISwim {
      swimming: () => void
    }
    
    interface IRun {
      running: () => void
    }
    
    class Person implements ISwim, IRun {
      swimming() {
        console.log('swimming')
      }
      
      running() {
        console.log('running')
      }
    }
    
    function swim(swimmer: ISwim) {
      swimmer.swimming()
    }
    
    const p = new Person()
    swim(p)   //swimming

交叉类型

交叉类型用 & 符号表示,表示需要满足多个类型的条件

type x = number & string           // 没有同时满足条件的值,所以当交叉的类型是基本数据类型时相当于 never 类型

// 常用于对象类型进行交叉
interface Animal {
  eating: () => void
}

interfact Dog {
  running: () => void
}

type NewType = Dog & Animal
const dog: NewType = {
  eating: function() {}
  running: function() {}
}

枚举类型

枚举类型是TypeScript特性之一:

  • 枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型
  • 枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型
  enum Direction {
      top,
      right,
      bottom,
      left
    }

枚举类型的值

枚举类型默认是有值的,比如上面的枚举,默认值是这样的

  enum Direction {
      top = 0,
      right = 1,
      bottom = 2,
      left = 3
    }
    // 当然也可以赋值给其他类型
    enum Direction {
      top = 'bottom',
      right = 'left',
      bottom = ,
      left = 
    }

泛型

泛型是方便增强函数的复用性(抽象)

 // 当我们需要封装一个函数, 传入一个参数,并且返回这个参数时。
    function foo (arg: number): number {      //实现了number类型,但不符合string、boolean等类型
      return arg            
    }
    // 使用 any
    function foo1(arg: any): any {
      return arg                 // 虽然可以实现需求,但这时候已经丢失了类型信息
    }
  	// 使用泛型可以完美解决问题
 	function foo2<T>(arg: T): T {
      return arg                
    }
    console.log(foo2(1))
    console.log(foo2(true))
    console.log(foo2('sad'))

当需要传入多个类型时

```typescript
function foo<T, E>(name: T, age: E) {
  console.log(name, age)
}

泛型接口

在定义接口的时候我们也可以使用泛型

 interface Animal<T> {
      name: T,
      friends: T[],
      sayHello: (value: T) => void
    }
    
    const cat: Animal<string> = {
      name: '蓝猫'
      friends: ['虹猫','咖啡猫']
      sayHello: function(value: string) {
        console.log(value)
      }
    }

泛型类

class Animal<T> {
  name: T
  shape: T
  
  constructor(name: T, shape: T) {
    this.name = name
    this. shape = shape
  }
}

const dog = new Animal('二哈','middle')
const cat = new Animal<string>('蓝猫', 'small')
const pig: Animal<string> = new Animal('天蓬', 'big')

泛型约束

有时候我们希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中

  • 比如string和array都是有length的,或者某些对象也是会有length属性的
 interface ILength {
      length: number
    }
    
    function getLength<T extends ILength>(args: T) {
      return args.length
    }
    console.log(getLength('abc'))         //3
    console.log(getLength([1,2,3]))       //3       
    console.log(getLength({name: 'zhangsan', age: 12, length: 180}))                    //180     

命名空间namespace

命名空间在TypeScript早期时,称之为内部模块,主要目的是将一个模块内部再进行作用域的划分,防止一些命名冲突的问题。

 export namespace Time {
      export function format(time: string) {
        return '2022-01-27'
      }
    }
    
    export namespace Prize {
      export function format(price: number) {
        return '九磅十五便士'
      }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值