cometang前端技术博客 cometang前端技术博客
首页
  • html5
  • JavaScript
  • ES6
  • Vue
  • 微信小程序
  • react
  • react上手教程
  • 前端框架
  • 大神之路
  • 面试汇总
  • Node
  • PHP
  • Go语言
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

cometang

永远相信技术的力量
首页
  • html5
  • JavaScript
  • ES6
  • Vue
  • 微信小程序
  • react
  • react上手教程
  • 前端框架
  • 大神之路
  • 面试汇总
  • Node
  • PHP
  • Go语言
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • ES6

  • vue

    • vue基础详解
    • vue组件与路由
    • 组件通信与插槽
    • MVC与MVVM
    • vuex状态管理
    • TypeScript基础
      • 1.前言
      • 2.搭建TypeScript 本地环境
      • 3 基本数据类型定义
        • 3.1 常用基本数据类型
        • 3.2 ES6 新增基本数据类型
        • 3.2.1 长整数 BigInt
        • 3.2.2 唯一值 Symbol
      • 3 数组定义
      • 4 接口 定义 对象的类型 interface
        • 4.1 基础使用
        • 4.2 可以合并的 类型
      • 5 对象数组 定义
      • 6.元组
      • 6 函数定义
      • 7 void 空类型
      • 8 any 类型
      • 9 类的定义 class
        • 9.1 简单类的定义
        • 9.2 简单类省略写法
        • 9.3 必传与可选参数
        • 9.4 类的修饰符
        • 9.5 类的存取器
      • 10.枚举类型 enum
      • 11.泛型
        • 11.1 场景:
        • 11.2 理解:
        • 11.3 泛型语法说明
        • 11.4 多个泛型参数
        • 11.5 泛型 约束
        • 11.6 泛型问题
      • 12 never 不存在的类型
      • 13 unknown 未知类型
      • 14 as 类型断言
      • 15 联合类型
      • 16 type 类型别名
        • 16.1 type 定义类型别名
        • 16.2 type 定义对象类型 与interface 相同
        • 16.3 interface 可以合并多个类型,type 不支持
    • vue进阶
    • Vue2 装饰器与TS结合
    • Vue3.2 语法基础
    • Vue3.2项目架构
    • vue进阶-keepalive
    • vue2配置-环境变量-响应式-proxy-mock
    • vite打包工具
  • h5

  • JavaScript

  • 前端框架

  • react

  • 大神之路

  • 微信小程序

  • 面试题汇总

  • react轻松上手教程

  • 前端
  • vue
cometang
2022-06-10
目录

TypeScript基础

# 1.前言

什么是typescript?

TypeScript简称TS TS和JS之间的关系其实就是Less/Sass和CSS之间的关系 就像Less/Sass是对CSS进行扩展一样, TS也是对JS进行扩展 就像Less/Sass最终会转换成CSS一样, 我们编写好的TS代码最终也会换成JS TypeScript是JavaScript的超集,因为它扩展了JavaScript,有JavaScript没有的东西。 硬要以父子类关系来说的话,TypeScript是JavaScript子类,继承的基础上去扩展。

为什么需要TypeScript?

简单来说就是因为JavaScript是弱类型, 很多错误只有在运行时才会被发现 而TypeScript提供了一套静态检测机制, 可以帮助我们在编译时就发现错误

TypeScript特点

支持最新的JavaScript新特特性 支持代码静态检查 支持诸如C,C++,Java,Go等后端语言中的特性 (枚举、泛型、类型转换、命名空间、声明文件、类、接口等)

# 2.搭建TypeScript 本地环境

  • 全局安装typeScript
npm i -g typescript
1
  • 安装ts-node
npm i -g ts-node
1
  • 初始化一个项目
tsc --init
1
  • 运行ts文件的编译命令[可以通过package.json 配置编译命令]
tsc index.ts
1

# 3 基本数据类型定义

# 3.1 常用基本数据类型

// 基本数据类型
let str:string="啦啦啦啦";
let num:number = 123;
let bool:boolean=true;
let nu:null = null;
let un:undefined = undefined;

console.log(str,num,bool,nu,un);    //啦啦啦啦 123 true null undefined
1
2
3
4
5
6
7
8

# 3.2 ES6 新增基本数据类型

注意: 如果要使用此种数据类型需要将 tsconfig.json 中的 lib 选项解注释并加入以下内容 lib: ["ESNext"] 或 直接更改ts整体编译 target: ES2020 "target": "es2020"

# 3.2.1 长整数 BigInt

