Typescript基础知识,带你快速入门

Typescript 基础

1、什么是Typescript?

编程语言有以下两种类型:

  • 动态类型语言: 只有在运行时才能确定变量的类型 (例如JS / Python
  • 静态类型语言: 在编译时就已经确定了变量类型,以及能够检查出错误(例如 c++ / c / c# / java

TS 的特点:

  • Javascript that scales (JS的超集)
  • 静态类型风格的类型系统
  • es6es10甚至是esnext的语法支持
  • 兼容各种浏览器,各种系统,各种服务器,完全开源

2、为什么要使用 TS ?

  • 程序更容易理解:容易知道函数的输入输出类型及外部条件,出错几率小
  • 编译期间能够发现大部分错误
  • 完全兼容JS

3、基础使用

新建 test.ts 文件

const hello = (name:string) => {
  return `Hello ${name}`
}

hello('Axton Tang')

使用 tsc 命令进行编译成 js 文件

该函数要求传入的参数为 string 类型,如何传入其他类型,编译则会报错

(1)原始数据类型和 Any 类型

let isDone: boolean = true

let age: number = 20

let firstName: string = 'Axton'
let message: string = `hello ${firstName}`
message = null    // null 和 undefined 是任何类型的子类型

let n: null = null
let u: undefined = undefined

let notSure: any = 20   // 当不确定传入的参数是什么类型时,可以用 any (不建议使用)
notSure = 'maybe a string'
notSure = true

notSure.myName
notSure.getName()

(2)数组和元组

let arrOfNumber: number[] = [1,2,3]   //定义number类型的数组
arrOfNumber.push(3)

function test () {
  console.log(arguments)    //类数组
}

let user: [string, number] = ['Axton', 20]    // 定义元组,与数据类型只能一一对应
user.push('Tang')   // 只能是上面两种数据类型之一

(3)Interface 接口

对对象的形状进行描述

interface Person {
  name: string,   //定义接口的属性
  age?: number    //如何该属性可选就可以改为 '?:' 这样如何实现该属性也不会报错
  readonly sex: string    //设置只读属性
}

let Axton: Person = {   //声明变量, 实现这个接口
  name: 'Axton Tang',   // 必须与接口的属性一致
  age: 20,
  sex: '男'
}

(4)函数

const add = (x: number, y:number, z?: number): number => {
  if (typeof z === 'number') {
    return x+y+z
  } else {
    return x+y
  }
}

add(1,2,3)

interface ISum {    //用接口来描述函数类型
  (x: number, y: number, z?: number): number
}

let add2: ISum = add

(5)类型推论 联合类型和 类型断言

1、类型推论: 在没有明确指明变量的类型时,TS 会根据你第一次的赋值推测出这个变量的类型,之后再进行赋值成其他类型会报错

2、联合类型:

当变量是联合类型时,只能使用联合类型共有的属性和方法

let str = 'string'

// 联合类型
let numberOrString: number | string
numberOrString = 123
numberOrString = 'Axton'

3、类型断言:

// 由于使用联合类型后只能用共有属性和方法,但是有时候想用特有的方法,就可以使用类型断言
// 方法一
function getLength(input: string | number): number {
  const str = input as string		// 注意: 此处并不是把它转化成这个类型
  if (str.length) {
    return str.length
  } else {
    const number = input as number
    return number.toString().length
  }
}

// 方法二
//type guard
function getLength2(input: string | number): number {
  if (typeof input === 'string') {		// 使用条件判断会自动缩小范围,可以使用该类型特有方法
    return input.length
  } else {
    return input.toString().length
  }
}

(6)类 Class

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())

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)

(7)类和接口

interface Redio {
  switchRedio(trigger: boolean):void;
}

interface Battery {
  checkBatteryStatus(): void;
}

interface RedioWithBattery extends Redio {		// 接口继承接口
  checkBatteryStatus(): void;
}

class car implements Redio {
  switchRedio(trigger: boolean) {
	...
  }
}

class cellPhone implements RedioWithBattery {
  switchRedio(trigger: boolean) {
	...
  }
  checkBatteryStatus() {
	...
  }
}

(8)枚举(Enum)

enum Direction {		// 如果在enum前面加上 const 则为常量枚举
  up = 10,   // 值默认从 0 开始, 此处赋值后从 10 开始增加
  down,
  left,
  right
}

console.log(Direction.up)   // 值为 10 


enum Direction2 {
  str1 = 'STR1',
  str2 = 'STR2'
}

const value = 'STR1'
if (value === Direction2.str1) {
  console.log('go str1')
}

(9)泛型(Generics)

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])

约束泛型

由于使用泛型时不确定参数的类型,所以不能直接使用传入参数类型的方法和属性,使用时继承需要用到的接口的方法和属性即可使用。

interface IWithLength {
  length: number
}

function echoWithLength<T extends IWithLength> (arg: T): T {
  console.log(arg.length)
  return arg
}

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

泛型在类中的使用

class Queue<T> {
  private data = []
  push (item: T) {
    return this.data.push(item)
  }
  pop () {
    return this.data.shift()
  }
}

const queue = new Queue<number>()

queue.push(123)
console.log(queue.pop().toFixed())

泛型在接口中的使用

interface KeyPair<T, U> {
  key: T,
  value: U
}

let kp1: KeyPair<string, number> = {key: 'string', value: 20}
let kp2: KeyPair<number, string> = {key: 10, value: 'str'}

// 定义 number 类型的数组的两种方法
let arr1: number[] = [1, 2, 3]
let arr2: Array<number> = [1, 2, 3]

(10)类型别名、字面量、交叉类型

// 类型别名
type plusType = (x: number, y: number) => number
let sum: plusType
const result1 = sum(1, 2)

type numOrStr = number | string
let result2: numOrStr = 'str'
result2 = 123

// 字面量
const str: 'name' = 'name'
const number: 1 = 1

type Directions = 'up' | 'down' | 'left' | 'right'
let toWhere: Directions = 'up'

// 交叉类型
interface IName {
  name: string
}

type IPerson =  IName & {age: number}
let person: IPerson = {name: 'Axton', age: 20}

(11)声明文件

在使用一些第三方库的时候,ts 并不知道我们引入的是什么文件,所以会报错

此时需要定义声明文件

// 声明文件一般放到以 .d.ts 结尾的文件中
declare var jQuery: (selector: string) => any;

// 例:使用
jQuery('#foo')

很多第三方库都会有现成的声明文件,我们通过 npm 安装就好

你可能感兴趣的:(typescript)