这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
Day04——TypeScript
01——为什么是TypeScript?
动态类型:在执行阶段才会去确定类型的匹配。在浏览器运行一段JavaScript代码,执行过程中,浏览器的JavaScript的解析引擎才会对他进行类型的匹配,假设你写了一个不正确的类型,执行时控制台会报错。
静态类型:是不可以直接执行的,一定是需要先编译,编译完之后才可以执行。
弱类型语言:可以进行类型转换,“1”+1是可以运行的,即隐式类型转换。(而这在强类型语言中是不可以的)
- 静态类型
- 可读性增强:基于语法解析TSDoc,ide增强
- 可维护性增强:在编译阶段暴露大部分错误
=>多人合作的大型项目中,获得更好的稳定性和开发效率
- JS的超集
- 包含于兼容所有Js特性,支持共存
- 支持渐进式引入与升级
02——基本语法
基础数据类型
对象类型
// IBytedancer 大写的I开头表示这是一个类型,用于跟普通的对象和类进行区分
const bytedancer: IBytedancer = {
jobId: 9303245,
name: 'Lin',
sex: 'man',
age:28,
hobby: 'swimming',
}
// 关键词interface 对IBytedancer进行定义
interface IBytedancer {
/*readonly 只读属性:约束属性不可在对象初始化外赋值*/
readonly jobId: number;
name: string;
sex: 'man' | 'woman' | 'other';
age: number;
/*可选属性:定义该属性可以不存在*/
hobby?: string;
/*任意属性:约束所有对象属性都必须是该属性的子类型*/
[key: string]: any;
}
函数类型
JavaScript 中有两种常见定义函数的方式——函数声明(Function Declaration)和函数表达式(Function Expression)。
一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到。
function add(x, y){
return x + y;
}
const mult = (x,y) => x * y;
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;
注意:TypeScript 中的=>用来表示函数定义,左边是输入类型,用括号括起来,右边是输出类型。跟 ES6 中的=>箭头函数还是不同的,不要混淆。
可选参数
// 参数 y 可选
function sum(x: number, y?: string): string {
return x + y
}
默认参数
function sum(x: number, y: string = 'Jane'): string {
return x + y
}
函数重载
JavaScript本身是个动态语言。 JavaScript里函数根据传入不同的参数而返回不同类型的数据是很常见的。这怎么在类型系统里表示呢?
方法是为同一个函数提供多个函数类型定义来进行函数重载,编译器会根据这个列表去处理函数的调用,重载的函数在调用的时候会进行正确的类型检查。
例一:
function fn(x: number, y: number): number
function fn(x: string, y: string): string
function fn(x: string|number, y: string|number): string|number{
if(typeof x === 'number' && typeof y === 'number') {
return x + y
} else if(typeof x === 'string' && typeof y === 'string') {
return x + '_' + y
} else {
return '错误'
}
}
// 如果没有前两个重载这里不会报错,输出内容是“错误”
// 如果有了前两个重载这里就会报错,
// 因为此时的参数不符合重载函数的任何一种传参数据类型
fn(10, 'kkk')
例二:
/*对函数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,
}
/*报错:不能将类型"(type:any,timestamp:any) => string | Date"分配给类型"IGetDate"
不能将"string | Date" 分配给类型"string"
不能将"Date"类型分配给类型"string"。 ts(2322)*/
const getDate2:IGetDate = (type,timestamp) => {
const date = new Date(timestamp);
return type === 'string' ? date.toLocaleString() : date
}
数组类型
-
「类型+方括号」表示
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,{},[]];
TypeScript补充类型
/*空类型,表示无赋值*/
type IEmptFunction = () => void;
/*任意类型,是所有类型的子类型*/
type IAnyType = any;
/*枚举类型:支持枚举值到枚举名的正反映射*/
enum EnumExample {
add = '+',
mult = '*'
}
EnumExample['add'] === '+'
EnumExample['+'] === 'add'
enum EColor {Mon,Tue,Wed,Thu,Fri,Sat,Sun};
EColor['Mon'] === 0;
EColor[0] === 'Mon'
/*泛型*/
type INumber = Array<number>
泛型
// 泛型函数
// 让函数的参数可以有多种类型,具体什么类型是我们使用的时候决定的
function getRepeatArr(target) {
return new Array(100).fill(target);
}
type IGetRepeatArr = (target: any) => any[];
/*不预先指定具体的类型,而在使用的时候再指定类型的一种特性*/
type IGetRepeatArrR = <T>(target: T) => T[];
/*泛型接口&多泛型*/
interface IX<T, U>{
key: T;
val: U;
}
/*泛型类*/
class IMan<T> {
instance: T;
}
/*泛型别名*/
type ITypeArr<T> = Array<T>;
/*泛型约束:限制泛型必须符合字符串*/
type IGetRepeatStringArr = <T extends string>(target: T)=> T[];
const getStrArr: IGetRepeatStringArr = target => new Array(100).fill(target);
/*报错:类型"number”的参数不能赋给类型"string"的参数*/
getStrArr(123);
/*泛型参数默认类型*/
type IGetRepeatArr<T = number> = (target: T)=> T[];
const getRepeatArr: IGetRepeatArr = target => new Array(100).fill(target);
/*报错:类型"string"”的参数不能赋给类型"“number"的参数*/
getRepeatArr('123');
类型别名&类型断言
类型别名——type关键字
类型断言——告诉ts编译器:“我知道我在干什么,我能确定我现在的这个变量是什么类型”。ts 会假设你已经进行了类型的检查。
/* 通过type关键字定义了I0bjArr的别名类型*/
type IObjArr = Array<{
key: string;
[objKey: string]: any;
}>
function keyBy<T extends IObjArr>(objArr: Array<T>) {
/*未指定类型时, result类型为{0}*/
const result = objArr.reduce((res, val, key) => {
res[key] = val;
return res;
}, {});
/*通过as关键字,断言result类型为正确类型*/
return result as Record<string, T>;
}
字符串/数字字面量
TypeScript允许指定字符串/数字必须的固定值。
-
IDomTag必须为html、body、div、span中的其一
type IDomTag = 'html' | 'body' | 'div' | 'span '; -
IOddNumber必须为1、3、5、7、9中的其一
type IOddNumber = 1 | 3 | 5 | 7 | 9;