TS知识点复盘

TS知识点复盘

TypeScript 官网地址:https://www.typescriptlang.org/zh/

什么是TypeScript

在聊TypeScript 之前先弄清楚两个概念:动态类型语言和静态类型语言。

动态类型语言:运行期间才会做数据类型检查的语言,不用给变量指定数据类型。如JavaScript、Ruby、Python等语言。

静态类型语言:数据类型检查发生在编译阶段,写程序时需要声明变量的数据类型。如C、C++、C#、Java等语言。

TypeScript把不注重类型的动态语言变成关注类型的静态语言。

所以到底什么是TypeScript?

  • 可以理解为可扩展的JavaScript 或JavaScript 的超集
  • 静态类型风格的类型系统
  • 从es6到es10甚至esnext的语法支持
  • 兼容各种浏览器,各种系统,各种服务器,完全开源

为什么要使用TypeScript

程序更容易理解

  • 问题:函数或者方法输入输出的参数类型,外部条件等
  • 动态语言的约束:需要手动调试等过程
  • 有了TypeScript:代码本身就可以回答上述问题

效率更高

  • 在不同的代码块和定义中进行跳转
  • 代码自动补全
  • 丰富的接口提示

更少的错误

  • 编译期间能够发现大部分错误
  • 杜绝一些比较常见的错误(如在undefined身上读取xx属性)

非常好的包容性

  • 完全兼容JavaScript
  • 第三方库可以单独编写类型文件
  • 大多数项目都支持TypeScript

一些小缺点

  • 增加了一些学习成本
  • 短期内增加了一些开发成本

安装TypeScript

Typescript 官网地址: https://www.typescriptlang.org/zh/

使用 nvm 来管理 node 版本: https://github.com/nvm-sh/nvm

安装 Typescript:

npm install -g typescript

使用 tsc 全局命令:

// 查看 tsc 版本
tsc -v
// 编译 ts 文件
tsc fileName.ts

原始数据类型

Typescript 文档地址:Basic Types

Javascript原始数据类型:

  • Boolean
  • Null
  • Undefined
  • Number
  • BigInt
  • String
  • Symbol
let isDone: boolean = false;

let age: number = 18;

let firstName: string = "Hyachin";
let message: string = `Hello,${firstName}`;

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

any 类型

let notSure: any = 4
notSure = 'maybe it is a string'
notSure = 'boolean'
// 在任意值上访问任何属性都是允许的:
notSure.myName
// 也允许调用任何方法:
notSure.getName()

Array和Tuple

Typescript 文档地址:Array 和 Tuple

//最简单的方法是使用「类型 + 方括号」来表示数组:
let arrOfNumbers: number[] = [1, 2, 3, 4]
//数组的项中不允许出现其他的类型:
//数组的一些方法的参数也会根据数组在定义时约定的类型进行限制:
arrOfNumbers.push(3)
arrOfNumbers.push('abc')

// 元祖的表示和数组非常类似,只不过它将类型写在了里面 这就对每一项起到了限定的作用
let user: [string, number] = ['viking', 20]
//但是当我们写少一项 就会报错 同样写多一项也会有问题
user = ['molly', 20, true]

interface接口

Typescript 文档地址:Interface

// 我们定义了一个接口 Person
interface Person {
  name: string;
  age: number;
}
// 接着定义了一个变量 viking,它的类型是 Person。这样,我们就约束了 viking 的形状必须和接口 Person 一致。
let Hyachin: Person ={
  name: 'Hyachin',
  age: 20
}

//有时我们希望不要完全匹配一个形状,那么可以用可选属性:
interface Person {
    name: string;
    age?: number;
}
let Hyachin: Person = {
    name: 'Hyachin'
}

//接下来还有只读属性,有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用 readonly 定义只读属性

interface Person {
  readonly id: number;
  name: string;
  age?: number;
}
let Hyachin: Person = {
  id: 1,
  name: "Hyachin",
};
Hyachin.id = 2;

函数

Typescript 文档地址:Functions

// 第一个例子,约定输入,约定输出
function add(x: number, y: number): number {
  return x + y;
}
// 函数本身的类型
const add2: (x: number, y: number) => number = add;
// interface 描述函数类型
interface ISum {
  (x: number, y: number): number;
}
const add3: ISum = add;

类型推论,联合类型 和 类型断言

Typescript 文档地址:类型推论 - type inference

联合类型 - union types

