Bootstrap

TS的学习

<template>

  <div class="aa">

11

  </div>

  <div class="aa">

11

  </div>

</template>

<script setup lang="ts">

// 基础的定义

import {ref ,reactive} from 'vue';

let num = ref(1);

let name:string = "Ben";

console.log(num.value,name)

const fun =(num1:number,num2:number):number=> {

  return num1 + num2;

}

let num1 = fun(1,2);

console.log(num1);

// * 数组类型

let arr:number[] = [1,2,3];

console.log(arr.length);

// * 元组类型 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

let arr1:[number,string] = [1,'str'];

console.log(arr1)

// * 函数类型 函数如果没有明确的类型可以使用 :void

const fun1 = ():void => {

  console.log(111)

}

fun1()

// * 函数的可选参数 , 可选参数后面加一个?, 可选参数只能放在参数的后面,负责会报错

const fun2 = (num1:number,num2:number,num3?:number):number => {

  if(num3) {

    return num1 + num2 + num3;

  }else {

    return num1 + num2;

  }

}

let fun2num1 = fun2(1,2);

let fun2num2 = fun2(1,2,3);

console.log(fun2num1,fun2num2);

// * 函数的默认参数

// * 如果函数的默认参数在前面而只传入了一个值,那么ts默认传入的是num1 ,故而会报错,可以第一个参数传递undefined

const fun3 = (num1:number = 100, num2:number):number => {

  return num1 + num2;

}

let fun3num1 = fun3(undefined,100);

console.log(fun3num1)

const fun4 = (num1:number,num2:number = 100):number => {

  return num1 + num2;

};

let fun4num1 = fun4(100);

console.log(fun4num1)

// * 函数重载 ==》 指的是两个函数相同,但是参数个数类型不一致

function fun5(x:number[]):number;

function fun5(x:string[]):string;

function fun5(x:any[]):any  {

  if(typeof x[0] == 'string') {

    return x.join('-')

  }else if(typeof x[0] == 'number') {

    return  x.reduce((acc, cur) => acc + cur)

  }

};

let fun5num1 = fun5(['a','b','c']);

let fun5num2 = fun5([1,2,3]);

console.log(fun5num1,fun5num2)

// * 接口 interface 属性必须和类型定义的时候完全一致。

/*

* 可选属性 在key的后面加一个?

* 只读属性 在key的前面加一个 readonly

*/

interface person {

  readonly id:number,

  name:string,

  age?:number

};

let student:person = {

  id:111111,

  name:'王五',

  age:18

};

console.log(student);

let student2:person =reactive({

  id:22222,

  name:'张三',

});

console.log(student2);

// * 描述函数类型

interface addfun {

  (num1:number,num2:number) :number

}

const fun6:addfun = (num1,num2) => {

  return num1 + num2;

};

let fun6num1 = fun6(1,2);

console.log(fun6num1)

// * 自定义属性 多个不明确的属性 , 当key的类型为string 则为对象,为number则为伪数组,可以通过下标获取,但无法使用数组的方法

interface Randomkey1 {

  [propName:string] :string | number

}

const Randomkey1:Randomkey1 = {

  'name':'Benson',

  'age':18

};

console.log('自定义属性1', Randomkey1);


 

interface Randomkey2 {

  [propName:number] :number

}

const Randomkey2:Randomkey2 = [1,2,3];

console.log('自定义属性2', Randomkey2)

//  * 鸭子类型 duck typing

interface FunctionWithProps {

    (x: number): number

    fnName: string

}


 

const fn: FunctionWithProps = (x) => {

    return x

}

fn.fnName = 'hello world'

console.log(fn)

// * 枚举 enum

// * 定义了一个数字枚举 他的特点

// * 数字递增

// * 反向映射

enum Direction { // * 枚举成员会被赋值从0开始的递增数据

  Up,

  Down,

  Left,

  Right

}

console.log(Direction.Up); // 0

console.log(Direction.Down); // 1

console.log(Direction[0]); // Up

// * 如果初始化的时候进行赋值,那么下面将依次++,但第一个依旧从0开始,依次++ 直到赋值的数据结束

enum Color {

  Red,

  Green = 0,

  Pick,

  Blue

}

console.log(Color.Red); // 0

console.log(Color.Green); // 0

console.log(Color.Pick); // 1

console.log(Color[2]); // Blue

// * 手动赋值

enum ItemStatus {

    Buy = 100,

    Send = 20,

    Receive = 1

}

console.log(ItemStatus['Buy'])      // 100

console.log(ItemStatus['Send'])     // 20

console.log(ItemStatus['Receive'])  // 1

