美文网首页
1. typescript 语法学习笔记

1. typescript 语法学习笔记

作者: yaoyao妖妖 | 来源:发表于2021-05-18 15:33 被阅读0次
  1. 动态类型语言(Dynamically Typed Language)运行期间才会作类型检查;
  2. 静态类型语言(Statically Typed Language)编译期间进行类型检查;
Ts简介:
  1. typescript 可以理解为 可扩展的 js 或者是 js 的超集;
  2. 静态类型风格的类型系统;
  3. 从es6到es10 甚至是 esnext 的语法支持;
  4. 兼容各种浏览器,各种系统,各种服务器,完全开源;

为什么要使用 ts,解决了什么问题,对我有什么提高?

  1. 因为类型,使得程序更加容易理解;
  2. 效率更高,支持代码块之间的跳转和代码补全;
  3. 更少的错误(编译期间能发现更多的错误);
  4. 非常好的包容性,完全兼容js,第三方库可以单独编写类型文件;
一、原始类型和 Any类型:

primitive value(原始类型:值不可变)
JS: Boolean 、Null、Undefined、Number、String、Bigint、Symbol
TS: boolean 、null、undefined、number、string

非原始类型
JS: Object
TS: interface、any(任意类型)
代码示例:

let isDone: boolean = false
let age: number = 10
let firstName: string = 'viking'
let message: string = `Hello, ${firstName}`
let u: undefined = undefined
let n: null = null
let num: number = undefined

let notSure: any = 4
notSure = 'maybe a string'
notSure = true

notSure.myName
notSure.getName()
二、数组和元组:

Array && Tuple
代码示例:

let arrOfNumbers: number[] = [1,2,3]
arrOfNumbers.push(3)

function test() {
  console.log(arguments);
  // arguments类数组, 有一些数组的属性,但是不能调用数组的方法
}
// 元组在一定程度上代表限制了类型的数组
let user: [string, number] = ['viking', 20]
三、interface: 定义 object 类型, 对对象的进行描述

readonly 只读
? 代表可选属性

interface Person {
  readonly id: number;
  name: string;
  age?: number;
}

let viking: Person = {
  id: 1,
  name: 'viking',
  age: 20,
}
四、函数:

在ts中凡是在冒号后面都是在声明类型;
在参数后面用冒号约定输入表示参数类型;
在输入后面用冒号约定输出表示返回值类型;
? 代表参数可选;可选参数必须放在最后面,避免程序对参数的判断发生错乱;

// 函数声明写法
function add = (x: number, y: number, z?: number): number  {
  if (typeof z === 'number') {
    return x + y + z
  } else {
    return x + y
  }
}
// 函数表达式 => add 获得了一个类型
const add = (x: number, y: number, z?: number): number => {
  if (typeof z === 'number') {
    return x + y + z
  } else {
    return x + y
  }
}
// 赋值
let add2: (x: number, y: number, z?: number): number =>number = add;
// interface 描述函数类型
interface ISum {
  (x: number, y: number, z?: number): number
}
// 赋值
let add2: ISum = add

五、类型推论,联合类型和类型断言
4762ed4db6acc1d6ad17cfa014ac1cb.png
// type inference: ts 会在没有明确声明一个类型的时候自动推断一个类型,再次赋值的时候如何和之前推论的值不一致,就会出现提示;
let str = 'str'
str=123 (警告如上图)

// union types (多种类型中的一种),当我们不确哪种类型的时候,只能访问联合类型的共有类型
let numberOrString: number | string

// 但是我们的确想要访问这个类型的方法的时候 使用 as 强制把这个变量看成某种类型,并不是类型转化
function getLength(input: string | number): number {
  const str = input as string
  if (str.length) {
    return str.length
  } else {
    // 类型断言 input as number
    const number = input as number
    return number.toString().length
  }
}

//或者是使用 type guard 解决,当遇到联合类型的时候,使用if语句可以智能的缩小类型的范围,
//(typeof 关键字)
function getLength2(input: string | number): number {
  if (typeof input === 'string') {
    return input.length
  } else {
    return input.toString().length
  }
}
六、Class
  1. 在JS中使用构造函数和原型链来实现继承;
  2. ES6 中语法糖=>原理还是原型链

类: 定义个一切失误的抽象特点;
对象:类的实例;
面向对象(OOP)三大特性:封装、继承、多态
封装: 隐藏内部实现逻辑;
继承: 子类、父类
多态:相同的方法,不同的响应

class Animal {
  // 限制属性只读
  readonly name: string;
  constructor(name) {
    this.name = name
  }
  run() {
    return `${this.name} is running`
  }
}
const snake = new Animal('lily')
console.log(snake.run())

// extends 继承
class Dog extends Animal {
  bark() {
    return `${this.name} is barking`
  }
}

const xiaobao = new Dog('xiaobao')
console.log(xiaobao.run())
console.log(xiaobao.bark())