// 我们只需要用中竖线来分割两个
let numberOrString: number | string 
// 当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
numberOrString.length
numberOrString.toString()

类型断言 - type assertions

// 这里我们可以用 as 关键字,告诉typescript 编译器,你没法判断我的代码,但是我本人很清楚,这里我就把它看作是一个 string,你可以给他用 string 的方法。
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

// typescript 在不同的条件分支里面,智能的缩小了范围,这样我们代码出错的几率就大大的降低了。
function getLength2(input: string | number): number {
  if (typeof input === 'string') {
    return input.length
  } else {
    return input.toString().length
  }
}

枚举

在一定范围内的一系列常量用枚举表示

// 数字枚举,一个数字枚举可以用 enum 这个关键词来定义,我们定义一系列的方向,然后这里面的值,枚举成员会被赋值为从 0 开始递增的数字,
enum Direction {
  Up,
  Down,
  Left,
  Right,
}
console.log(Direction.Up)

// 还有一个神奇的点是这个枚举还做了反向映射
console.log(Direction[0])

// 字符串枚举
enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT',
}
const value = 'UP'
if (value === Direction.Up) {
  console.log('go up!')
}

泛型

基本使用

泛型 Generics

泛型(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]);

约束泛型

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法

function echoWithArr<T>(arg: T): T {
  console.log(arg.length)
  return arg
}

// 上例中,泛型 T 不一定包含属性 length,我们可以给他传入任意类型,当然有些不包括 length 属性,那样就会报错

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

echoWithLength('str')
const result3 = echoWithLength({length: 10})
const result4 = echoWithLength([1, 2, 3])

泛型与类和接口

class Queue {
  private data = [];
  push(item) {
    return this.data.push(item)
  }
  pop() {
    return this.data.shift()
  }
}

const queue = new Queue()
queue.push(1)
queue.push('str')
console.log(queue.pop().toFixed())
console.log(queue.pop().toFixed())

//在上述代码中存在一个问题,它允许你向队列中添加任何类型的数据,当然,当数据被弹出队列时,也可以是任意类型。在上面的示例中,看起来人们可以向队列中添加string 类型的数据,但是那么在使用的过程中,就会出现我们无法捕捉到的错误,

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

//泛型和 interface
interface KeyPair<T, U> {
  key: T;
  value: U;
}

let kp1: KeyPair<number, string> = { key: 1, value: "str"}
let kp2: KeyPair<string, number> = { key: "str", value: 123}
let arr: number[] = [1, 2, 3];
let arr2: Array<number> = [1, 2, 3];

类型别名、字面量和交叉类型

类型别名 Type Aliases

类型别名,就是给类型起一个别名,让它可以更方便的被重用。

let sum: (x: number, y: number) => number
const result = sum(1,2)
type PlusType = (x: number, y: number) => number
let sum2: PlusType

// 支持联合类型
type StrOrNumber = string | number
let result2: StrOrNumber = '123'
result2 = 123

// 字符串字面量
type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Up'

交叉类型 Intersection Types

interface IName  {
  name: string
}
type IPerson = IName & { age: number }
let person: IPerson = { name: 'hello', age: 12}

type和interface的区别

相同点:

  • 都可以描述一个对象或者函数
  • 都允许拓展(类型别名使用交叉运算符&来扩展,接口通过extends方式来扩展)

不同点:

  • type 可以声明基本类型别名,联合类型,元组等类型,而interface只能用于定义对象类型
  • interface 能够声明合并,而type不行

声明文件

自身项目定义声明文件

声明文件需要遵循后缀为.d.ts的格式

// 它里面没有任何的实际实现代码,只有类型声明
// 只有类型 - 比如 interface,function 或者 class等等

// declare function axios(url: string): string;
interface IAxios {
  get: (url: string) => string;
  post: (url: string, data: any) => string;
}
declare const axios: IAxios;

第三方库

可以在@types 搜索声明库搜索看看是否需要安装@types文件

配置文件

配置文件的官方文档

{
  "files": ["test.ts", "test.d.ts"], // 当运行tsc的时候,test.ts文件会变编译成js
  // 配置怎么编译的选项
  "compilerOptions": {
    "outDir": "./output", // 编译好的文件输出到哪里
    "module": "ESNext", // 输出的module的类型
    "target": "ES5", // 符合怎样的ES标准
    "declaration": true // 每个ts文件都会生成对应的.d.ts文件
  }
}

你可能感兴趣的:(前端,javascript,typescript,前端)