【TypeScript】 笔记

目录

一、什么是 TypeScript

二、为什么要用 TypeScript

三、环境安装

1. 方式一

2. 方式二

四、语法

1. 变量

2. 数据类型的约束

2.1. undefined 与 null

2.2. 联合类型

2.3. any

2.4. 数组

2.5. 对象

3. 函数的约束

4. interface

5. 类

6. 修饰符

7. 抽象类 abstract

8. implement

9. 泛型

10. 装饰器

11. 注释


一、什么是 TypeScript

  • TypeScript 是微软推出的一门语言,强类型语言

  • TypeScript 是 JavaScript 的父级,里面包含了 JavaScript 以及 ES567,它可以编译成 js

  • 在 JavaScript 之上新增了类型和完整的面向对象功能

好处:使用 ts 编写的项目更加稳健,并且更容易扩展和维护

二、为什么要用 TypeScript

  • js 不能限制传递值的类型

function fn(a,b){
    // 但是我只想做加法运算,使用 js 的话只能对传递的值进行判断
    return a + b  // 返回 12
}
​
fn(1,'2') // 运行完才发现传递的是个字符串,再回头去改,影响开发效率
  • ts 限制传递值的类型

function fn(a:number,b:number){
    // 加法运算,传递的值不是 number 类型的话就会报错
    return a + b  // 返回 12
}
​
fn(1,'2')  // 还没运行,传递的类型不一致就会报错,可以及时的更改,不用把问题放在后面

好处:将问题放在开发前,不用等到运行后才发现错误

三、环境安装

  • 新增的语法,浏览器和 node 都是无法识别并执行的

  • 需要工具将 ts 代码转换为 浏览器 或 node 识别的 js 代码

  • 安装 node 和 npm ,npm 会和 node 一起被安装

1. 方式一

  • 安装: npm install -g typescript

  • 检验安装是否成功: tsc -v

  • 用法:tsc -w ts文件名

作用:将 ts 文件转换成 js 文件

2. 方式二

  • 安装:npm install -g ts-node

  • 用法:ts-node ts文件名

作用:自动将 ts 代码转换成 js 代码

四、语法

1. 变量

  • 声明变量时,必须指定变量的数据类型

  • 用法:let name : string = '张三'

注意:变量值的类型和指定的类型不一致,数据无法存储,会报错

2. 数据类型的约束

2.1. undefined 与 null

  • js 中是变量的值

    undefined:表示未初始化变量的值

    null:变量指向一个空对象

  • ts 中是一种数据类型

    undefined:表示未初始化变量的值,只能存储 undefined 的值

    null:变量指向一个空对象,只能存储 null 的值

注意:因为 undefined 和 null 是其他类型的子类,所以这两个变量的值可以赋值给其他类型的变量

2.2. 联合类型

  • 用法:let 变量名:类型1 | 类型2

  • 可以让变量存储多种类型的值

作用:变量取值的时候,可以是两种类型当中的任意一种

2.3. any

  1. any 的值可以存储任意类型的数据

2.4. 数组

  • 所有值必须是 同一个 类型

// 写法1
let arr:number[]=[1,3,4,5]
// 写法2
// Array<number> 泛型集合,相当于 new Array
let arr:Array<number>=[1,3,4,5]
  • 值必需是()中规定的类型

// 写法1(不需要按照类型的顺序写)
let arr1: (number | string | object)[] = ['1', 3, 8, '4', '4', '4', '4', '444', 789789,{
  id:1,name:"李四"
}]
// 写法2(按照类型的顺序写)第一位为字符串,第二位为数值,类型必须一一对应
let arr: [string,number] = ['1', 3]

2.5. 对象

  • 限制对象 属性值 的类型

// c?: number (缺省) 判断有没有 c ,有的话只能 number 类型,没有也可以。
// 不加 ? 就必须就 c 这个属性,并且是 number 类型
let obj: { n: number, c?: number } = { n: 11 }