class Cat extends Animal {
  // 静态属性
  static categories = ['mammal']
  constructor(name) {
    super(name)
    console.log(this.name)
  }
  run() {
    return 'Meow, ' + super.run()
  }
}
const maomao = new Cat('maomao')
console.log(maomao.run())
console.log(Cat.categories)

TS 如何增强类:
public 修饰的属性或者方法是共有的
private 修饰的属性或者方法是私有的
protected 修饰的属性或者方法是受保护的(子类可以调用,实例对象不行)

七、类和接口

// interface 对类的部分行为进行抽象,替代部分相同功能但是又不是子类和父类关系的情景;

interface Radio {
  switchRadio(trigger: boolean): void;
}
interface Battery {
  checkBatteryStatus(): void;
}
// 接口之间的继承
interface RadioWithBattery extends Radio {
  checkBatteryStatus(): void
}
// Car  implements (实现了) Radio 的方法
class Car implements Radio{
  switchRadio(trigger: boolean) {
  }
}

class Cellphone implements RadioWithBattery {
  switchRadio(trigger: boolean) {
  }
  checkBatteryStatus() {
  }
}
八、枚举

在一定范围内的一系列的常量:使用枚举


8eb52038d9d22786f2091ed2fafa607.png
// 数字枚举,默认从 0 开始自动递增的数据
const enum Direction {
  Up = 10,
  Down,
  Left,
  Right,
}
// 原理如上图
 console.log(Direction.up); // 10
 console.log(Direction[0]);  // Up 
// 字符串枚举,const 常量枚举,会提升性能,会直接把值翻译为结果,不会把枚举翻译为js代码, 如下图,并不是所有的枚举都可以使用常量枚举
const enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}
const value = 'UP'
if (value === Direction.Up) {
  console.log('go up!')
}
549d7268c58d7e00aaa59545126ec4d.png
九、泛型

定义函数/类/接口时,不预先指定类型,而在使用的时候去推断类型,相当于一个占位符;
// 为了解决函数在传参和返回值确定情况下,使用场景局限性的问题,使用 any 会导致代码可读性较差;

// 根据传入的类型,类型推断
function echo<T>(arg: T): T {
  return arg
}
const result = echo(true)

// 传入多个值的泛型
function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])

function echoWithArr<T>(arg: T[]): T[] {
  console.log(arg.length)
  return arg
}
const arrs = echoWithArr([1, 2, 3])

// 约束泛型
interface IWithLength {
  length: number
}
// 必须是拥有length属性的对象
function echoWithLength<T extends IWithLength>(arg: T): T {
  console.log(arg.length)
  return arg
}

const str = echoWithLength('str')
const obj = echoWithLength({ length: 10, width: 10})
const arr2 = echoWithLength([1, 2, 3])

// 泛型在Class中的使用
class Queue<T> {
  private data = [];
  push(item: T) {
    return this.data.push(item)
  }
  pop(): T {
    return this.data.shift()
  }
}
const queue = new Queue<number>()
queue.push(1)
console.log(queue.pop().toFixed())  // toFixed 只能是number类型

// 泛型在 interface 中的使用
interface KeyPair<T, U> {
  key: T
  value: U 
}
let kp1: KeyPair<number, string> = { key: 1, value: "string"}
let kp2: KeyPair<string, number> = { key: 'str', value: 2 }
let arr: number[] = [1,2,3]
let arrTwo: Array<number> = [1,2,3]
十、类型别名、字面量、交叉类型
// type aliase => 解决部分类型较长的问题 关键字 type 
let sum: (x: number, y: number) => number
const result = sum(1,2)
type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result2 = sum2(2, 3)

type StrOrNumber = string | number
let result3: StrOrNumber = '123'
result3 = 123

// 字面量 只能是primative value
const str: 'name' = 'name'
const number: 1 = 1
type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Left'

// 交叉类型 和 联合类型相对应 (非)
为了实现对象组合的扩展
interface IName {
  name: string
}
type IPerson = IName & { age: number }
let person: IPerson = { name: '123', age: 123 }
十一、TS内置类型
//global objects
const a: Array<number> = [1,2,3]
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('abc')

//build-in object
Math.pow(2, 2)

//DOM and BOM
let body = document.body
let allLis = document.querySelectorAll('li')
allLis.keys()

document.addEventListener('click', (e) => {
  e.preventDefault()
})

//Utility Types 功能类型
interface IPerson {
  name: string
  age: number
}
// Partial 返回的类型可以把类型属性变为可选
let viking: IPerson = { name: 'viking', age: 20 }
type IPartial = Partial<IPerson>
let viking2: IPartial = { name: 'viking' }

// IOmit 返回的类型可以忽略传入类型的某个属性
type IOmit = Omit<IPerson, 'name'>
let viking3: IOmit = { age: 20 }

相关文章

网友评论

      本文标题:1. typescript 语法学习笔记

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