首页 > 其他分享 >TypeScript中的类型注解、Interface接口、泛型

TypeScript中的类型注解、Interface接口、泛型

时间:2024-11-04 20:19:48浏览次数:4  
标签:TypeScript string number 泛型 let 类型 Interface 注解

一、认识TypeScript

1.概述

TypeScript是具有类型语法的JavaScript,是一门强类型的编程语言。它是 JavaScript 的超集(js中的所有元素都属于ts),这意味着任何有效的 JavaScript 代码本身也是有效的 TypeScript 代码。

在这里插入图片描述

2.优点

静态类型检查

TypeScript 在编译阶段就可以检查类型错误,而不像 JavaScript 是在运行时检查。例如,在 JavaScript 中,你可以这样写代码:

let x = 5;
x = "hello";

这段代码在 JavaScript 中是完全合法的,但是可能会导致一些难以发现的错误。在 TypeScript 中,你需要先定义变量的类型。

let x: number = 5;
x = "hello";//会报错,因为x被定义为数字类型,不能赋值为字符串

这种静态类型检查有助于在开发早期发现错误,提高代码的质量和可维护性。

3.用处

TypeScript不是万能的,技术的选项不能脱离具体的业务与应用场景,TS更适合用来开发中大型的项目,或者是通用的js代码库,再或者是团队写作开发的场景

二、搭建TypeScript环境

1.为什么需要搭建环境

TypeScript编写的代码无法直接在js引擎(浏览器/Node.js)中运行,最终还是需要编译成js代码才能运行。

带来的好处:既可以在开发时使用TypeScript编写代码享受类型带来的好处,同时也保证实际运行的还是javaScript代码

在这里插入图片描述

2.搭建编译环境

  • 全局安装TypeScript包(编译引擎)

    • npm install -g typescript
      
  • 将TypeScript文件编译,生成JavaScript文件

    • tsc xxx.ts
      
  • 执行node xxx.js 运行

在这里插入图片描述

三、类型注解

1.TypeScript类型注解是什么

概念:类型注解是指给变量添加类型约束,使得变量只能被赋值为约定好的数据类型,同时还可以有相关的类型提示

说明: :string 就是类型注解,约束变量message只能被赋值为string类型,同时可以有string类型相关的提示

//类型注解入门
let msg:string
msg = "Hello World";

let count:number;
count = 100;

let isLading:boolean
isLading = true;

2.TypeScript支持的常用类型注解

js已有的数据类型

  • 简单类型
    • number、string、boolean、null、undefined
  • 复杂类型
    • 数组、函数

TypeScript新增类型

​ 联合类型、类型别名、接口(interface)、字面量类型、泛型、枚举、void、any等

2.1 简单类型

简单类型的注解完全按照js的类型(全小写)来书写

//简单类型进行类型注解
let age:number = 18;
let username:string = 'jacklove';
let isLoading:boolean = false;
let nullValue:null = null;
let undefinedValue:undefined = undefined;

2.2 数组类型

变量被注解为数组类型后,有两点好处

  • 不仅可以限制变量类型为数组,且可以限制数组成员的类型
  • 编码的时候不仅可以提示数组的属性和方法且可以提示成员的属性和方法
//数组类型注解的两种方法:
1.第一种(推荐)
let arr1:number[] = [1,2,3]
arr.forEach(item => console.log(item))

2.第二种(泛型写法)
let arr2:Array<number> = [1,2,3]

//输出步骤:当前文件夹打开cmd,输入
tsc 02数组类型类型注解.ts
node 02数组类型类型注解.js
1 2 3

2.3联合类型

概念:将多个类型合并为一个类型对变量进行注解

需求:如何注解数组类型可以让数组类型中既可以放string类型,游客与放number类型

说明:number | string 表示arr3中的成员既可以是string类型也可以是number类型

//联合类型
let arr3: (number | string)[] = [1, 2, 3, 4, 5,'jack'];
arr3.push(6);
arr3.push('a');

2.4函数类型

给函数添加类型注解,本质上给函数的参数和返回值添加类型约束

说明:

  • 函数参数注解类型之后不但限制了参数的类型还是限制了参数为必填
  • 函数返回值注解类型之后,限制了该函数内部必须有return出去的值,才能满足类型要求

参数和返回值分开注解以及函数整体注解

//参数和返回值分开注解1
function add(a:number,b:number):number{
    return a+b;
}
console.log(add(1,2));

//参数和返回值分开注解2
const add2 = (c:number,d:number):number =>{
    return c+d;
}
console.log(add(1,2));