3. 函数的约束

  • 带返回值 number 返回对应的数据类型

function fn(a:number,b:number):number{
    return a + b  // 返回 12
}
​
fn(1,2)
  • 不带返回值 void

function fn(a:number,b:number):void{
    return a + b  // 返回 12
}
​
fn(1,2)

4. interface

  • 接口:自定义约束结构

// 1. 首字母一定要大写
// 2. 分号结尾
interface Data {
  message: string;
  success: boolean;
  data: { list: {}[] };
}
​
// data 数据的类型规定按照 Data 自定义的
let data: Data = {
  message: '成功',
  success: true,
  data: {
    list: [
      { id: 1, name: '李四' }
    ]
  }
}
  • 继承:可以对之前的约束进行复用,在之前的基础上往上添加,可有可无的属性可以使用缺省 属性?:类型

interface Data {
  message: string;
  success: boolean;
  data: { list: { id: number, name: string }[] }
}
​
// extends 继承 Data 的数据类型
interface Res extends Data {
  children?: {}[]
}
​
// 使用 Res 定义的约束,Res 又继承了 Data 相当于 Res 的约束等于 Data 和它的自身的约束
let data: Res = {
  message: '成功',
  success: true,
  data: {
    list: [
      { id: 1, name: '李四' }
    ]
  }
}

作用:将数据的类型进行单独维护,提高代码的灵活性

5. 类

  1. 写法

class Person {
  // 需要给当前类的属性设置类型
  name: string;
  age: number;
​
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
    
  run():string{
      return this.name;
  }
}
​
new Person('李四', 89)

6. 修饰符

  • readonly 只读

  • private 私有的,当前类使用

  • public 公共的,任何地方都可以访问

  • protected 受保护的,只在当前类和当前子类内部使用

7. 抽象类 abstract

  • 定义抽象方法,不能实现具体的功能

  • 子类必须对抽象方法进行重写执行不同的任务,除非子类为抽象类

  • 抽象类不能 new,不能进行实例化

  • 抽象类可以继承,如果要继承,就必循实现该类的抽象方法

  • 抽象类存在的意义就是为了被继承

  • 抽象类中的普通属性和普通方法都需要用子类的对象去调用

  • 用法

abstract class Person {
  // 抽象属性
  abstract name: string
​
  // 定义抽象方法,在子类中重写来执行不同的任务
  abstract run(): string
}
​
class Son extends Person {
  // 重写改属性 name 并赋值
  name: string = '李四';
​
  // 重写父类的方法,来执行不同的任务
  run() {
    return this.name
  }
}
​
let son = new Son()
console.log(son.run());

作用:提取子类共有的属性以及方法,封装重复的功能

8. implement

  1. 对类的进行约束,让类必须这些方法和属性

interface ip1 {
  name: string,
  age?: number,
}
​
interface ip2 {
  gender: string,
}
​
// 对这个类进行2个约束
class Person implements ip1,ip2 {
  name: string
}

9. 泛型

  • 什么是泛型

    • 指定义函数、接口、类的时候,不预定指定具体类型,在使用时再指定类型的一种特性

  • 函数的泛型写法

// 函数使用多个类型
function fun1<F, U>(arg: F, b: U) {
  console.log(arg, b);
}
​
// number 对应 arg
// string 对应 b
fun1<number, string>(1, '111')
​
​
// T extends string 表示泛型 T 必须是 string 的子类
// 继承 string 类里面的 length 属性
// <T extends string | string[] 联合声明
function fun1<T extends string | string[]>(arg: T): number {
  // 报错传递的值中没有 length 属性
  return arg.length
}
​
console.log(fun1<string>('jkflda'));
console.log(fun1<string[]>(['jkflda','d','e']));
  • 接口的泛型写法

interface Data<T> {
  data: T
}
​
// 对函数的返回值进行约束
function init(): Data<object> {
  return {
    data: {}
  }
}
  • class 的泛型写法