const big: BigInt = BigInt(Number.MAX_SAFE_INTEGER);
console.log(big);  //9007199254740991n
1
2

# 3.2.2 唯一值 Symbol

let id: symbol = Symbol(1);
let id1: symbol = Symbol(2);

console.log(id);    //Symbol(1)
console.log(id1);  //Symbol(2)
1
2
3
4
5

# 3 数组定义

let arr:string[]=['1','2','3','4'];
1
let arr1:Array<number> = [100,200,300];
1
let arr2:(string|number)[] = ['1',2,'3',4];
1

# 4 接口 定义 对象的类型 interface

# 4.1 基础使用

interface User{
    name:string,
    age:number,
}
let user1:User={name:"张麻子",age:40};
1
2
3
4
5

# 4.2 可以合并的 类型

interface User{
    name:string,
    age:number
}

interface User {
    like:string,
}
let user:User = {name:'张麻子',age:22,like:'xxxxx'};
1
2
3
4
5
6
7
8
9

# 5 对象数组 定义

let list:(User)[] = [{name:"黄四郎",age:45},{name:"马邦德",age:44}]
let list:Array<User> = [{name:"黄四郎",age:45},{name:"马邦德",age:44}]
1
2

# 6.元组

和数组类似,但是其中的类型和顺序以及数量都需要被提前定义。

let arr:[string,number,string]= ['张麻子',22,'敲代码'];
//不可以通过索引新增元祖的元素
// arr[3]='啦啦啦';
// 可以通过push追加,这是ts 元祖的缺陷
arr.push('啦啦啦')
1
2
3
4
5
//长度可变元祖定义
let arr:[number,...any] = [100]
arr[1] = '你好啊'
1
2
3

# 6 函数定义

function sum(a:number,b:number):number{
    return a+b;
}
console.log(sum(100,200));
1
2
3
4
// 可选参数类型
let func: (name: string, age?: number) => void;

// 可选参数一定要在必选参数的后面。
func = function (name: string, age?: number): void {
  console.log(name, age);
};
func('zhangsan'); // zhangsan undefined
// 默认参数一定要在必选参数的后面。
func = function (name: string, age: number = 24): void {
  console.log(name, age);
};
func('zhangsan'); // zhangsan 24

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 7 void 空类型

//函数没有返回值
const avg = (a:number,b:number,c:number):void=>{
    console.log(a+b+c);
}
avg(100,200,300)
1
2
3
4
5

# 8 any 类型

定义任何变量 可以赋值为任何数据类型,写any 相当于没有类型限制

let num1:any=123;
num1='100';
console.log(num1);   
1
2
3

# 9 类的定义 class

# 9.1 简单类的定义

class Person {
    // public 表示实例公共属性
    public name: string;
    public age: number;
    // public可以省略
    like: string;
    constructor(name: string, age: number, like: string) {
        this.name = name;
        this.age = age;
        this.like = like
    }
    // 实例方法
    public say(): string {
        return '你好啊,我是' + this.name;
    }
    // 静态方法
    static eat(food: string): string {
        return '我正在吃' + food;
    }
}
let p1 = new Person('张三', 22, '抽烟,喝酒,烫头');
console.log(p1);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 9.2 简单类省略写法

每次定义类 都需要在构造函数前面去定义每个属性的类型太过繁琐,可以直接简写到构造函数中

  • 原写法
class Person {
    // public 表示实例公共属性
    public name: string;
    public age: number;
    // public可以省略
    like: string;
    constructor(name: string, age: number, like: string) {
        this.name = name;
        this.age = age;
        this.like = like
    }
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 简写 直接把定义属性的关键字放到构造函数中
class Person {
    // 省略写法,不需要提前定义类型
    // public name: string;
    // public age: number;
    // like: string;
    constructor( public name: string,  public age: number, public like: string) {
        // 省略写法,不需要再去对每个属性赋值
        // this.name = name;
        // this.age = age;
        // this.like = like
    }
    ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 9.3 必传与可选参数

?: 可选参数,可以不传,默认类型为隐式any,默认值为undefined

!: 必传参数,必须传递


class Person {
    // !:  必传参数
    public name!: string;
    // ?:  可选参数,默认类型 number | undefined ,默认值:undefined 
    public age?: number;
    constructor(name: string, age?: number) {
        this.name = name;
        this.age = age;
    }
}
let p1 = new Person('张三', 22);  //Person { name: '张三', age: 22 }
let p2 = new Person('李四')       //Person { name: '李四', age: undefined }
// let p3 = new Person();  //报错 必须传递1-2个参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 9.4 类的修饰符

类的属性和方法 有特定的作用或者限制 就需要通过修饰符进行处理

js中类的修饰符: public static readonly(只读)

ts中类的修饰符:除了js类的三个修饰符之外,新增了:

  • public (公共) 公共属性、方法,可以在实例以及子类中访问
  • protected (保护) 只能在子类中访问该属性和方法
  • private(私有) 只能在当前类中访问该属性和方法
class Person {
    
    protected age!: number;
    private name!: string;
    public sex!: string;
  
    private getName() {}
    protected getAge() {}
    public getSex() {}
  
    // name 和 getName() 只能在 Person 中用 this 访问
  }
  class User extends Person {
    constructor() {
      super();
      // User中可以访问 getAge() 和 age 以及被 public 修饰的属性以及方法
    }
  }
  const person = new Person(); // person 只能访问到 getSex() 和 sex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

注意: private 私有属性与方法 只能在当前类中使用,不能通过子类 和 this实例访问

class Person{
    private name:string;
    constructor(name:string){
        this.name = name;
    }
    private say(){
        return 'ssss';
    }
    // 私有方法只能通过当前类进行使用
    public xxx(){
        console.log(this.name);
        console.log(this.say())
    }

}

let p1 = new Person('张麻子');
// p1.name = '黄四郎'  // 私有属性 使用报错
// p1.say()   //私有方法调用报错
p1.xxx()     //通过实例正确的使用方法
console.log(p1);    //Person { name: '张麻子' }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 9.5 类的存取器

如果想通过 实例对象直接访问或修改 类中的私有属性与方法,除了通过公有方法进行调用与操作之外,TS提供了存取器来进行操作

TS 支持通过 getter/setter 来截取对象成员的访问

假设我们现在有个类,其中 name 是私有属性,但是我们又想要更改以及访问这个属性,此时就可以使用存取器

Object.defineProperty 也拥有存取器

class Person{
    private _name:string;
    constructor(name:string){
        this._name = name;
    }
    // 获取name时自动执行
    get name():string{
        return this._name;
    }
    // 修改name时 自动修改_name 
    set name(val:string){
        this._name = val;
    }
}

let p1 = new Person('张麻子');
console.log(p1.name)    //自动执行 get     张麻子
p1.name = '黄四郎'      //自动执行 set   
console.log(p1.name)   //黄四郎
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 10.枚举类型 enum

作用:一般用来定义 多种不同的状态

enum State{
    Pending="PENDING",
    Success="SUCCESS",
    Fial="FIAL"
}
console.log(State.Pending)    //PENDING 
1
2
3
4
5
6
// 无默认值的枚举值 默认从 0 开始
enum State{
    Pending,
    Fial,
    Success,
}
console.log(State.Pending)   //0
console.log(State.Fial)     //1
console.log(State.Success)  //2
1
2
3
4
5
6
7
8
9

# 11.泛型

泛型: 泛指一切类型

泛型可以理解为 类型变量: 可变的类型

# 11.1 场景:

如果一个函数 传入了数字类型,就返回数字 ,如果传入了字符串,就返回一个字符串

function fn(a:number):number{
    return a;
}
function fn(a:string):string{
    return a;
}
1
2
3
4
5
6
  • 泛型写法
function fn<T>(a:T):T{
    return a;
}
fn(100)  //100
fn('张麻子')  //张麻子
fn(true)  //true
//调用时传入泛型的类型
fn<number>(1000)  //1000
fn<object>({name:'张麻子'}) //{name:'张麻子'}
1
2
3
4
5
6
7
8
9

# 11.2 理解:

img

# 11.3 泛型语法说明

为什么是 T ? 难道不能是其他的字母或者单词吗?当然可以 可以使任意单词或者字母,只要语义化清晰即可。建议首字母大写。当然 T 并不是毫无道理。