//函数整体注解
type AddFn = (c:number,d:number) => number 
const addFunction1:AddFn = (a,b) => {
    return a + b;
}
console.log(addFunction1(1,2));

2.5字面量类型

概念:使用JavaScript字面量作为类型对变量进行类型注解,这种类型就是字面量类型,字面量类型比普通类型更加精确

说明:除了下面的数字字面量,javaScript里面常用的字符串字面量、数组字面量、对象字面量都可以成为类型使用

//普通number类型,可以赋值任何数值
let count:number
count = 100
count = 200

//字面量类型
let count1:100 | 200  //只能赋值为100
//let count1:100 | 200  //只能赋值为100或200
count1 = 100
// count1 = 200 //报错

字面量类型的实际应用

场景1:性别只能是“男”或“女”,就可以采用联合类型配合字面类的类型定义方案
type gender ='男'|'女'
let sex:gender = '(提示男或女)'

场景2:ElementUI (饿了么UI)中的el-buttong组建的type属性
type Props = {
 type: 'primary' | 'success' | 'danger' | 'warning'
}

字面量类型与const

const声明的变量称之为常量,常量是不可以重新赋值的,所以str2推断出来的是字面量类型而不是string类型
let str1 = 'this is string'
const str2 = 'this is const string'

2.6any类型

作用:变量别注释为any类型之后,TypeScript会忽略类型检查,错误的类型赋值不会报错,也不会有任何提示

注意:any的使用越多,程序可能出现的漏洞就越多,因此不推荐使用any类型,尽量避免使用

let obj:any = 100;
obj = "hello";
obj = {age:18}
obj = [18,20,'jack']

const n:number = obj;

3.类型别名

概念:通过Type关键字给写起来比较复杂的类型起一个其它的名字,用来简化和复用类型

说明: type 类型别名= 具体类型。

其中类型别名的命名方式采用规范的大驼峰写法

//类型别名
let arr:(string | number)[] = [18,'jack'];

//起别名
type ItemType = (string | number)[]
//使用类型别名
let array1:ItemType = [18,'jack'];
let array2:ItemType
//对于已经声明的变量,再赋值的时候就不用去重复声明数据类型
array2 = [18,'jack'];

4.可选参数

概念:可选参数指的是当前参数可传也可以不传,一旦传递实参必须保证参数类型正确

//可选参数:可以传也可以不传,如果传就必须类型正确
function builderName(firstName:string,lastName?:string){
    if(lastName){
        return `${firstName} - ${lastName}`
    } else {
        return firstName;
    }
    
}
console.log(builderName('张'));
console.log(builderName('张','三丰'));

5 .无返回值 - void

概念:javaScript中有些函数只有功能没有返回值,此时使用void进行返回值的注解,明确表示函数没有返回值

注意事项:在JavaScript中如果没有返回值,默认返回的是undefined,在TypeScript中void和undefined不是一回事,undefined在typeScript中式一种明确的简单类型,如果指定返回值为undefined,那么返回值必须写undefined

//无返回值
function eachArr(arr:number[]):void{
    arr.forEach(item => {
        console.log(item)
    })
    //return ; //只写个renturn表示函数结束
}
eachArr([1,2,3,4,5])

6.Interface接口

6.1接口的作用

在TypeScript中使用interface接口来描述对象数据的类型(常用于给对象的属性和方法添加类型约束)

说明:一旦注解接口类型之后,对象的属性和方法类型都需要满足要求,属性不能多也不能少

//接口的作用
interface Person{
    name:string
    age:number,
    height:number
}

const p:Person = {
    name:'zhangsan',
    age:18,
    height:180
}

6.2应用场景

场景:在常规的业务开发中比较典型的就是前后端数据通信的场景

  • 前端向后端发送数据:收集表单对象数据时的类型校验
  • 前端使用后端数据:渲染后端对象数列表时的智能提示

6.3接口的继承

概念:接口的很多属性是可以进行类型复用的,使用extends实现接口继承,实现类型的复用

//原价商品类型
interface GoodsType {
    id:string
    price:number
}

//打折商品类型
// interface DisGoodTpye{
//     id:string
//     price:number
//     disPrice:number
// }
interface DisGoodTpye extends GoodsType{
    disPrice:number
}

7.type注解对象类型

7.1注解对象

概念:在TypeScript中对于对象数据的类型注解,除了使用interface之外还可以使用类型别名来进行注解,作用类似

type Person = {
    name:string,
    age:number
}

const p:Person = {
    name:'mark',
    age:39
}

7.2type+交叉类型模拟继承

类型别名配合交叉类型(&)可以模拟继承、同样可以实现类型复用

//父接口
type GoodsType = {
    id:string
    price:number
}