class Person<T, U>{
  name: T;
  age: U
  constructor(name: T, age: U) {
    this.name = name
    this.age = age
  }
}
​
let p = new Person<string, number>('lisi', 18)
console.log(p);

10. 装饰器

  1. 什么是装饰器

    • 就是一个方法,可以注入到类、方法、属性参数上来 拓展 类、属性、方法、参数的功能

    • 使用装饰器,必须在 tsconfig.json 中进行 experimentalDecorators": true 配置

  2. 类装饰器

    • 类装饰器在类声明之前被声明(紧靠着类声明)。

    • 类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。

    • 传入一个参数 要获取装饰器扩展的东西,需要把实例对象的类型设置为any

  1. 普通装饰器(无法传递参数)

// target = Person
function fun(target: any) {
  // 在 Person 构造函数原型上添加一个 name 属性
  target.prototype.name = "李四"
  // 在 Person 构造函数上添加 aaa 属性
  target.aaa = '7777'
}

// 将当前类传递给 fun 函数 = @fun(Perosn)
@fun
class Perosn {
  uname: string
  constructor(uname: string) {
    this.uname = uname
  }
}

let p = new Perosn('张三')
// 访问 Person 原型上的 name
// @ts-ignore
console.log('name', p.name);
// 访问 Person 构造函数上的 aaa 属性
// @ts-ignore
console.log(Perosn.aaa);
  1. 装饰器工厂(可传参)

    • 装饰器工厂函数实际上就是一个高阶函数,在调用后返回一个函数,返回的函数作为装饰器函数。

// optios 传递的参数
function fun(options: any) {
  // target 类构造函数传递给装饰器函数
  // 返回装饰器函数
  return function (target: any) {
    // 在 p 构造函数原型上增加新的方法
    target.prototype.get = () => {
      console.log(options);
    }
  }
}

// @符号后为调用工厂函数,依次从上到下执行,目的是求得装饰器函数
@fun({
  name: "李四",
  age: 18
})
class P { }

let p = new P()

// @ts-ignore
p.get()
console.log(p);
  1. 装饰器组合

    • @符号后为调用工厂函数,依次从上到下执行,目的是求得装饰器函数。装饰器函数的运行顺序依然是从下到上依次执行。

    • 写了工厂函数,从上到下依次执行,求得装饰器函数。

    • 装饰器函数的执行顺序是从下到上依次执行。

// 装饰器函数
function demo1(target: any) {
  console.log('demo1'); // 6
}
// 装饰器工厂
function demo2(value: any) {
  console.log('demo2'); // 1
  return function (target: any) {
    console.log('内部 demo2'); // 5
  }
}
// 装饰器函数
function demo3(target: any) {
  console.log('demo3'); // 4
}
// 装饰器工厂
function demo4(value: any) {
  console.log('demo4'); // 2
  return function (target: any) {
    console.log('内部 demo4'); // 3
  }
}

@demo1
@demo2('')
@demo3
@demo4('')
class Person { }

// 执行结果
// demo2
// demo4
// 内部 demo4
// demo3
// 内部 demo2
// demo1
  1. 属性装饰器

// options 传递的参数
function fun(options: any) {
  // target 类的原型对象
  // attr 属性名
  // 返回装饰器函数
  return function (target: any, attr: any) {
    // 给类里面需要装饰的属性进行赋值
    target[attr] = options
    // 在类中添加 age 属性
    target.age = 18
    console.log(target, attr)
  }
}
​
​
class Person {
  // 给装饰器工厂传递参数
  @fun('张三')
  // @ts-ignore
  userName: string
​
  // 构造函数
  constructor(name: any) {
    this.userName = name
  }
}
​
let p = new Person('ddd')
console.log(p);
​
console.log(p.userName);
// 获取类的原型对象中的 age 属性
// @ts-ignore
console.log(p.age);
  1. 方法装饰器

11. 注释

  • @ts-ignore 取消下一行的报错

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值