TS学习随笔

1,ts是什么

TypeScript 是 JavaScript 的超集,这意味着它可以完成 JavaScript 所做的所有事情,而且额外附带了一些能力。
Typed JavaScript at Any Scale. 它强调了 TypeScript 的两个最重要的特性——类型系统、适用于任何规模。

 

JavaScript 本身是一种动态类型语言,这意味着变量可以改变类型。从 TypeScript 的名字就可以看出来,「类型」是其最核心的特性。

使用 TypeScript 的主要原因是就是为了给 JavaScript 添加静态类型。静态类型意味着变量的类型在程序中的任何时候都不能改变。

2,TS基础

数据类型

javascript有七种原始数据类型,布尔值、数值、字符串、null、undefined 以及 ES6 中的新类型 Symbol 和 ES10 中的新类型 BigInt

就是再原始js变量上面增加个类型 这是基本类型

 let 变量名 : 数据类型 = 值

let isFlag: boolean = false; //布尔值
let name: string= '景天';
let age: number = 6;

数组

数组也是没有太大区别的,只是加了类型。  数组定义后,数组内的数据类型必须和定义数组的时候的类型是一致的,否则会有错误提示,某些情况下不会编译通过。

写法1: let 变量名 : 数据类型[] = [值1,值2,值3]

写法2: let 变量名 : Array<数据类型> = [值1,值2,值3]

 1 // 数组
 2 let lists: number[] = [1, 2, 3, 4, 5] // 如果此处没有写数值类型,而是别的,会直接报错,其他的写法也类似,前面定义了类型后面写的类型不对就会报类似的错误   不能将类型“string”分配给类型“number”。
 3 // console.log(lists, '1, 2, 3, 4, 5')
 4 
 5 let listString: string[] = ['1', '2']
 6 // console.log(listString, "'1', '2'")
 7 let listArray1: Array<number> = [1,2,3,4,5]
     let lsitArray2: Array<number | string> = [1, 2, '2']
 8 let listObj: object[] = [
 9   { name: '张三', age: 6 },
10   { name: '李四', age: '9999' }
11 ]
12 // console.log(listObj, '=============')
13 // 这里的any 表示可以是任意类型,(有人说在ts代码中全部写any就成了js)
14 let listany: any[] = [1, '2', false, {}, function () {
15   return false
16 }]
17 // console.log(listany, '=============')
18 // 这里的代码表示可以是多个类型,不一定是单一的。也不需要按照对应的位置,比如说我先写的 number ,数组的索引0就必须是number类型,这是错误的
19 let listSome: (number | string | boolean | Function | object)[] = [1, '2', false, {}, function () {
20   return false
21 }]
22 listSome.push(NaN)
23 // console.log(listSome, '=============')

元组

元组概念在js中是没有的,一个新的概念  用于表示一组固定数量的不同类型元素的有序集合。

一种特殊类型的数组,元组,他比常规数组更严格

写法 let 变量名: [类型1,类型2] = [值1,值2]

值1的类型需要与类型1相同,若不同会报错   值2也一样需要相同

1 // 元组
2 let listTuple: [boolean, string] = [false, '1']
3 // listTuple.push(true) // 元组说是有长度限制,为什么能push成功,并且不报错,这不就是相当于元组没有长度限制了???
4 listTuple.push('12')
5 listTuple[0] = true
6 console.log(listTuple, '=============')

编译后js代码

1 // 元组
2 var listTuple = [false, '1'];
3 // listTuple.push(true) // 元组说是有长度限制,为什么能push成功,并且不报错,这不就是相当于元组没有长度限制了???
4 listTuple.push('12');
5 listTuple[0] = true;
6 console.log(listTuple, '=============');

在我看来元组还是数组,所以说数组的方法也能用,如push 并且push类型没有错误,所以说编译时候没有报错

转换成js时候没有元组概念,变成了普通数组,所以说能正常运行

(若是有大佬看到这个问题,麻烦留言一下我理解的是否正确。万分感激)

