TypeScript2

继承接口

  • 如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用
  • 比如,这两个接口都有 x、y 两个属性,重复写两次,可以,但很繁琐 ,直接继承就不用写了

例子:


interface Point2D { x: number; y: number }
interface Point3D { x: number; y: number; z: number }

interface Point2D { x: number; y: number }
// 继承 Point2D
interface Point3D extends Point2D {
        z: number
 }

用type实现继承效果

  // & 与连接符: 既要满足前面的也要满足后面的
  // | 或连接符: 满足其中一个即可
  type Student = {
    score: number
    sleep: () => void
  } & Person

  const s2: Student = {
    username: '刘狄威',
    age: 28,
    gender: '未知',
    sayHi() {
      console.log('大嘎好!')
    },
    score: 80,
    sleep() {
      console.log('我在睡觉')
    },
  }

元组类型

元组类型是另一种类型的数组,它确切地知道包含多少个元素,以及特定索引对应的类型

let position: [number, number] = [39.5427, 116.2317]

类型推论

根据初始化的值 定属性。

  • 在 TS 中,某些没有明确指出类型的地方,TS 的类型推论机制会帮助提供类型
  • 换句话说:由于类型推论的存在,这些地方,类型注解可以省略不写

发生类型推论的 2 种情况:

  • 1. 声明变量并初始化时
  • 2. 决定函数返回值时

// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number): number {
return num1 + num2
}

字面量类型

任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用

字面量: { name: 'jack' } [] 18 20 'abc' false function() {}

使用模式:字面量类型配合联合类型一起使用

使用场景:用来表示一组明确的可选值列表

比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个

// 使用自定义类型:
type Direction = 'up' | 'down' | 'left' | 'right'
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,会有类型提示

changeDirection('up')

枚举类型

枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值

枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个

// 创建枚举
enum Direction { Up, Down, Left, Right }
// 使用枚举类型
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,需要应该传入:枚举 Direction 成员的任意一个
// 类似于 JS 中的对象,直接通过 点(.)语法 访问枚举的成员
changeDirection(Direction.Up)

解释:

1. 使用 enum 关键字定义枚举

2. 约定枚举名称以大写字母开头

3. 枚举中的多个值之间通过 , (逗号)分隔

4. 定义好枚举后,直接使用枚举名称作为类型注解

可以键值对相互查找。

// 枚举: 如果不设置值, 默认从 0 开始
  // type Direction = '上' | '下' | '左' | '右'
  enum Direction {
    Up = 'Up',
    Down = 'Down',
    Left = 'Left',
    Right = 'Right'
  }

  // enum Direction {
  //   Up, // 0
  //   Down, // 1
  //   Left, // 2
  //   Right // 3
  // }
  // 枚举内部还做了一个事情: 可以通过键找值, 也可以通过值找键
  // console.log(Direction)

  function changeDirection(direction: Direction) {
    console.log(direction)
  }

  changeDirection(Direction.Up)
  changeDirection(Direction.Down)
  changeDirection(Direction.Left)
  changeDirection(Direction.Right)

  // 后端给前端的一些属性都是 0 1 2 3 这样的数字, 例如: 性别
  // 如果后端给的是 100 上  101 下  102 左  103  右

any类型

原则:不推荐使用 any!这会让 TypeScript 变为 “AnyScript”(失去 TS 类型保护的优势) 因为当值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示

let obj: any = { x: 0 }
obj.bar = 100
obj()
const n: number = obj

类型断言


  // 页面上有一个 id 为 link 的 a 标签
  // 我们知道它是 a 标签
  // 但是 TS 不知道
  // document.getElementById 的返回值是 HTMLElement
  // 而 HTMLElement 身上没有 href
  // 类型断言: 强行指定获取到的结果类型
  const a = document.getElementById('link') as HTMLAnchorElement
  const box = document.getElementById('box') as HTMLDivElement
  const pp = document.getElementById('pp') as HTMLParagraphElement
  const img = document.getElementById('avatar') as HTMLImageElement

  // img.src

  // const result = document.createElement('img')

  // console.log(a.href)
  // if (a) {
  //   console.log(a.href)
  // }
  // a && a.href
  // 总结: 当函数获取到的结果类型较为宽泛时, 我们又知道具体类型, 就可以使用断言强行指定类型

TypeScript泛型

  • 泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而实现复用,常用于:函 数、接口、class 中
  • 需求:创建一个 id 函数,传入什么数据就返回该数据本身(也就是说,参数和返回值类型相同) 、
function id(value: number): number { return value }
  • 上面的函数只能接受number类型,而无法接受其他类型,为了安全我们要选用泛型 ,就是让其他的,类型传入函数依然不发生错误。
