美文网首页
typescript基础

typescript基础

作者: noyanse | 来源:发表于2020-06-06 19:26 被阅读0次

/**
 * @description 原始数据类型
 */

let isDone: boolean = false

let age: number = 20

// 二进制
let binaryNumber: number = 0b1111

let firstName: string = 'hello'
// 模版字符串
let message: string = `my name is ${firstName}`

// undefined 和 null 是所有类型的子类型
let u: undefined = undefined
let n: null = null
let num: number = undefined // number类型可以赋值为 undefined

/**
 * @description any类型 和 联合类型 |
 */

// 无法确定是什么类型 any 允许赋值为任意类型
// 当有明确类型时,不要用any
let notSure: any = 3
notSure = 'string'
// notSure.getName() // 可以调用方法 也没有报错

// 允许一部分类型 | 表示联合类型
let numberOrString: number | string = 123

/**
 * @description array 和 tuple
 */

 // 定义数组里面元素的类型
let arrOfNumbers: number[] = [1, 3, 4]
arrOfNumbers.push(5) // 数组的方法也会限制

// 类数组
function test() {
  console.log(arguments) // 类数组,有数组的一定属性
  // 但是没有数组的方法
  // let htmlCollection: NodeList
}

// 数组将同一种类型的数据聚合到一起
// 不同类型的数据用tuple
let tupleArr: [string, number] = ['hello', 1]

/**
 * @description interface接口
 * 定义js中 对象类型
 * 1 对对象的形状(shape)进行描述 如属性方法
 * 2 对类进行抽象 duck typing
 * 
 * 首字母一般大写
 */
interface Persons {
  readonly id: number // 只读 不可再次赋值 readonly 用在属性上 const用在变量上,二者相似
  name: String
  age?: Number
}

let viking: Persons = {
  id: 1,
  name: 'argen',
}

/**
 * @description 函数 和 类型推断
 */

 // 函数声明写法
 function add (x: number, y: number): number {
   return x + y
 }

 let result = add(2, 3)

 // 可选参数 只能放最后
 function add1 (x: number, y: number, z?: number): number {
   if (typeof z === 'number') {
    return x + y + z
   }
   return x + y
}

// 可选参数还可用es6的默认值写法
function add2 (x: number, y: number, z: number = 10): number {
  if (typeof z === 'number') {
   return x + y + z
  }
  return x + y
}

let result1 = add1(2, 3)
let result2 = add1(2, 3, 4)

// 函数表达式写法
// add3也是有类型的,是个函数类型
const add3 = function (x: number, y: number, z: number = 10): number {
  if (typeof z === 'number') {
   return x + y + z
  }
  return x + y
}
// ts直接推断出add3是函数类型
const add4: (x: number, y: number, z?: number) => number = add

/**
 * @description class
 */
class Animal {
  public name: string
  constructor (name: string) {
    this.name = name
  }
  run () {
    return `${this.name} is running`
  }
}
const snake = new Animal('snake')
console.log(snake.run())

// 继承 拥有了父类的属性和方法,并且有了自己的方法
class Dog extends Animal {
  bark () {
    return `${this.name} is barking`
  }
}
const dog = new Dog('dog')
console.log(dog.bark())

// 继承 方法重写
class Cat extends Animal {
  constructor (name) {
    super(name)
    console.log(this.name)
  }
  run () {
    return `miaomiao - ` + super.run()
  }
}
const cat = new Cat('cat')
console.log(cat.run())

/**
 * @description 修饰符
 * public
 * pravite 只能自己访问,子类也不能调用
 * protected 只有自己和子类可以访问
 * readonly 只能读 不能写
 * 静态属性和方法 不需要实例化 可直接调用
 * static 和
 */
class Animal1 {
  public name: string
  static categories: string[] = ['animal', 'bird']
  static isAnimal (a) {
    return a instanceof Animal1
  }
  constructor (name: string) {
    this.name = name
  }
  run () {
    return `${this.name} is running`
  }
}
const lion = new Animal1('lion')
console.log(lion.run())
console.log(Animal1.categories)
console.log(Animal1.isAnimal(lion))


/**
 * @description 类和接口
 * 接口对类的一部分类型进行抽象
 * 类 实现 接口
 */

 interface Radio {
   // 参数和返回值类型定义
   switchRadio (): void
 }

 interface Battery {
   checkBatteryStatus()
 }

 // 接口之间可以有继承关系, 合并Radio 和 Batter接口
 interface RadioWithBattery extends Radio {
  checkBatteryStatus()
 }

 // 通过 interface告诉手机和汽车都要实现这个功能