// * 计算成员 枚举的成员是可以被计算的

enum Count {

  Bitwise = 1 << 1,

  Add = 1 + 2

};

console.log(Count.Bitwise);

console.log(Count.Add);

// * 字符串枚举 它的意义在于 : 提供了具体语义的字符串,更容易的理解代码和调试

enum Direction1 {

  Up = 'up',

  Down = 'down',

  Left = 'left',

  Right = 'right'

};

const dire = 'up';

if(dire == Direction1.Up) {

  console.log('向上移动6个格子',Direction1.Up)

}

// * 常量枚举  使用const编译JS 代码会变得简洁,提高性能; 常量枚举不包含计算成员

// * 常量枚举避免了在额外生成代码上的开销和额外的非直接的对枚举成员的访问

const enum week {

  SUN = 0,

  MON = 1,

  TUE = 2,

  WED = 3,

  THU = 4,

  FRI = 5,

  SAT = 6

}

const now = 1;

if(now == week.MON) {

  console.log('今天星期一', week[0])

}

// * 枚举的意义在于,可以定义一些带名字的常量集合,清晰的表达意图和语义,更容易的理解代码和调试

// * 类型推断

/*

* 1 定义时不赋值,那么自动推导成any

* 2 定义时初始化变量,那么自动推导为该变量的类型

* 3 函数设置了默认参数,也会自动推导

* 4 决定函数返回值

*  4.1 没有return 那么自动为 void

*  4.2 如果有return ts 也会自动推导返回值

*/

const fun8 = () => {

  console.log(111)

}

fun8();

const fun9 = () => {

  return 9;

}

const fun9num1 = fun9();

console.log(fun9num1);

// * 内置类型

// * 八种内置类型

/*

* string

* number

* boolean

* undefined

* null

* object

* bigint

* symbol

*/

// * ECMAScript 的内置对象

let date:Date = new Date();

console.log(date);

let err:Error = new Error('error!');

console.log(err)

// * DOM BOM ==>  HTMLElement、NodeList、MouseEvent

const body:HTMLElement = document.body;

console.log(body);

const aaaBox:NodeList = document.querySelectorAll('div');

console.log(aaaBox)

function move(e:MouseEvent) {

  return e

}

// * 联合类型 使用 | 将多个类型进行链接,如果不知道数据的类型 只能访问他们的共有方法

let num4 : number | string;

num4 = 1;

num4 = 'Ben';

console.log(num4);

// * 交叉类型 使用 &

// * 如果一个接口包含着另外一个接口的所有属性,那么可以通过&进行链接

// 例如 学生的接口包含人的接口,但多一个性别,即可使用& 进行交叉

interface Person {

  name:string,

  age:number

}

type Student = Person & {grade:string}

let num5:Student = {

  name:'王五',

  age:18,

  grade:'沃尔玛购物袋'

};

console.log(num5);

let num6:Person = {

  name:'李四',

  age:19

};

console.log(num6)

// * 类型别名 type

type STRING  = string;

type FUN = () => string;

type link = STRING | FUN;

function getname(n :link):STRING {

  if(typeof n == 'string') {

    return n

  }else {

    return n()

  }

}

let getnamenum1 =  getname('ben');

let getnamenum2 = getname(()=>'ben');

console.log('getnamenum1',getnamenum1);

console.log('getnamenum2',getnamenum2)

// * type 和 interface 的区别

// * 相同点

// 两者都可以定义一个对象或者函数

// 都允许继承

// interface 使用 extends继承 , type 使用 &继承

// * 不同点

/*

interface(接口) 是 TS 设计出来用于定义对象类型的,可以对对象的形状进行描述。

type 是类型别名,用于给各种类型定义别名,让 TS 写起来更简洁、清晰。

type 可以声明基本类型、联合类型、交叉类型、元组,interface 不行

interface可以合并重复声明,type 不行

*/

// * interface 合并重复声明

interface Box{

  width:number

}

interface Box {

  hight:number

}

let box:Box = {

  width:100,

  hight:50

}

console.log(box);

// * 类型保护

type getLength = number | string;

interface getLengthFun{

  (x:getLength): number

}

const getLengthFUN:getLengthFun=(x)=> {

  // return x.length

  if(typeof x == 'string') {

    return x.length;

  }else {

    return x.toString().length

  }

}

let getLengthFUNnum1 = getLengthFUN(1);

let getLengthFUNnum2 = getLengthFUN('aaa');

console.log(getLengthFUNnum1 +'---' + getLengthFUNnum2);

// * 类型断言 as 类型断言不是类型转换,把一个类型断言成联合类型中不存在的类型会报错。类型断言,是告诉浏览器,开发者比浏览器更知道数据是什么类型