//子接口继承
type DisGoodType = GoodsType & {
    disPrice:number
}

let goods:DisGoodType = {
    id:'1',
    price:100,
    disPrice:90
}

console.log(goods.disPrice);

7.3 interface对比type

  • 相同点
    • 都能描述对象类型
    • 都能实现继承,interface使用extends。type配合交叉类型(&)
  • 不同点
    • type除了能描述对象还可以用来自定义其它类型
    • 同名interface会合并(属性取并集,不能出现类型冲突),同名type会报错

在注解对象类型的场景下非常相似,推荐大家一律使用tpye。type更加灵活

8.类型推断

类型推断::在TypeScript中存在类型推断机制,在没有给变量添加类型注解的情况下,TypeScript也会给变量提供类型

9.类型断言

作用:有些时候开发者比TypeScript本身更清楚当前的类型是什么,就可以使用断言(as)让类型更加精确和具体

类型断言只能够【欺骗】TypeScript编译器,无法避免运行的时候报错,滥用类型断言会导致运行时错误

说明:利用断言把foo变量的类型指定为精确的number,但是传参的时候还是可以传递number或者是string类型均满足类型要求,但是传递string类型的时候会导致运行时错误

function log(foo:string | number){
    //toFixed:保留几位小数
    console.log((foo as number).toFixed(2));
}

log(100.2345);
log(100)
log('100')

10.泛型

10.1泛型概述

概念:泛型是指在定义接口、函数等类型的时候,不预先指定具体的类型,而是在使用的时候再指定类型的一种特性,使用泛型可以复用类型并且让类型更加灵活

10.2泛型语法

语法:再接口类型的而名称后面使用<T>即可声明一个泛型参数,接口里面的其它成员都能使用该参数类型

通用思路:

  • 找到可变的类型部分通过泛型抽象为反向参数(定义参数)
  • 在使用泛型的时候,把具体的类型传入到泛型参数位置(传参)
infterface  ResData<T> { }
//什么是泛型
interface ResData<T>{

}

//定义了一个具体的类型
interface User{
    name:string
    age:number
}

//使用泛型并传入具体类型
let userData:ResData<User> = {
    code:2000,
    msg:'成功',
    data:{
        name:'张三',
        age:18
    }
}
//什么是泛型
interface ResData<T>{

}

//定义具体的类型
interface Goods{
    goodsName:string
    price:number
}


//使用泛型并传入具体的类型
let goodData:ResData<Goods> = {
    code:2000,
    msg:'成功',
    data:{
        goodsName:'苹果',
        price:18
    }
}

10.3泛型别名

语法:在类型别名type的使用即可声明一个泛型参数,接口里的其它成员都使用该参数类型

type ResData<T> = {  }

案例:需求:使用泛型类型重构ResData案例

//泛型别名
//定义泛型
type ResData<T> = {
    msg:string
    code:number
    data:T
}

//定义具体类型
type User = {
    name:string
    age:number
}
//使用泛型传入具体的类型
let userData:ResData<User> = {
    msg:'success',
    code:200,
    data:{
        name:'jack',
        age:18
    }
}

//定义具体类型
type Goods = {
    id:number
    goodsName:string
}

//使用泛型传入具体的类型
let GoodsData:ResData<Goods> = {
    msg:'success',
    code:200,
    data:{
        id:1,
        goodsName:'火龙果'
    }
}

10.4泛型函数

语法:在函数名称的后面使用 即可声明一个泛型函数,整个函数中(参数、返回值和函数体)的变量都可以使用该参数的类型

function fn<T> () {  }

案例:需求:设置一个函数createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值(多种类型)

function createArray<T>(len:number,value:T){
    let result:Array<T> = [];
    for(let i = 0; i < len; i++){
        result[i] = value;
    }
    return result;
}

console.log(createArray<number>(4,100));
console.log(createArray<string>(4,'a'));

10.5泛型约束

作用:反向的特点就是灵活不确定,有些时候泛型函数的内部需要访问一些特定类型的数据才有属性,此时会有类型错误,需要通过泛型的约束解决

在这里插入图片描述

四、综合案例

需求:记录当前页面的刷新次数和刷新时间,每次刷新都自动加1,并记录,要求使用typescript实现

  • 从本地获取当前最新列表,取出当前列表中的第一条记录
  • 在最后面的一条记录的基础上把次数加1,重新把次数和当前的时间记录到列表的末尾
  • 把最新列表渲染到页面
  • 把最新的列表存入到本地
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
</head>
<body>
    <div></div>


    <script src="./25.综合案例.js"></script>