枚举

 1 // 枚举
 2 /**
 3  * 使用关键字 enum 创建 枚举默认值是0 可以设置起始位开始得值,类似与后端数据库中id累加
 4  * 也可以创建字符串枚举
 5  * 在我看来这可以用作字典值,比如说某个流程总共几个状态
 6  * 取值方式与数组类似,没什么难度
 7  */
 8 enum num{
 9   a,b,c
10 }
11 enum num1{
12   a=3,b,c
13 }
14 enum num2{
15   a='a',
16   b='b',
17   c='c',
18 }
19 // console.log(num); //{ '0': 'a', '1': 'b', '2': 'c', a: 0, b: 1, c: 2 }
20 // console.log(num['a']); // 0
21 // console.log(num[0]); // a
22 // console.log(num1); //{ '3': 'a', '4': 'b', '5': 'c', a: 3, b: 4, c: 5 }
23 // console.log(num1['a']); // 3
24 // console.log(num1[0]); // undefined
25 // console.log(num1[3]); // a
26 // console.log(num2); // { a: 'a', b: 'b', c: 'c' }
27 // console.log(num2['a']); // a

 

对象(接口)

对象需要用关键字 interface 来定义  也有文章表示这个是接口,我不太理解,不过能用就行,无所谓叫什么名字

interface 定义的对象有几个属性,在 let 时候就需要有几个,否则会报错,

 1 // 对象
 2 interface person {
 3   name: string,
 4   age: number,
 5   sex: string,
 6   weight: number|string, // 这里可以多写类型,同样的在下边就可以多接受一种类型
 7   isGood: boolean,
 8 }
 9 let personOne: person = {
10   name: '景天',
11   age: 24,
12   sex: '男',
13   weight: 150,
14   isGood: true // 如果这里少了某个属性,会报语法错误,意思就是这个对象少了某个属性
15 }
16 // console.log(personOne);
17 
18 interface Animal {
19   name: string,
20   eat(name: string): string;     // 普通函数
21   speak: (name: string) => string;   // 箭头函数
22 }
23 
24 let catAnimal: Animal = {
25   name: '1',
26   eat: function (name: string) {   // 这里就是一个key为eat的函数属性?
27     return name
28   },
29   speak: (name) => name
30 }
31 // catAnimal.eat('banan')
32 // console.log(catAnimal.eat('apple'));
33 // console.log(catAnimal);
34 // console.log(Object.keys(catAnimal));

函数

在ts中函数并没有什么特别得地方,还是类型问题,在形参后边添加上数据类型就可以了。

有一点就是在函数括号后边可以添加返回得数据类型。

 1 let fun = function (v1: number = 2) {
 2   return v1
 3 }
 4 console.log(fun(3));
 5 let foo = (r: number): string => {
 6   return '' + Math.PI * r
 7 }
 8 // console.log(foo(4));
 9 let add = (a: string, b: number, c?: string | number | boolean) => {
10   return `名字叫${a}的人,今年${b}岁了。拥有${c}`
11 }
12 // console.log(add('jack', 23, false));

 类

ts中得类是一种新的概念,在js中是没有得,感觉有点类似于对象,比对象多了一些方法  通过关键字 class 创建出来

类的修饰符readonly,public,static,private,protected,

 1 class Person1 {
 2   public name: string; // public 能省略不写
 3   adress: string = '蜀山路142号';
 4   static age: number = 24; // 静态属性 不能通过new出来的类访问
 5   readonly hobby: string = '探险';  // readonly 只读属性,只能被读取,在 constructor构造函数中可以修改
 6   private isFlag: boolean; // 类的私有属性,外部访问不到
 7   protected email: string; //只能从这个类和他的子类中进行访问和修改
 8 }
 9 let per1 = new Person1()
10 per.name = '徐长卿'
11 console.log(per); // 此时输出的是 { adress: '蜀山路142号', hobby: '探险', name: '徐长卿' } 是没有age 的,因为 age属性不能通过new出来的类访问
12 console.log(Person); // 这里能输出 { age: 24 }

上面是类的简单属性用法

