TypeScript详解

文章目录

      • [一.TS 基础概念](#一.TS 基础概念)
        • 1.什么是TS
        • 2.TS基础类型与写法
        • [* boolean string number array null undefined](#* boolean string number array null undefined)
        • [* tuple - 元组](#* tuple - 元组)
        • [* enum - 枚举](#* enum - 枚举)
        • [* any unknown void](#* any unknown void)
        • [* object | Object | {} - 对象](#* object | Object | {} - 对象)
      • [二. 接口 - interface](#二. 接口 - interface)
      • 三.交叉类型
      • [四.断言 - 类型声明,转换](#四.断言 - 类型声明,转换)
      • [五.类型守卫 -Type Guards](#五.类型守卫 -Type Guards)
      • 六.TS进阶
        • [1.泛型(Generics) - 重用](#1.泛型(Generics) - 重用)
        • [2.装饰器 - decorator](#2.装饰器 - decorator)

一.TS 基础概念

1.什么是TS
  • 对比原理

  • ts是 js 的一个超集,在原有基础上添加了

  • 可选静态类型

  • 基于类的面向对象编程

  1. 编写项目 - 更利于架构维护
  2. 自主检测 - 编译期间检测
  3. 类型检测 - 支持了动态和静态类型检测;ts不是强类型语言=》本质上还是存在类型转换
  4. 运行流程 - 依赖编译
  5. 复杂特性 - 模块化,泛型,接口
2.TS基础类型与写法
* boolean string number array null undefined
typescript 复制代码
// es
let isEnable = true;
let class = "ts";
let classNum = 2;
let classArr = ["basic","execute"];

// ts
let isEnable:boolean = true;
let class:string = "ts";
let classNum:number = 2;
// 数组的两种写法
let classArr:string[]= ["basic","execute"];
let classArr:Array<string> = ["basic","execute"];
* tuple - 元组

数组的搭配比较多样,用来声明数组中有多种类型时使用

typescript 复制代码
let tupleType:[string,boolean] 
  tupleType =["ts",true]
* enum - 枚举
typescript 复制代码
// 数字枚举- 默认从零开始,依次递增
enum Score {
  BAD,
  NG,
  GOOD,
  PERFECT
}
let score:Score = Score.BAD;

// 字符串类型
enum Score {
  BAD="BAD",
  NG="NG",
  GOOD="GOOD",
  PERFECT="PERFECT"
}

// 反响映射
enum Score {
  BAD,
  NG,
  GOOD,
  PERFECT
}
let scoreName = Score[0]; // "BAD",因为默认依次递增
let scoreValue = Score["BAD"];// 0

// 异构 (数字和字符串都有)
// 字符串设置什么就是什么
// 数字类型依据上一个加一
enum Score {
  A, //0
  B, //1
  C='C',
  D="D",
  E=6,
  F // 7
}
* any unknown void
typescript 复制代码
// 输入
//any - 绕过所有检查 => 类型检测和编译筛查全部失效
let anyValue:any =123;

anyValue ="anyValue";

// unknown - 绕过赋值检查=> 禁止更改传递
// 传递
let unkonwnValue:unknown;

 unknownValue="unknownValue";

let value1:unknown =unknownValue;//ok
let value2:any=unknownValue;//ok
let value3:boolean = unknownValue;/nok

// 返回
// void - 声明函数返回值 不返回任何值
function voidFunction():void{
  console.lg("no return")
}

// nerver - 永不返回
function error(msg:string):never{
  throw new Error(msg)
}
function longlongloop():never{
  while(true)
}
* object | Object | {} - 对象
typescript 复制代码
// object - 非原始类型
interface ObjectConstrutor {
  create(o:object | null):any;
}

const proto = {};
Object.create(proto);//ok

// Object  - 原型属性
// Object.prototype 上的属性
interface Object {
  constructor:Function;
  toString():string;
  valueOf():Object
}

// {} - 空对象 - 没有成员的对象
const a = {} as A; // 通过断言来设置
a.class = "es"; 
a.name=30; // {} 表示空对象,赋值会抛出异常

二. 接口 - interface

在TypeScript中,接口是一种定义对象形状的方式,它描述了对象应该有哪些属性和方法,但并不直接提供这些属性和方法的实现。接口主要用于确保类或其他结构(如对象字面量)符合特定的契约

  1. 定义属性:接口可以定义对象的属性类型,但不包括属性值。
  2. 定义方法:接口可以定义对象的方法,但不包括方法的实现
  3. 只读属性:使用 readonly 关键字可以定义只读属性,即这些属性只能做对象被创建时被赋值,之后不能被修改
  4. 继承接口:一个接口可以继承另一个或者多个接口,从而继承它们的属性和方法
javascript 复制代码
interface Class {
  name:string;
  time:number
}
let course:Class = {
  name:"ts",
  time:2
}

//只读
interface Class {
  readonly name:string;
  time:number
}
// 任意
interface Class {
  name:string;
  time:number
  [propName:string]:any
}
// 面试题:ts 和 js的引用的不同
let arr:number[] = [1,2,3,4];
let ro:ReadonlyArray<number> = arr;

ro[0] = 12; //Error - 只读状态不可赋值
ro.push(5); //Error - 增加
ro.length = 100; //Error - 长度改写

arr = ro;//Error - 覆盖

//定义方法
interface Greeter {
  greet(message: string): void;
}

class PersonGreeter implements Greeter {
  greet(message: string) {
    console.log(`Hello, ${message}`);
  }
}

//继承
interface Named {
  name:string;
}
interface Person extends Named{
  age:number
}

const person:Person = {
  name:"张三",
  age:18
}

三.交叉类型

在TypeScript中,交叉类型是一种组合多个类型到一个单一类型的方式。通过交叉类型,你可以创建一个新的类型,这个类型具有所有被组合类型的特性。当一个对象具有多个类型的属性时通过&符号来定义的

  • 交叉类型和运算符里面的 与( && ) 是一样的,既要 ... 又要 ... 还要
  • 可以把两个对象合并到一个对象
typescript 复制代码
// 合并
interface A {x:D}
interface B {x:E}
interface C {x:F}

interface D {d:boolean}
interface E {e:string}
interface F {f:number}

type ABC = A & B & C;

let abc:ABC ={
  x:{
    d:false,
    e:"class",
    f:5
  }
}

// 合并冲突
interface A {
  c:string;
  d:string
}
interface B {
  c:number;
  d:string
}
type AB = A & B;
// 合并关系是并且 => c:never

四.断言 - 类型声明,转换

在TypeScript中,断言是一种告诉编译器我们对某个表达式类型的明确预期的方式。通过使用断言,我们可以为编译器提供额外的信息,以确保在编译时能够正确地处理类型。断言不仅用于声明变量的类型,还可以用于在类型之间进行显式转换,从而确保代码的类型安全性。

typescript 复制代码
// 尖括号
let anyValue:any = 'hi ts';
// 当anyValue是 string 时去取length
let anyLength:number = (<string>anyValue).length; //阶段性声明;

// as 声明
let anyLength:number = (anyValue as string).length; //阶段性声明;

// 非空判断 - 非空断言操作符 !
// 非空断言操作符,用于告知编译器我确定这个值是非空的,不需要再进行类型检查
type ClassTime = () => number;

const start = (classTime:ClassTime | undefined)=>{
  let num = classTime!(); //确认一定不会为空
}

五.类型守卫 -Type Guards

在TypeScript中,类型守卫是一种特殊的表达式,它允许你执行运行时检查以缩小一个值的类型范围。类型守卫可以用于确保一个值是某种特定的类型,或者在多种类型之间进行区分。

typeof | instanceof 类型守卫

在TypeScript中,typeof 和 instanceof 运算符被特殊对待,并被认为是类型守卫。当它们用于类型检查时,TypeScript会缩小变量的类型范围。

typescript 复制代码
interface Teacher {
  name:string;
  courses:string[];
}
interface Student{
  name:string;
  startTime:Date;
}

type Class = Teacher | Student

function startCourse(cls:Class){
    if('courses' in cls){
      // teacher
    }
    if("startTime" in cls){
      // student
    }
}

function startCourse(cls:Class){
    if(cls intanceof Teacher){
      // teacher
    }
    if(cls intanceof Student){
      // student
    }
}

function startCourse(name:string,score:string | number){
    if(typeof score === "number"){
      // teacher
    }
    if(typeof score === "string"){
      // student
    }
}

六.TS进阶

1.泛型(Generics) - 重用

在 TypeScript 中,泛型是一种允许你为组件(如类、接口和函数)创建可复用的类型的方式,而无需在每次使用组件时都明确指定类型。泛型提供了一种创建可重用组件的方式,这些组件可以工作于多种数据类型。

  1. 泛型函数:泛型函数是指在调用指定类型参数的函数。在函数后面使用(其中 T 是类型变量)
  2. 泛型类:泛型类是在类定义中使用类型变量的类
  3. 泛型接口:中接口定义中引入类型变量
  4. 泛型约束:定义泛型时,可以对泛型参数添加一些约束,以确保它符合某些结构。可以通过中类型参数上设置extends 约束来实现
  5. 类型推断与默认类型:typeScript的类型推断机制可以自动推断泛型类型参数;泛型类型可以设置默认类型
typescript 复制代码
//泛型函数
function startClass<T,U>(name:T,score:U):T{
  return name + score
}

console.log(startClass(<string,number>('yy',5)))

function startClass<T,U>(name:T,score:U):string{
  return `${name}${score}`
}

function startClass<T,U>(name:T,score:U):T{
  return (name + String(score)) as any as T;
}

// 泛型接口
interface GenericIdentityFn<T> {
    (arg: T): T;
}
function identityFn<T>(arg: T): T {
    return arg;
}
let myIdentity: GenericIdentityFn<number> = identityFn;


// 泛型约束
interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // 现在我们可以访问.length属性了
    return arg;
}

// 使用泛型约束
loggingIdentity({length: 10, value: 3});
2.装饰器 - decorator

在 TypeScript 中,装饰器是一种特殊类型的声明,它可以被附加到类声明、方法、访问符、属性或参数上。装饰器使用 @expression 的形式,其中 expression 必须在运行时求值为一个函数,它将在编译时调用,

装饰器可以使用在许多不同的上下文中,但它们的主要用途是修改类的行为,为类添加元数据,或者为类、方法、属性等提供额外的功能。

typescript 复制代码
function Roo(target:Function):void{
  // 拿到的类
  target.prototype.startClass = function():void{
    // 逻辑
  }
}

// 类装饰器
@@Roo
class Course {
  constructor(){
    // 业务逻辑
  }
}

// 属性装饰器
function nameWrapper(target:any,key:string){
  // 逻辑处理
  Object.defineProerty(target,key){
    // 数据劫持
  }
}

class Course {
  constructor(){
    // 业务逻辑
  }
  @nameWrapper
  public name:string
}
相关推荐
m0_748257185 分钟前
Spring Boot FileUpLoad and Interceptor(文件上传和拦截器,Web入门知识)
前端·spring boot·后端
桃园码工23 分钟前
15_HTML5 表单属性 --[HTML5 API 学习之旅]
前端·html5·表单属性
百万蹄蹄向前冲1 小时前
2024不一样的VUE3期末考查
前端·javascript·程序员
轻口味1 小时前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami1 小时前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
wakangda2 小时前
React Native 集成原生Android功能
javascript·react native·react.js
吃杠碰小鸡2 小时前
lodash常用函数
前端·javascript
emoji1111112 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼2 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250032 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html