  • T : 代表 Type 在定义泛型时通常用作第一个类型变量名称.
  • K : 表示对象中的 key 类型。
  • V : 表示对象中的 value 类型。
  • E : 表示 Element 元素类型。

# 11.4 多个泛型参数

function fn<N,M>(a:N,b:M):N{
    return a;
}
console.log( fn(1000,'sss')   );   //1000
1
2
3
4

# 11.5 泛型 约束

使用泛型之后 会造成一些问题: 泛型之间不能使用运算符,泛型拿到数组、元祖之后没有length

解决length问题需要使用到 泛型约束

泛型约束:可以理解为 该泛型可以包含的属性及属性类型

这里出现 extends 关键字,此处表示泛型必须包含某种类型,从而在调用时约束了传入的类型。


function fn<T>(arr:T):number{
    return arr.length;    //报错  泛型T 不存在 length属性
}
console.log( fn([100,200,300])  );
1
2
3
4
5
  • 泛型约束写法
// 定义泛型的约束
interface Len{
    length:number
}
function fn<T extends Len>(arr:T):number{
    return arr.length;    
}
console.log( fn([100,200,300])  );   //3
1
2
3
4
5
6
7
8
  • 多个泛型约束

如果需要约束多个条件 <T extends Type1, Type2, ...>

# 11.6 泛型问题

泛型之间不能使用运算符

解决方案: 函数重载

function add<T>(a:T,b:T):T{
    return a+b  //报错 两个泛型不能进行加法运算
}
1
2
3
  • 函数重载

需要注意的是只有最后一个才是真正的函数,其他的地方只能是函数类型的定义。

function add(a: string, b: string): string
function add(a: number, b: number): number
function add(a: any, b: any) {
    return a + b;
}
console.log(add(11,22));    //33
console.log(add('ssss','eeeee'));  //sssseeeee
1
2
3
4
5
6
7

# 12 never 不存在的类型

抛出异常,或者永远不会有返回值的函数以及永远不会为真的类型返回 never。

function infiniteLoop(): never {
    while (true) {}
  }

  function error(): never {
    throw '异常错误';
  }
  error()
  infiniteLoop()
1
2
3
4
5
6
7
8
9

# 13 unknown 未知类型

unknown 和 any 很类似

定义为 unknown 类型的变量可以接收 任意数据类型

unknown 的变量只能赋值给 unknown 和any 类型的变量

any 定义的类型变量可以赋值给任意类型变量

let a:unknown;
a=1;
a='222'
console.log(a);  //'222'
1
2
3
4
let a:unknown = '100';
// let b:string = a;  //不能讲unknown 类型 分配给string类型
let c:unknown = a;    //'100'  
let d:any = a;       //'100'
1
2
3
4

# 14 as 类型断言

在某种情况下我们可能明确的知道这个值的类型,但是静态检查不是想要的类型。此时可以使用类型断言确定这个值的类型


let arr = [111,'2222',333];
// let len = arr[1].length;   //报错 很明显'2222'是一个字符串,但是却没有length属性

// 使用强制断言 可以强制确定该变量的类型
let len = (arr[1] as string).length;  //4
1
2
3
4
5
6

# 15 联合类型

表示一个类型可以是多种类型中的一种

// 两个类型 选择一个
let a: string | number;
a = 1;
a = '1';
console.log(a)  //'1'
1
2
3
4
5

# 16 type 类型别名

type 可以对 比较复杂的类型 取一个别名,简化 ts 的代码

type 和 interface 有很多相同之处 也有不同之处

相同:type 和interface 都可以定义 对象和 函数的类型

不同:

interface 是接口:用于描述一个对象 使用 extends 或implements 是 必须使用 interface

type 是类型别名: 使用组合或者交叉类型 必须使用type

# 16.1 type 定义类型别名


type Name = string    //type 取别名
type NameResolver = () => string   //type 取别名
type NameOrResolver = Name | NameResolver          // 联合类型 通过type 取别名 简化代码
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n
    }
    else {
        return n()
    }
}
getName('黄四郎');  //'黄四郎'
getName(()=>'张麻子')  //'张麻子'
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 16.2 type 定义对象类型 与interface 相同

interface User{
    name:string,
    age:number
}
let user:User = {name:'张麻子',age:30};
1
2
3
4
5
type User = {
    name:string,
    age:number
}
let user:User = {name:'张麻子',age:22};
1
2
3
4
5

# 16.3 interface 可以合并多个类型,type 不支持

interface User{
    name:string,
    age:number
}

interface User {
    like:string,
}
let user:User = {name:'张麻子',age:22,like:'xxxxx'};
1
2
3
4
5
6
7
8
9
type User = {
    name:string,
    age:number
}

type User = {   //报错 User 标识符重复
    like:string,
}
1
2
3
4
5
6
7
8
编辑 (opens new window)
上次更新: 2022/06/15, 01:13:31
vuex状态管理
vue进阶

← vuex状态管理 vue进阶→

最近更新
01
go语言基础
07-13
02
《react上手教程》- 基础语法
07-13
03
redux-redux toolkit-状态管理
03-18
更多文章>
Theme by Vdoing | Copyright © 2019-2023

cometang | 唐世杰 渝ICP备18015657号-2

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式