</body>
</html>
//时间处理函数
function formateTime() {
    var _data = new Date();
    var h = _data.getHours();
    var m = _data.getMinutes();
    var s = _data.getSeconds();
    return "".concat(h, ":").concat(m, ":").concat(s);
}
console.log(formateTime());
var KEY = 'ts-key';
//在浏览器中写入次数和时间
function setData(data) {
    //在localStorage支持存入字符串,将对象转换成字符串
    //JSON.stringify(对象); 可以将对象转换成json格式字符串
    localStorage.setItem(KEY, JSON.stringify(data));
}
//从浏览器中取出
function getData() {
    //需要将取出的字符串转换成对象对象,JSON.parse(json格式的字符串) 转换成对象
    return JSON.parse(localStorage.getItem(KEY) || '[]');
}
// setData([{count:1,time:'16:34:01'}])
// console.log(getData());
//核心业务
//记录当前页面的刷新次数和刷新时间,每次刷新都自动加1,并记录,要求使用typescript实现
function updateData() {
    //1.获取当前的列表
    var list = getData();
    //2.渠道上一条记录
    var lastItem = list[list.length - 1];
    //3.基于上一条记录count自增,然后把新的数据添加到数组的末尾
    //加的是一个DateItem的对象
    list.push({
        count: lastItem ? lastItem.count + 1 : 1,
        time: formateTime()
    });
    //4.把最新的列表存储到本地
    setData(list);
}
updateData();


//数据在页面中展示
let div:HTMLElement = document.querySelector('div') as HTMLElement;
function getStr():string{  
    let newStr:string = '';
    getData().forEach(item => {
        newStr += `<p>访问时间:${item.time},访问次数:${item.count}</p>`
    })
    return newStr;
}
let str = getStr();
div.innerHTML = str;

在这里插入图片描述

标签:TypeScript,string,number,泛型,let,类型,Interface,注解
From: https://blog.csdn.net/qq_63946637/article/details/143493170

相关文章

  • 【typescript】什么是类型参数全局?如何使用它们?
    在TypeScript中,“类型参数全局”并不是一个标准术语,这里是指如何在全局范围内定义和使用类型参数,或者是如何处理全局类型的定义。不过,如果从全局类型的角度来看,我们可以讨论一下如何在TypeScript中定义和使用全局类型,以及如何通过类型参数在全局范围内传递类型信息。全局类......
  • 【typescript】什么是类型参数工具类型?如何使用它们?
    什么是类型参数工具类型?类型参数工具类型(UtilityTypes)是TypeScript提供的内置类型,用于在现有类型的基础上进行转换或修改。这些工具类型可以帮助开发者简化常见的类型操作,如去除属性的可选项、添加只读属性、提取对象的键等。TypeScript的工具类型非常强大,能够显著提高代......
  • Java的泛型
    Java的泛型(Generics)是一种编程技术,它允许类、接口和方法在定义时使用参数化类型。通过泛型,可以编写更加通用和类型安全的代码。以下是Java泛型的一些关键知识点:1. 泛型类(GenericClass)定义泛型类时,使用尖括号 <> 来声明类型参数。例如:publicclassBox<T>{priva......
  • 泛型数组列表_演练
    ex1:基础练习基础练习请尽量独立完成(不要借助AI,实在不会才看参考代码)。原始数组学生类:packageex1;publicclassStudent{protectedStringname;protectedintscore;publicStudent(Stringname,intscore){this.name=name;this.sc......
  • ts:泛型函数(T)
    ts:泛型函数(T)一、主要内容说明二、例子(一)、泛型函数的创建1.源码1泛型函数的创建2.源码1运行效果(二)、泛型与其他类型参数的对比1.源码22.源码2运行效果三、结语四、定位日期一、主要内容说明泛型有几个,有T(type)、V(vuale)、E(element)、U、R等。本文用T,当然T也是......
  • 万能盒子——搞懂泛型,让你的代码更灵活!
    你有没有写过那种“重复性工作”——比如要处理不同类型的数据,写了好几遍相似的代码?这时候,Java的泛型就派上用场了!泛型就像一个“万能盒子”,可以装各种类型的东西,让代码更简洁,还不容易出错。1.什么是泛型?简单来说,泛型就是一种可以让你定义“灵活类型”的机制。用泛型,你......
  • Java-SE-泛型编程-总结/java
    泛型一、泛型的定义和使用类定义:在定义一个泛型类时,需要在类名后加上<T>,以指示这是一个泛型类。例如:publicclassPair<T>{...}方法定义:在定义泛型方法时,需要在返回类型前加上<T>,这样编译器才会知道这是一个泛型方法。例如:public<T>Tadd(Pair<T>p){...}......