目录
1.什么是自学Ts?
1.1 设计公司:微软
1.2 TS概述
1.3 TS是静态类型 JS是动态类型
1.4 TS是强类型语言 JS是弱类型语言
2.TypeScript编译器
2.1 安装
2.2 TS自动编译和编译选项设置
3.TS的数据类型
3.1 基础数据类型number 、string 、文档boolean
3.2 Arrays(数组类型)
3.3 any(任意类型)
3.4 unknown(类型未知)
3.5 void(空值)了解
3.6 never
3.7 TS中的自学类型推断
3.8 Functions (函数)
3.9 Object(对象类型)
3.10 联合类型
3.11 类型别名(Type Alias)
3.12 类型语法(Interfaces)
3.13 类型断言(Type Assertion)
3.14 字面类型(Literal Types)
3.15 元组(tuple)
3.16 枚举(Enum)
3.17 不常用类型 了解即可
3.18 类型过滤(Type Narrowing)集中数据筛选方式 感兴趣可以看下
4、TS函数
4.1函数格式:
5 、文档class 类
5.1 类的自学定义
5.2 类的继承
5.3 修饰符
5.4 静态属性和方法
5.5 抽象类
5.6 多态(Polymorphism)
6.TS的接口
6.1 接口的定义
6.2 接口的用途
6.3 属性类型接口
6.4 函数类型接口
6.5 可索引性接口 了解
6.6 类类型接口
6.7接口的继承
7、TS泛型
7.1 泛型类
7.2 泛型类接口
8 、文档TS修饰器
8.1 类装饰器 ClassDecorator(不可传参)
8.2装饰器工厂 (也可以叫柯里化,闭包,可传参)
8.3 属性装饰器
8.3 方法装饰器 MethodDecorator
8.4 各种装饰器的自学执行顺序
官方介绍:TypeScript 是 JavaScript 的超集,这意味着它可以完成 JavaScript 所做的所有事情,而且额外附带了一些能力
。
Typed JavaScript at Any Scale. 它强调了 TypeScript 的文档两个最重要的特性——类型系统、适用于任何规模
。自学
(简述:JavaScript应用广泛,但是文档由于其为弱类型语言,使其在项目管理层面表现得相当差劲 。科技巨头微软为了解决这个尴尬的自学问题,推出了typeScript)
静态类型:编写时要注意变量 、函数的文档数据类型,并且在编译时就对代码类型检测并立即报错。
动态类型:编写时不需要注意变量 、自学函数的文档数据类型,只有程序运行后才对代码类型检测并报错 。
总体来说,静态类型语言更适合大型项目,可以减少错误并提高代码质量;而动态类型语言则更适合小型或快速开发项目,可以增加开发效率。自学
弱类型:编程时变量可以不声明数据类型,并在赋值或运算时数据类型可以随意转换 。
强类型:编程时必须明确声明数据类型,如果发现类型错误,就会在编译或运行期间发生错误 。
tsc是TypeScript的编译器,我们一起来安装一下吧!
//安装ts编译器npm i -g typescript//检查是否安装成功tsc//ts文件编译变为js文件 (helloTS.ts这个是文件名)tsc helloTS.ts//ts文件编辑中 遇到无法重新声明块范围变量“*****” (生成tsconfig.json文件就可以解决了)tsc --init
tsc helloTS.ts 编译前
tsc helloTS.ts 编译后
2.2.1 局部-自动编译指定文件
tsc (文件名) -w 可以对指定文件自动编译
tsc helloTS1.ts -w
2.2.2 全局-自动编译文件
tsc -w
提及下tsconfig.json相关设置 (有助于自定义全局自动编译文件)
{// include是指定要编译哪些ts文件"include":["./src/**/*"],// exclude表示不包含"exclude":["./hello/**/*"],//compilerOptions编译器的选项"compilerOptions": {// target用来指定ts被编译为的Es的版本"target":"ES6",//module 指定要使用的模块化的规范"module": "ES6",//用来指定项目中要使用的库"lib":["es6","dom"],//outDir用来指定编译后文件所在的目录"outDir": "./dist",//将代码合并为一个文件//设置outFile后,所有的全局作用域中的代码会合并到同一个文件中"outFile": "./dist/app.js",//是否对js文件进行编译 默认是false"allowJs":false,//是否检查js代码是否符合语法规范 默认值是false"checkJs": false,//是否移除注释 默认为false"removeComments": false,//是否生成编译后的文件 "noEmit": false,//当有错误的时不生成编译后的文件 "noEmitOnError": false,//用来设置编译后的js文件是否设置严格模式"alwaysStrict": false,//不允许隐式的any类型"noImplicitAny": true,//不允许明确类型的this"noImplicitThis": true,//严格的检查空值"strictNullChecks": false,},}
类型 | 例子 | 描述 |
---|---|---|
number | 1,-33,2.5 | 任意数字 |
string | “hi”,“hi”,hi | 任意字符串 |
boolean | true,false | 布尔值true或false |
字面量 | 其本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的any |
void | 空值(undefined) | 没有值(或undefined) |
never | 没有值 | 不能是任何值 |
object | {name:‘孙悟空’} | 任意的JS对象 |
array | [1,2,3] | 任意JS数组 |
tuple | [4,5] | 元素,TS新增类型,固定长度数组 |
enum | enum{A,B} | 枚举,TS中新增类型 |
let a:number; //数值a = 18;console.log(a,"number");let b:string; //字符串b = 'wengzi';console.log(b,"string");let c:boolean; //布尔c = true;console.log(c,"boolean");
let arr:number[]; //数组arr=[1,2,3,4,5,6]console.log(arr,"array");
let arr1:Array; //数组arr1=[1,2,3,4,5,6]console.log(arr1,"array1");
any类型表示任意类型,它可以在编译时不进行类型检查和类型推断,允许我们随意地对其进行读写操作。使用any类型通常是为了处理一些动态类型 、非常规类型或者无法确定类型的值。
let d: any;d = 123; // 赋值为数字d = "hello"; // 赋值为字符串d = true; // 赋值为布尔值console.log(d, "任意类型");
概念:一个安全的any,一个类型为unknown的变量,不能直接赋值给其他变量
小提示:unknown 数据类型的数据要赋值的话,得使用类型断言 详情请看-> 3.13类型断言
void 用来表示空,用作函数的返回值类型,表示函数没有返回值。除了将void类型作为函数返回值类型外,在其他地方使用void类型是无意义的
function fn():void{}
never类型可以作为函数的返回值类型,表示该函数无法返回一个值 。
function fn2():never{throw new Error('报错了!!!');//该函数永远无法执行到末尾,返回值类型为"never"}
ts也可以根据赋值类型,推断出来变量的类型。
let e = "ceshi";console.log(e, "类型推断");
function add(x: number, y: number): number {return x + y;}//调用函数const result = add(10, 30);console.log(result, "函数");
//使用对象字面量创建对象const person = {name: "xiaoming",age: 18,gender: "female",};console.log(person, "对象");
//定义一个person1接口interface person1 {name: string;age: number;gender: string;}//使用接口定义对象const person2: person1 = {name: "xiaohong",age: 20,gender: "female",};console.log(person2, "对象");
TypeScript中的联合类型使用 | 符号将几种不同类型组合成一个新的类型 。表示该变量 、参数或属性可以是这些集合中任何一种类型之一
let numOrStr:number|string;numOrStr=100; //数值numOrStr='Hello world'; //字符串console.log(numOrStr,"联合类型");
function printId(id: number | string) {console.log("联合类型", id);}printId(11);printId("文字");
小提示:
开发中会因为联合类型导致toUpperCase()方法无法使用
解决方法如下:
(我们通过一定的条件过滤将类型做了划分,最终解决了类型交叉的问题。)
function printId(id: number | string) {if (typeof id === "string") {// In this branch, id is of type 'string'console.log(id.toUpperCase());} else {// Here, id is of type 'number'console.log(id);}}
定义一个变量
type bieming = number | string;let bm: bieming;bm = 123;bm = "aaa";console.log(bm, "类型别名");
//定义一个person1接口interface person1 {name: string;age: number;gender: string;}//使用接口定义对象const person2: person1 = {name: "xiaohong",age: 20,gender: "female",};console.log(person2, "类型语法");
概念:可以强制将一个值的类型转化为开发者想要的类型
let someValue:any="hello world"let ceshiValue:number=(<string>someValue).lengthconsole.log(ceshiValue,"类型断言");
let someValue:any="hello world"let ceshiValue:number=(someValue as string).lengthconsole.log(ceshiValue,"类型断言");
小提示:实际开发过程中会碰到有些类型没办法直接断言的情况,那么我们就需要断言两次,通常会使用as any或者as unknown作为第一层断言“(expr as any) as T
概念:定义一个字面类型,以后赋值只能内容 === 恒等
type myString='hello'; //定义一个字符串字面类型type myNumber=123; //定义一个数值字面类型type myBoolean=true; //定义一个布尔字面类型let myVar1: myString = 'hello'; // 可以赋值为 'hello'let myVar2: myString = 'world'; // 报错,只能是 'hello'let myVar3: myNumber = 123; // 可以赋值为 123let myVar4: myNumber = 456; // 报错,只能是 123let myVar5: myBoolean = true; // 可以赋值为 truelet myVar6: myBoolean = false; // 报错,只能是 true
再来一个联合类型的例子
function printText(s: string, alignment: "left" | "right" | "center") {// ...}printText("Hello, world", "left");printText("G'day, mate", "centre");
再来一个联合类型的例子
function compare(a: string, b: string): -1 | 0 | 1 {return a === b ? 0 : a > b ? 1 : -1;}
概念:元组,就是固定长度的数组,即其中的元素个数是固定的 。
let h :[string,number];h = ['a',10]
概念:是一种常用的数据类型,用于表示固定的预定义值集合
enum Color{Red=1,Green,Blue,}console.log(Color.Red); //输出1console.log(Color.Green);//输出2console.log(Color.Blue); //输出3console.log(Color[1]); //输出'Red'console.log(Color[2]); //输出'Green'console.log(Color[3]); //输出'Blue'
在上述代码中,我们定义了一个名为 Color
的枚举类型,并设置了三个枚举项,分别对应的数值依次为 1
, 2
和 3
。枚举项的名称可以通过 .
访问,也可以通过枚举值反向查找到对应的名称。
需要注意的是,如果不显式为枚举项指定数值,则它们将会从 0
开始依次递增 。如果第一个枚举项指定了数值,则它之后的枚举项将在此基础上增加。
枚举是一种比较简单、直观的数据类型,可以用于表示有限的取值范围和状态等 。特别是在开发过程中定义一些固定的常量时,枚举可以起到很好的作用,并提高代码的可读性和可维护性 。
bigint
从ES2020开始,JavaScript中有一个用于非常大整数的原语BigInt:
// Creating a bigint via the BigInt functionconst oneHundred: bigint = BigInt(100);// Creating a BigInt via the literal syntaxconst anotherHundred: bigint = 100n;
symbol
JavaScript中有一个原语,用于通过函数Symbol()创建全局唯一引用:
const firstName = Symbol("name");const secondName = Symbol("name");if (firstName === secondName) {This condition will always return 'false' since the types 'typeof firstName' and 'typeof secondName' have no overlap.// Can't ever happen}
概念:使用断言、判断和匹配等手段,在特定条件下缩小一个变量的类型范围。常用的类型过滤技巧包括条件语句 、类型保护函数和 in 操作符等 。
let value: string | number;if (typeof value === 'string') {console.log(value.toUpperCase()); // OK,字符串类型} else {console.log(value.toExponential()); // OK,数值类型}
function isPerson(obj: any): obj is Person {return typeof obj.name === 'string' && typeof obj.age === 'number';}type Person = { name: string, age: number };function greet(person: Person | string) {if (isPerson(person)) {console.log(`Hello, ${person.name}!`); // OK,可以直接访问 person 的属性} else {console.log(`Hello, ${person}!`);}}greet({ name: "Alice", age: 25 }); // 输出:Hello, Alice!greet("World"); // 输出:Hello, World!
type Shape = Square | Circle;interface Square {width: number;}interface Circle {radius: number;}function area(shape: Shape) {if ('width' in shape) { // 判断作为 Square 类型处理return shape.width ** 2;} else { // 判断作为 Circle 类型处理return Math.PI * shape.radius ** 2;}}console.log(area({ width: 5 })); // 输出:25console.log(area({ radius: 1.5 })); // 输出:7.0685834705770345
function 函数名(参数列表): 返回值类型 {函数体 ...[return 返回值;]}
格式二
let 函数名 = function (参数列表): 返回值类型 {函数体 ...[return 返回值;]};
常见写法
function getInfo(name:string,age:number):string{return `${name}---${age}`}console.log(getInfo('小明',1)); //正确console.log(getInfo('小红')); //错误console.log(getInfo(1)); //错误
function getInfo(name:string,age?:number):string{return `${name}---${age}`}console.log(getInfo('小明',1)); //正确console.log(getInfo('小红')); //正确console.log(getInfo(1)); //错误
默认参数
function getInfo(name:string,age:number=20):string{return `${name}---${age}`}console.log(getInfo('小明',30)); //正确 小明---30console.log(getInfo('小红')); //正确 小红---20console.log(getInfo(1)); //错误
剩余参数:在参数的类型确定而参数个数不确定的情况时,我们需要用到剩余参数,它使用 ...
将接收到的参数传到一个指定类型的数组中
。
function sum(...result:number[]):number{let sum=0;for(let i=0;i
箭头函数
setTimeout(function () {console.log("匿名函数执行了...");}, 1000);setTimeout(() => {console.log("箭头函数执行了...");}, 1000);
class Person{name:string;constructor(n:string){ //constructor是用来定义类的构造函数this.name=n;}run():void{console.log(this.name+"在图书馆");}}let p=new Person('王哈哈');p.run();
类的继承:在TypeScript中想要实现继承使用extends关键字
class Person {name: string;//父类属性,前面省略了public关键词constructor(n: string) {//构造函数,实例化父类的时候触发的方法this.name = n;//使用this关键字为当前类的name属性赋值}run(): void {//父类方法console.log(this.name + "在跑步");}}//中国人这个类继承了人这个类class Chinese extends Person {age: number;//子类属性constructor(n: string, a: number) {//构造函数,实例化子类的时候触发的方法super(n);//使用super关键字调用父类中的构造方法this.age = a;//使用this关键字为当前类的age属性赋值}speak(): void {//子类方法super.run();//使用super关键字调用父类中的方法console.log(this.name + "说中文");}}var c1 = new Chinese("张三", 28);c1.speak();
TypeScript 里面定义属性的时候给我们提供了 三种修饰符
public
: 默认的修饰符,可以被类的实例
、子类和其他类访问。
private
: 只能被定义它的类所访问,在其它地方无法进行访问。
protected
: 可以被定义它的类和该类的子类所访问,但是在类外部无法访问。
class Person {private name:string; //private: 只能被定义它的类所访问,在其它地方无法进行访问。constructor(n: string) {this.name = n;}run(): void {console.log(this.name + "在跑步");}}class Chinese extends Person {age: number;constructor(n: string, a: number) {super(n);this.age = a;}speak(): void {super.run();console.log(this.name + "说中文"); //报错}}var c1 = new Chinese("张三", 28);c1.speak();
static:用于声明静态成员或方法。静态成员不需要实例化即可访问。
class MathUtility {public static readonly PI: number = 3.14159; // 只读静态成员public static add(a: number, b: number): number { // 静态方法,用于求和return a + b;}}const sum = MathUtility.add(4, 5); // 直接通过类名调用静态方法console.log(sum); // 输出 9console.log(MathUtility.PI); // 直接通过类名访问只读静态变量
抽象类是一种不能被实例化的类,因为它仍然需要子类来继承并实现其方法