什么是TS,我们为什么要学TS,TS对前端的影响有哪些?相信很多小伙伴第一次接触TypeScript,可能会有这些和我一样的疑问,今天我们就聊一聊TS相关的知识。
什么是TypeScript?
TypeScript是微软开布的静态弱类型编程语言,简称TS,是JavaScript的超集,简而言之就是JS有的TS都有,但是TS有的JS不一定有。TS = type + JavaScript 。
我们在使用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;