类还包含有内置方法和自定义方法

 1 //
 2 class Person {
 3   public name: string; // public 能省略不写
 4   adress: string = '蜀山路142号';
 5   static age: number = 24; // 静态属性 不能通过new出来的类访问
 6   weight: number | undefined = 150;
 7   readonly hobby: string = '探险';  // readonly 只读属性,只能被读取,在 constructor构造函数中可以修改
 8   public flying() {
 9     return "i can flying public"
10   } // 普通方法
11   flying1(v: number): string { // public 能省略不写
12     return "i can flying"
13   } // 普通方法
14   // public function flying2(v:string) {
15   //   return "i can flying public function"
16   // } // function 报 意外的关键字或标识符。
17   static fly() {
18     return "i can fly static"
19   } // 静态方法
20   constructor(v: string, b?: number) {
21     // console.log(this); // 此时 this 指向的是 Person 这个类本身 输出内容为 { adress: '蜀山路142号', hobby: '探险' }
22     this.hobby = v // 只有在此处可以修改 readonly 属性
23     // this.age = b // 语法错误 此时this 无法指到这个静态属性
24     this.weight = b
25   }
26 }
27 let per = new Person('打怪') // 当这个类有 constructor 并且有形参为必须时候,必须填写参数,否则会语法错误
28 per.name = '徐长卿'
29 // console.log(per); // 此时输出的是 { adress: '蜀山路142号', hobby: '探险', name: '徐长卿' } 是没有age 的,因为 age属性不能通过new出来的类访问
30 // console.log(Person); // 这里能输出 { age: 24 }
31 // console.log(per.flying()); // 输出 i can flying public
32 // console.log(Person.fly()); // 输出 i can fly static
33 // public 定义的属性或者方法 可以直接通过实例化对象访问
34 // static 定义的属性或者方法 需要通过类去访问 
35 console.log(per); // 输出 {adress: '蜀山路142号',weight: undefined,hobby: '打怪',name: '徐长卿'} 因为我没有传第二个参数所以weight 为undefined
36 console.log(Person); // 这里能输出 {fly: [Function (anonymous)], age: 24}

 类的继承

类可以继承 通过关键字 extends

 1 class Animal {
 2   name: string | undefined = ''
 3   static food: string = '狗粮';
 4   readonly hobby: string = '探险';
 5   sayHello() {
 6     return '动物会跑'
 7   }
 8   static staticFun() {
 9     return '动物睡觉'
10   }
11 }
12 class Dog extends Animal { }
13 let ani = new Animal()
14 let dog = new Dog()
15 // console.log(ani, 'ani'); // { name: '', hobby: '探险' } ani
16 // console.log(dog, 'dog'); // { name: '', hobby: '探险' } dog
17 // console.log(ani.sayHello()); // 动物会跑
18 // console.log(dog.sayHello()); // 动物会跑
19 // 根据输出可以看出 类的继承可以继承父类的 除static之外的属性和方法
20 
21 // console.log(Animal); // { staticFun: [Function (anonymous)], food: '狗粮' }
22 // console.log(Dog); // 什么都没有输出
23 // 根据此处输出可以的出 通过 static 定义的属性和方法不能被子类继承
24 
25 class Dog1 extends Animal {
26   name: string | undefined = '旺财';
27   age: number = 6
28   readonly hobby: string = '吃狗粮';
29   sayHello() { // 方法重写
30     return '汪汪汪'
31   }
32   sayHello1() {
33     return '嗷嗷叫'
34   }
35 }
36 let dog1 = new Dog1()
37 console.log(dog1, 'dog1'); // { name: '旺财', hobby: '吃狗粮', age: 6 } dog1
38 console.log(dog1.sayHello()); // 汪汪汪
39 console.log(dog1.sayHello1()); // 嗷嗷叫
40 // 根据输出可以看出继承的父类属性和方法可以被子类覆盖,并且可以添加自己单独的属性方法

 类的继承中还有构造函数  constructor

