TypeScript(一)

129 阅读5分钟

什么是TS,我们为什么要学TS,TS对前端的影响有哪些?相信很多小伙伴第一次接触TypeScript,可能会有这些和我一样的疑问,今天我们就聊一聊TS相关的知识。

什么是TypeScript?

TypeScript是微软开布的静态弱类型编程语言,简称TS,是JavaScript的超集,简而言之就是JS有的TS都有,但是TS有的JS不一定有。TS = type + JavaScript 。

image.png

我们在使用JS编写代码的过程中,通常只有最后运行时,你才能发现你代码的错误,但是使用TS编写代码时,在编译过程暴露出大部分错误,并且增加了代码的可读性,并且各种数据类型都可以声明好类型,就不存在JS中的隐式类型转换等一系列问题,在多人合作的大型项目的开发过程中,有更好的稳定性和开发效率 。

在学习TypeScript的过程中推荐使用VSCode(Visual Studio Code)编辑器。

基本语法

基础数据类型

/*1.字符串*/
const str:string = 'string';
/*2.数字*/
const num:number = 123;
/*3.布尔值*/
const bool:boolean = true;
/*4.null*/
const nu:null = null;
/*5.undefined*/
const un:undefined = undefined;

可以发现其实基本的TS语句相比于JS语句就是多了类型声明,并且声明了类型的数据被赋值成其它数据类型在JS中是被允许的,但是在TS中不被允许。

let num:Number = 123;
num = '123';
/*不能将String类型分配给Number类型变量*/

对象类型

在TS中我们通常会使用interface关键字来声明数据类型

interface IUserInfo {
/*readonly 只读属性,不能对只读属性的变量修改*/
  readonly UserId: number,
  name: string,
  age: number,
/*?在变量名后面添加,则为可选属性,有则遵循类型声明,没有也不报错*/
  hobby?: string,
  sex: 'man' | 'woman' | 'other',
/*任意属性,约束所有对象属性都必须是该属性的子类型*/
  [key:string]: any
}

const user1:IUserInfo = {
  UserId: 2020213503
  name: '寒月十九',
  age: 21,
  hobby: 'reading',
  sex: 'man'
}
user1.UserId = 2020213504
//报错:无法分配到"UserId",因为其是只读属性

当我们试图修改只读属性的变量时,会报错,无法分配到该属性,该属性为只读属性;

user1.email = '2633368044@qq.com'
// 成功,任意属性标注下可以添加任意属性
const user2 = {
  UserId: 2020211111,
  name: '十九',
  age: 19
}
// 报错: 缺少sex属性,hobby属性可省略

函数类型

function add(x: number,y: number): number {
  return x + y;
}

const mult: (x: number,y: number) => number = (x,y) => x * y;

// ----------------------------------------------------------

interface IMult {
  (x: number,y: number): number;
}

const mult: IMult = (x,y) => x * y;

函数重载

/*对函数getDate进行函数重载*/
function getDate(type: 'string',timestamp?: string): string;
interface IGetDate {
  (type: 'string',timestamp?: string): string,
  (type: 'date',timestamp?: string): Date,
  (type: 'string' | 'date',timestamp?: string): Date | string,
}

const getDate2:IGetDate = (type,timestamp) => {
  const date = new Date(timestamp);
  return type === 'string' ? date.toLocaleString() : date
}
/*报错:不能将类型"(type:any,timestamp:any) => string | Date"分配给类型"IGetDate"
        不能将"string | Date" 分配给类型"string"
        不能将"Date"类型分配给类型"string"。 ts(2322)
*/

重载:用于实现不同参数输入并且对应不同参数输出的函数,在前面定义多个重载签名,一个实现签名,一个函数体构造,重载签名主要是精确显示函数的输入输出,实现签名主要是将所有的输入输出类型做一个全量定义,防止TS编译报错,函数体就是整个整个函数实现的全部逻辑。

数组类型

  • 类型 + 方括号表示
  • 泛型表示
  • 元组表示
  • 接口表示
type IArr1 = number[];
type IArr2 = Array<string | number | Record<string,number>>;
type IArr3 = [number,number,string,string];
interface IArr4 {
  [key: number]: any;
}

const arr1: IArr1 = [1,2,3,4];
const arr2: IArr2 = [1,2,'3',{a: 4}];
const arr3: IArr3 = [1,2,'3','4'];
const arr4: IArr4 = ['string',() => null,{},[]];

补充类型

type IEmptFunction = () => void
/*空类型,表示无赋值*/
type IAnyType = any
/*任意类型,是所有类型的子类型*/
enum EnumExample {
    add = '+',
    mult = '*'
}
EnumExample['add'] === '+'
EnumExample['mult'] === '*'

enum EColor {Mon,Tue,Wed,Thu,Fri,Sat,Sun}
EColor['Mon'] === 0;
EColor[0] === 'Mon'
/*枚举类型:支持枚举值到枚举名的正反映射*/

type INumber = Array<number>
/*泛型*/

泛型

泛型:不预先指定类型,而在使用的时候再指定类型的一种特性。

/*在js中,我们会这样写一个function*/
function getRepeatArr(target) {
  return new Array(100).fill(target);
}

type IGetRepeatArr = (target: any) => any[];

/*使用泛型的写法*/

type IGetRepeatR = <T>(target: T) => T[];

泛型接口 & 多泛型

interface IX<T, U> {
  key: T;
  val: U;
}

泛型类

class IMan<T> {
  instance: T;
}

泛型别名

type ITypeArr<T> = Array<T>

泛型约束

使用extends关键字继承,使得泛型必须符合继承的类型A extends B,A类元素必须符合B类

/*泛型约束:限制泛型必须符合字符串*/
type IGetRepeatArr = <T extends string>(target: T) => t[];
const getStrArr: IgetRepeatArr = target => new Array(100).fill(target);
/*报错:类型为"number"的属性不能赋值给类型为"string"的参数*/
getStrArr(123);

类型别名

通过type关键字定义别名

/*基本类型*/
type str = string
/*此处的str就是string的类型别名,其他基本类型同理*/
const a: str = 'abc'

/*对象类型*/
type IObjArr = Array<{
  key: string;
  [objKey: string]: any;
}>

function keyBy<T extends IObjArr>(objArr: Array<T>) {
  /*未指定类型时,result类型为{}*/
  const result = objArr.reduce((res,val,key) => {
    res[key] = val;
    return res;
  },{});
  /*通过as关键字,断言result类型为正确类型*/
  return result as Record<string, T>;
}

字符串/数字/字面量

/*允许指定字符串/数字必须的固定值*/

/*IString 必须为 HTML、CSS、JavaScript中的一个*/
type IString = 'HTML' | 'CSS' | 'JavaScript';
/*INumber 必须为 1、2、3、4、5中其中一个*/
type INumber = 1 | 2 |3 | 4 | 5;