TS笔记
计划三天看完TS课程,此为课程笔记
一点准备
npm i typescript -g
全局安装TS编译器npm i ts-node -g
安装好后可在vscode右键run直接运行tstsc hello.ts
可运行编译文件tsc --init
生成TS配置文件
配置tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "./js"
}
}
运行vscode检视任务
vscode -> 终端 -> 运行生成任务 -> tsc:监视
这样保存ts文件时 会自动编译出js文件,方便查看
数据类型
布尔 数字 字符串 数组
let married: boolean = false; // boolean
let age: number = 25; // number
let firstName: string = 'lzy'; // string
let arr2: number[]=[4,5,6]; // array
let arr3: Array<number>=[7,8,9];// array
let arr4: (string | number)[]=[7,8,9,'a'];// array
元组: 表示 类型 和 数量 固定的 数组
与数组的区别: 每一项可以是不同类型, 有预定义的长度,
const animal:[string,number,boolean] = ['lzy',25,true]; // tuple
let lzy:[string,number] = ['lzy',5]; // tuple
// 此处如果没定义类型,则在TS中下面两行会报错。因为类型
lzy[0].length; // OK
lzy[1].toFixed(2); // OK
枚举: 该数据类型的变量 只能为事先写好的几个类型
// 普通枚举
enum Color {
Red,// 默认值为 0
Yellow,// 默认值为1
Blue// 默认值为2
}
// 常量枚举
const enum Color2 {
Red,// 默认值为 0
Yellow,// 默认值为1
Blue// 默认值为2
}
// 常量枚举的变量名(如Red)会在编译时被完全删除,节省变量名开销,因为是常量,必然是固定值,调用这个固定值的地方会直接被替换为值
let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];
symbol
表示唯一不变的类型
const sym1 = Symbol('key');
const sym2 = Symbol('key');
// 报错:此条件将始终返回false
console.log(sym1 === sym2)
使用Symbol 需要 ES6 编译辅助库
bigint
可以安全的 储存 和 操作 大整数
const max = Number.MAX_SAFE_INTEGER;// 2**53-1
console.log(max + 1 === max + 2); // true,因为溢出了
const max:bigint = BigInt(Number.MAX_SAFE_INTEGER);
console.log(max + 1 === max + 2); // 报错,BigInt 不能直接 + number类型
console.log(max + 1n === max + 2n); // 代表BigInt(1)
使用 BigInt 需要 ESNext 的编译辅助库
JS 原始数据类型 BigInt Number,ts 里的类型 bigint number
any
任意类型,可以被赋值任何类型数据的类型
null undefined
null 和 undefined 是其他类型的子类型,可以赋值给任意类型.
但,TS配置文件设置了strictNullChecks:true时,直接这样赋值会报错
null 和 undefined 可以相互赋值
void
表示没有任何类型,当函数没有返回值时,被认为是void类型
never
never 是其他类型的子类型,表示永远不会被执行到的值
function error(message: string): never {
throw new Error(message);
}
function fn(x: number | string) {
if (typeof x === 'number') {
// x: number 类型
} else if (typeof x === 'string') {
// x: string 类型
} else {
// x: never 类型
// --strictNullChecks 模式下,这里的代码将不会被执行,x 无法被观察
}
}
never 和 void 的区别: void 可以是 null 或 undefined
拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。
function validateCheck (v:never) {}
function test (stringOrNumber: string | number) {
if(typeof stringOrNumber === 'string') {
return
}
// 报错number类型不能赋值给never
validateCheck(stringOrNumber)
}
function validateCheck (v:never) {}
function test (stringOrNumber: string | number) {
if(typeof stringOrNumber === 'string') {
return
} if(typeof stringOrNumber === 'number') {
return
}
// OK!
validateCheck(stringOrNumber)
}
类型推导
指 编程语言中 能自动推导出 值 的类型的能力,一般强类型语言才有
定义未赋值时,会推论为any类型
let username2;
username2 = 25; // 自动推理为number类型
username2 = 'lzy';// string类型
包装对象
JS有两类数据类型, 原始数据类型(null undefined boolean number string Symbol) 和 对象类型
所有原始数据类型都没有 属性 或 方法 可供使用,仅仅是储存一个数据.
但字符串数据 却可以直接调用 splice等方法,
这是因为 当 调用 基本数据类型 的方法时, JS 会把 原始数据类型 强制性切换为 对象类型,
c# Java中都有这个概念,叫 自动装箱,
let isOK: boolean = true; // 编译通过
let isOK: boolean = Boolean(1) // 编译通过
let isOK: boolean = new Boolean(1); // 编译失败 期望的 isOK 是一个原始数据类型
联合类型
表示 取值可以时多种类型中的一种
未赋值时 联合类型 上只能访问 两个类型共有的 属性或方法
let name:string | number // 联合类型
console.log(name!.toString()); // 公共方法
name = 10;
console.log(name!.toFixed(2)); // number方法
name = 'zf';
console.log(name!.toLowerCase()); // 字符串方法
类型断言
将联合类型的变量 指定为 更加具体的类型
let name: string | number;
console.log((name as string).length);
console.log((name as boolean).length); // 报错,不能指定为联合类型外的类型
console.log((name as any as boolean).length); // 双重断言,OK
字面量类型和类型字面量
字面量类型 一个字面量就是一个类型,类型和值必须一致.
const up:'Up' = 'Up' // 这样写也是字面量类型,只不过无法复用
type OneToFive = 1 | 2 | 3 | 4 | 5;
type Bool = true | false;
字面量类型本身并不是很实用,但是可以在一个联合类型中组合成一个强大的抽象
类型字面量 写法很像一个对象
type Person = {
name:string,
age:number
};
// 注意写法: 不要和enum的写法搞混
enum Color {
Red,// 默认值为 0
Yellow,// 默认值为1
Blue// 默认值为2
}
TS函数
函数的类型约束主要是 入参 和 返回值
函数的声明方式有两种,function关键字来声明 表达式声明
表达式声明时,如果把类型约束写在函数里,则变量类型是根据函数推导出来的类型。
// function关键字声明 定义类型
function hello(name:string):void {
console.log('hello',name);
}
// 表达式声明 定义类型
type GetUsernameFunction = (x:string,y:string)=>string;
type GetUsernameFunction2 = {(x:string,y:string):string}
let getUsername:GetUsernameFunction =
function(firstName,lastName){
return firstName + lastName;
}
// 表达式声明时,如果把类型约束写在函数里,则变量类型是根据函数推导出来的类型。
支持 可选 默认值 剩余参数 函数重载 四种写法
注意print(name:string = 'lzy',age?:number)
可不传第二个参数,
age的类型改成age:number | undefined
还是必须传第二个参数,只不过可以为undefined
// 默认参数,可选参数 和 ES6一样
function print(name:string = 'lzy',age?:number):void {
console.log(name,age);
}
// 剩余参数
const sum = (...args: string[]): string => {
return args.reduce((memo, current) => memo += current, '')
}
sum('a', 'b', 'c', 'd')
Function关键字声明的函数才能重载(伪重载,只是对类型的重载)
重载使用场景,输入和输出存在某种关联,参数的个数不一致时实现的逻辑也不一致
注意: 函数的重载,无法用泛型替代。????????? 存疑???
// 函数重载
// TS中的函数重载,表现为 同一个函数提供多个函数类型定义
// Java中的重载,表现为 同名函数 参数不一样
function toArray(value: number): number[];
function toArray(value: string): string[];
function toArray(value: string | number): string[] | number[] {
// 只有一个具体的实现
// 此处返回值可不写 : string[] | number[] ,但入参必须能兼容上面两个重载。
if (typeof value === "string") {
return value.split("");
} else {
return value.toString().split("").map(Number);
}
}
let arr1 = toArray(1);
let arr2 = toArray("2");
// 上面的重载和这里一样的效果,那这样看重载好像也没什么用?
function attr2(val: string|number): void {
if (typeof val === 'string') {
obj.name=val;
} else {
obj.age=val;
}
}
// 重载解决了下面这种情况
// 要求两个参数,要不都是string,要不都是string[]
function attr3(a: string,b: string): void;
function attr3(a: string[],b: string[]): void;
function attr3(a: any,b: any): void {
}
typeof keyof 函数this类型约束
TS中:
typeof 取变量的类型
keyof 取的是类型的key的集合
this 可在函数的第一个参数处做类型约束
注意: 如果 type 关键字后面的 typeof 会被视为 TS语法,具有获取 实例类型的功能,
或 getName(this: typeof person, key: PersonKey) 冒号后的typeof,也能被识别为TS
返回的是 类型本身
而语句中的 typeof 会被视为 js语法, 非获取类型的功能,而是返回类型字符串
const person = { name: "lzy", age: 25 }
type Person = typeof person;
type PersonKey = keyof Person;
function getName(this: Person, key: PersonKey) {
return this[key];
}
getName.call(person, "name");
let a = typeof person
// let a: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
其它笔记
?.
是js语法,链运算判断符,这个值没有值就不继续取值了
!
是TS语法,非空断言,断言该值必不为空,无需进行null检测。
注意: ele?.style.color = "red"
编译器会报错,
因为 ele?.
真不存在时实际上是返回undefined,运行会报错。
类 也是一个 类型(就像symbol,number,boolean一样),
构造完一个类后得到两个类型,一个构造函数类型 一个实例类型.