const getLengthFUN2:getLengthFun = (x) => {

  const str = x as string;

  console.log(str)

  if(str.length) {

    return str.length;

  }else {

    const num = x as number;

    return num.toString().length;

  }

}

console.log(getLengthFUN2(1)+'----' + getLengthFUN2('aaa'));

// * 字面量类型

type grade = '男' | '女';

const sex:grade = '沃尔玛购物袋';

// * 泛型 <T> 尖括号中写参数的类型

const fun10 = <T>(x: T): T => {

  return x;

};

const fun10num1: number = fun10(111);

const fun10num2: string = fun10("aaa");

console.log(fun10num1, fun10num2);

function fun11<T>(x: T): T {

  return x;

}

const fun11num1: number = fun11(111);

const fun11num2: string = fun11("aaa");

console.log(fun11num1, fun11num2);

// * 泛型中的占位符,或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,他可以原封不多的输出

// * 使用类型别名定义泛型

type Ttype = <T>(x: T) => T;

const fun12: Ttype = (x) => {

  return x;

};

let fun12num1: string = fun12("aaa");

let fun12num2: number = fun12(111);

let fun12num3: boolean = fun12(true);

console.log(fun12num1, fun12num2, fun12num3);

// * 使用接口定义泛型

interface Tinterface<T> {

  (x:T):T;

}

const fun13 = <T>(x: T):T => {

  return x;

};

let fun13num1: Tinterface<number> = fun13;

console.log(fun13num1);

/*

由于fun13num1被声明成了 Tinterface<number> 类型 即他是一个函数类型,而不是一个函数的调用结果

*/

// * 默认参数

type Ttype01 = <t = number>(x:t)=>t;

const fun14: Ttype01 = (x) => {

  return x;

}

let fun14num1 = fun14(111);

console.log(fun14num1);

// * 处理多个函数参数

function fun15<T,U> (tuple:[T,U]):[U,T] {

  return [tuple[1],tuple[0]]

}

const tupledata:[number,string] = [111,'ben'];

const fun15num1 = fun15(tupledata);

console.log('fun15num1',fun15num1);

// * 约束泛型

interface fun16getlength {

  length:number

};

const fun16 = <T extends fun16getlength> (x:T) :T => {

  console.log(x.length)

  return x

}

let fun16num1 = fun16('aaa');

console.log(fun16num1)

let fun16num2 = fun16(111);

console.log(fun16num2);

// * 泛型的应用 使用泛型可以再定义函数,接口,类的时候,不预先指定具体类型,而是在使用的时候指定类型。

// * 泛型约束接口

interface IkeyValue<T,U> {

  key:T,

  value:U

};

const k1:IkeyValue<string,number> = {key:'ben',value:20};

console.log(k1);

const k2:IkeyValue<number,string> = {key:100,value:'棵'};

console.log(k2);

// * 泛型定义数组

const gparr:Array<number> = [1,2,3];

  console.log(gparr);

  // * 泛型小结

  /*

  * 泛型是指在定义函数,接口,类的时候不预先指定具体类型,而是等到使用的时候,再指定类型。

  * 泛型中的TU等,就像一个占位符,或者说是产量,等到使用的时候,把定义的类型就像常量一样传入,然后原封不动的输出

  * 泛型在成员直接提供有意义的约束,函数参数,函数返回值等

  *

  */

// * 鸡兔同笼

interface CageCounts {

  heads:number,

  feet:number

}

type CageCount = (x:number,y:number)=>string;

interface ChickenAndRabbitResult {

  chickens:number,

  rabbits:number

}

const getnum:CageCount = (x,y) => {

  const count:ChickenAndRabbitResult = {

    chickens:0,

    rabbits:0

  };

  for(let rabbits = 0 ; rabbits <= x; rabbits++) {

    let chicks = x - rabbits;

    let totalFeet = rabbits * 4 + chicks * 2;

    if(totalFeet == y) {

      count.chickens = chicks;

      count.rabbits = rabbits;

      break;

    }

  };

  if(count.rabbits >= 0 && count.chickens >= 0) {

    return `鸡的数量是${count.chickens} , 兔子的数量是 ${count.rabbits}`;

  }else {

    return `错误的`

  }

}

const checkData:CageCounts = {

  heads:50,

  feet:140

};

const getdata = getnum(checkData.heads,checkData.feet);

console.log(getdata)




 

</script>

<style scoped>

</style>

学习来自大佬的博客 :「1.9W字总结」一份通俗易懂的 TS 教程,入门 + 实战!-CSDN博客 

;