function id(value: any): any { return value }
  • 泛型在保证类型安全(不丢失类型信息)的同时,可以让函数等与多种不同的类型一起工作,灵活可 复用

泛型-泛型函数

function id(value: Type): Type { return value }
function id(value: T): T { return value }
  • 1. 语法:在函数名称的后面添加 <> (尖括号),尖括号中添加类型变量,比如此处的 Type
  • 2. 类型变量 Type,是一种特殊类型的变量,它处理类型而不是值
  • 3. 该类型变量相当于一个类型容器,能够捕获用户提供的类型(具体是什么类型由用户调用该函 数时指定)
  • 4. 因为 Type 是类型,因此可以将其作为函数参数和返回值的类型,表示参数和返回值具有相同 的类型
  • 5. 类型变量 Type,可以是任意合法的变量名称
const num = id(10)
const str = id('a')

1. 语法:在函数名称的后面添加 <> (尖括号),尖括号中指定具体的类型,比如,此处的 number

2. 当传入类型 number 后,这个类型就会被函数声明时指定的类型变量 Type 捕获到

3. 此时,Type 的类型就是 number,所以,函数 id 参数和返回值的类型也都是 number

  • 同样,如果传入类型 string,函数 id 参数和返回值的类型就都是 string
  • 这样,通过泛型就做到了让 id 函数与多种不同的类型一起工作,实现了复用的同时保证了类型安全

简化泛型函数调用

// 省略  调用函数
let num = id(10)
let str = id('a')

因为有ts有类型推断机制,我们可以省略类型,但是要注意, 当编译器无法推断类型或者推断的类型不准确时,就需要显式地传入类型参数 。

约数泛型

在正常情况下,泛型可以代表多种类型,这会导致无法访问任何属性。就像你调用泛型函数传入一个string类型的参数,而你却不能用length属性,那么就要加约束。

指定更加具体的类型

// 指定更加明确的类型: T类型的数组, val 确定就是一个数组了, 所以可以用 length
   function getIds(val: T[]) {
    console.log(val.length) // val: 已经明确是一个数组了, 所以自然会有数组的所有属性
    return val
   }

添加约束

// 创建一个接口
interface ILength { length: number }
// Type extends ILength 添加泛型约束
// 解释:表示传入的 类型 必须满足 ILength 接口的要求才行,也就是得有一个 number 类型的 length 属性
function id(value: Type): Type {
console.log(value.length)
return value
}

类型收缩: 比较麻烦


   function getId(val: T) {
   if (typeof val === 'string') {
     console.log(val.length) // 报错: T 是一个未知的类型, 所以无法得知它到底有没有 length
   } else if (typeof val === 'number') {
     val.toFixed()
    }
    return val
 }

添加约束

// 定义接口
  interface ILength {
    length: number
    // sayHi: () => void
  }

  // 添加约束: 给泛型找爸爸
  function getId(val: T) {
    console.log(val.length)
    return val
  }

  console.log(getId('abcd'))
  // console.log(getId(123))
  // console.log(getId(true))

多个类型变量

泛型的类型变量可以有多个,并且类型变量之间还可以约束(比如,第二个类型变量受第一个类型变量约 束) 比如,创建一个函数来获取对象中属性的值:

function getProp(obj: Type, key: Key) {
return obj[key]
}
let person = { name: 'jack', age: 18 }
getProp(person, 'name')
  1. 添加了第二个类型变量 Key,两个类型变量之间使用 , 逗号分隔。
  2. keyof 关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型。
  3. 本示例中 keyof Type 实际上获取的是 person 对象所有键的联合类型,也就是: 'name'
    | 'age'
  4. 类型变量 Key 受 Type 约束,可以理解为:Key 只能是 Type 所有键中的任意一个,或者说只能访问对象中存在的属性

泛型接口

泛型接口:接口也可以配合泛型来使用,以增加其灵活性,增强其复用性

interface IdFunc {
id: (value: Type) => Type
ids: () => Type[]
}
let obj: IdFunc = {
id(value) { return value },
ids() { return [1, 3, 5] }
}

{
  // 泛型接口   为了复用  
  interface Student {
    id: number
    name: T
    hobby: T[]
  }

  let s1: Student = {
    id: 123,
    name: '小刘',
    hobby: ['抽烟', '喝酒', '写圣杯布局']
  }

  const s2: Student = {
    id: 123,
    name: 0,
    hobby: [1, 2, 3, 4]
  }

  const arr1: number[] = [1, 2, 3]
  const arr2: Array = [1, 2, 3]
  const arr3: Array = ['1', 'a', 'c']
  // arr2.push('abc')
  // arr3.push(123)
}

你可能感兴趣的:(Ts,前端,javascript,开发语言)