这就引出新的 关键字 super 调用父类构造函数

 1 // 类 的构造函数继承
 2 class Plant {
 3   color: string | undefined = ''
 4   readonly height: number = 100
 5   constructor(color: string) {
 6     this.color = color
 7   }
 8   growUp() {
 9     console.log('植物在生长');
10   }
11 }
12 class Rose extends Plant { }
13 let plant = new Plant('#f00')
14 // let rose = new Rose() // 此处写法包语法错误,因为继承了父类的 constructor构造函数,需要传递一个参数进去才行
15 let rose = new Rose('#00f')
16 // console.log(plant); // { color: '#f00', height: 100 }
17 // console.log(rose); // { color: '#00f', height: 100 }
18 
19 class Peony extends Plant {
20   constructor(color: string) {
21     super(color) // 如果子类中有构造函数,那就必须要调用父类的构造函数,使用 super 调用。不调用报语法错误
22     this.color = color
23   }
24   growDown() {
25     super.growUp() // 此行代码表示调用父类中的 growUp 方法
26     console.log('植物不会向下生长');
27   }
28 }
29 let peony = new Peony('#f0f')
30 // console.log(peony); // { color: '#f0f', height: 100 }
31 // peony.growDown()// 植物在生长   植物不会向下生长

 抽象类  abstract

写完感觉抽象类没什么意义,不知道有什么用,还可多语法限制

 1 // 抽象类abstract 抽象类中可以添加抽象方法
 2 // 整个语法都是莫名其妙的感觉没什么用,
 3 abstract class Fish {
 4   name: string = ''
 5   swimming() {
 6     console.log('并不是所有的鱼都在海里');
 7   }
 8   // abstract swimming1(){} // 语法错误 方法“swimming1”不能具有实现,因为它标记为抽象
 9   abstract eating(): string // 这样写就没问题不知道为啥,但是这样写继承时候会报语法错误 非抽象类“Dolphin”不会实现继承自“Fish”类的抽象成员“eating”。
10 }
11 // let fish = new Fish() // 语法错误 无法创建抽象类的实例
12 class Dolphin extends Fish {
13   name: string = '海豚'
14   eating(): string { // 需要对继承的方法进行重写 否则就是 非抽象类“Dolphin”不会实现继承自“Fish”类的抽象成员“eating”
15     return ''
16   }
17 }
18 let dolphin = new Dolphin()
19 // console.log(dolphin); // { name: '海豚' }
20 // dolphin.swimming() // 并不是所有的鱼都在海里

 泛型

 2 /**
 3  * 定义:泛型是指你不知道数据类型是什么样子得,在你使用时候才知道这个数据类型是什么。
 4  * 泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候在指定类型限制的一种特性。
 5  * 这个泛型像极了 any ,但是你ts代码要是用太多any 就像是变成了js,失去了ts特点
 6  */
 7 // 以下函数写法不同但是输出结果相同 大写T类似与一个类型形参,也可以用别的字母代替例如 A B 如果类型形参有两个,写法就如 testT4
 8 // testT3 三个位置得T需要一致,
 9 function testT1(v) {
10   console.log(v);
11   return v
12 }
13 function testT2<T>(v) {
14   console.log(v);
15   return v
16 }
17 function testT3<T>(v: T): T {
18   console.log(v);
19   return v
20 }
21 function testT4<T, A>(v: T, b?: A): T {
22   console.log(v);
23   console.log(b);
24   return v;
25 }
26 // let v = testT3('123') // 123 string
27 // let v1 = testT3(123) // 123 number
28 // let v2 = testT3(true) // true boolean

接口泛型 类泛型

 1 // 在我看来接口泛型与类泛型差不多,用法基本上就是加一个参数,用<> 包起来,再接口与类中函数中泛型用法也都一样
 2 // 接口泛型  
 3 interface testT5<T> {
 4   name: T,
 5   age: number
 6 }
 7 let testT6: testT5<string> = {
 8   name: '张三',
 9   age: 24
10 }
11 // console.log(testT6);
12 // 类型泛型
13 class testT7<T>{
14   name: T;
15   constructor(v) {
16     this.name = v
17   }
18 }
19 let testT8 = new testT7('李四')
20 let testT9 = new testT7(123)
21 // console.log(testT8); // { name: '李四' }
22 // console.log(testT9); // { name: 123 }

 

posted @ 2024-02-21 17:29  马文庆i  阅读(18)  评论(0编辑  收藏  举报