class Car implements Radio {
  switchRadio () {
  }
}
class Cellphone implements Radio, Battery {
  switchRadio () {
  }
  checkBatteryStatus () {

  }
}
class Cellphone1 implements RadioWithBattery {
  switchRadio () {
  }
  checkBatteryStatus () {

  }
}

/**
 * @description 枚举 Enum
 * 一系列常量
 */
enum Direction {
  Up = 10, // 接下来的项会递增
  Down,
  Left,
  Right
}
console.log(Direction.Up)
console.log(Direction[10])

// 加一个 const 就是一个常量枚举 提升性能
// 只有常量值可以作为常量枚举
const enum Direction1 {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT'
}
const value1 = 'UP'
if (value1 === Direction1.Up) {
  console.log('go up')
}

/**
 * @description 泛型 Generics
 * ts最难的点
 * 解决怎么样的问题:
 *  函数参数的值类型与返回类型统一
 * <> 尖括号里面写泛型的名称 相当于一个占位符
 */
function echo <T> (arg: T): T {
  return arg
}
const resultEcho: string = echo('str')
console.log(resultEcho)

// 调换一下位置,返回2项
function swap<T, U> (tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]]
}
const resSwap = swap(['string', 123])
console.log(resSwap)

/**
 * @description 约束泛型
 */

 // 事先不知道参数什么类型,所以不能使用它的方法
 function echoWithArr<T> (arr: T): T {
  //  console.log(arr.length)
  return arr
 }

 // 设定是数组,才能使用数组的方法 返回也是T[]
 function echoWithArr1<T> (arr: T[]): T[] {
   console.log(arr.length)
  return arr
 }

 const arrs = echoWithArr1([1, 2, 3])

 // 对泛型约束 定义一个接口,extends这个接口
 interface IWithLength {
   length: number
 }
 function echoWithLength<T extends IWithLength> (arg: T) : T {
  console.log(arg.length)
  return arg
 }

 // 只要有length属性,就符合这个约束,duck typing啦⁄⁄⁄⁄⁄
 const str = echoWithLength('str')
 const obj = echoWithLength({ length: 10})
 const arr2 = echoWithLength([1, 2, 3])

 /**
 * @description 泛型在其他场景重的使用
 */
class Queue {
  private data = []
  push (item) {
    return this.data.push(item)
  }
  pop () {
    return this.data.shift()
  }
}

const queue = new Queue()
// 可以push各种类型的值
queue.push(1)
queue.push('str')
// 运行的时候会捕获错误,但是ts并没报错
// 这里只调用数字上的方法会报错
console.log(queue.pop().toFixed())
console.log(queue.pop().toFixed())

// 解决方法1 不实用
class Queue1 {
  private data = []
  push (item: number) {
    return this.data.push(item)
  }
  pop (): number {
    return this.data.shift()
  }
}

// 解决方法2 希望传入什么输出什么 用泛型
// 在实力化的时候约定参数类型
class Queue2<T> {
  private data = []
  push (item: T) {
    return this.data.push(item)
  }
  pop (): T {
    return this.data.shift()
  }
}
const queue2 = new Queue2<number>()

queue2.push(1)
// queue2.push('str') // 这里就会报错了

// interface用泛型描述
interface KeyPair<T, U> {
  key: T
  value: U
}
let kp1: KeyPair<number, string> = {
  key: 1,
  value: 'str'
}

// 描述数组
let arr: number[] = [1, 2, 3]
// 可以也成
let arrTwo: Array<number> = [1, 2, 4]

// 描述函数
function plus(a: number, b: number): number {
  return a + b
}
// 这个接口就比较通用了
interface IPlus<T> {
  (a: T, b: T): T
}

const a: IPlus<number> = plus // 此时的a由于类型推断是函数类型


/**
 * @description 类型别名和类型断言
 * type aliases
 */
function sum (x: number, y: number): number {
  return x + y
}

const sum2: (x: number, y: number) => number = sum
// 抽象函数类型
type PlusType = (x: number, y: number) => number
const sum3: PlusType = sum

// 在联合类型下的应用
type NameResolver = () => string
type NameOrResolver = string | NameResolver
function getName (n: NameOrResolver): string {
  if (typeof n === 'string') {
    return n
  } else {
    return n()
  }
}

// type assertion 类型断言
// 在不知道返回值类型的时候就要使用他的属性和方法

function getLength (input: string | number): number {
  // input.length
  const str = input as String
  if (str.length) {
    return str.length
  }

  // 简单写法
  if ((<string>input).length) {
    // 整体就变成了一个断言
    return (<string>input).length
  }
}


/**
 * @description 引用第三方库 声明文件
 */

 // 通常会把这个放在单独的文件中
 declare var jQuery: (selector: string) => any
 

相关文章

网友评论

      本文标题:typescript基础

      本文链接:https://www.haomeiwen.com/subject/cfjftktx.html