总结TypeScript相关知识

news2024/10/7 10:12:02

目录

  • 引入
  • 认识
  • 特点
  • 安装使用
  • 变量
    • 声明
    • 类型推导
  • 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
    

泛型

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

映射类型

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

条件类型

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

类型体操

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

模块-声明-配置

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[统计分析] 出现典型锯齿图的一种情况;资源泄露

接上回说&#xff0c;https://mzhan017.blog.csdn.net/article/details/142689870&#xff1b; 在问题分析的过程中发现产品里的一个统计计数出现了下面的锯齿型。而这个问题的表象之一是每隔一段时间&#xff0c;业务程序重启。所以产生这个锯齿形的原因之一就是业务程序重启&…

【C++ STL算法】二分查找 lower_bound、upper_bound、equal_range、binary_search

文章目录 【 1. 首个不小于 lower_bound 】【 2. 首个大于 upper_bound 】【 3. 所有等于 equel_range 】【 4. 二分查找 binary_search 】 当 指定区域内的数据处于有序状态 时&#xff0c;如果想查找某个目标元素&#xff0c;更推荐使用二分查找的方法&#xff08;相比顺序查…

openpnp - juki吸嘴尺寸

文章目录 openpnp - juki吸嘴尺寸概述笔记吸嘴可以对应的最小元件尺寸END openpnp - juki吸嘴尺寸 概述 在网上买的juki吸嘴的商品页面&#xff0c;并没有具体的吸嘴尺寸。 现在贴片时&#xff0c;要根据吸嘴外径大小来决定具体元件要用哪种吸嘴&#xff0c;先自己量一下。 …

研究生系统化入门教程(四)【机器学习】分类算法:决策树(信息熵,信息增益);集成学习方法之随机森林:估计器的工作流程是什么?为何采用BootStrap抽样?

“一般人都不是他们想要做的那种人,而是他们不得不做的那种人。——毛姆《月亮与六便士》” 🎯作者主页: 追光者♂🔥 🌸个人简介: 📝[1] CSDN 博客专家📝 🏆[2] 人工智能领域优质创作者🏆 🌟[3] 2022年度博客之星人工智能领域TOP4🌟 �…

鸿蒙next开发第一课03.ArkTs语法介绍-案例

前面已经学习了ArkTs的基本语法和DevEcoStudio的基本操作&#xff0c;接下来按照官方提示开发一个基本案例。 该案例是系统自带的demo&#xff0c;下载下来源代码后可以直接运行。 接下来我来演示如何运行demo。我在demo中加入了自己的注释。 切记&#xff1a;文件夹不能有中…

Crypto虐狗记---”你“和小鱼(七)

前言&#xff1a;剧情七 提示&#xff1a; 下载&#xff1a; 脚本&#xff1a; cyberpeace{125631357777427553} RSA算法_百度百科 (baidu.com)

VMware Tools 安装和配置

1. 使用 ISO 映射文件&#xff0c;并且选择.iso文件 2. 启动虚拟机&#xff0c;如果 VMware Tools 是灰色的&#xff0c;那么卸载 open-vm-tools&#xff08;不要重装&#xff09;&#xff0c;重新启动虚拟机。卸载可以参考&#xff1a;重装 open-vm-tools-CSDN博客 3. 拷贝挂载…

[C++]使用纯opencv部署yolov8-cls图像分类onnx模型

【算法介绍】 使用纯OpenCV部署YOLOv8-cls图像分类ONNX模型涉及几个关键步骤。 首先&#xff0c;你需要将YOLOv8-cls模型从PyTorch格式转换为ONNX格式&#xff0c;这是为了确保模型在不同深度学习框架之间的互操作性。这个转换过程通常是通过ultralytics框架中的model.export…

请求响应-08.响应-案例

一.案例 获取员工数据&#xff0c;返回统一响应结果&#xff0c;在页面上渲染展示 二.展示最终效果 三.步骤 步骤一&#xff1a; <dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.3<…

C语言 | Leetcode C语言题解之第460题LFU缓存

题目&#xff1a; 题解&#xff1a; /* 数值链表的节点定义。 */ typedef struct ValueListNode_s {int key;int value;int counter;struct ValueListNode_s *prev;struct ValueListNode_s *next; } ValueListNode;/* 计数链表的节点定义。 其中&#xff0c;head是数值链表的头…

【Canvas与色彩】十六等分多彩隔断圆环

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>隔断圆环Draft5十六等分多彩</title><style type"text…

MyBatis-MP这个ORM框架强过你写的100行SQL,操作简单到不敢相信

MyBatis-MP这个ORM框架强过你写的100行SQL&#xff0c;操作简单到不敢相信 在繁杂的 Java 项目中&#xff0c;如何优雅、高效地进行数据库操作&#xff1f;MyBatis-MP&#xff0c;一个基于 MyBatis 的轻量级 ORM 框架&#xff0c;或许就是你的救星&#xff01;本文将介绍 MyBat…

Android车载——VehicleHal运行流程(Android 11)

1 概述 本篇主要讲解VehicleHal的主要运行流程&#xff0c;包括设置属性、获取属性、订阅属性、取消订阅、持续上报属性订阅等。 2 获取属性流程 2.1 获取属性流程源码分析 作为服务注册到hwServiceManager中的类是VehicleHalManager&#xff0c;所以&#xff0c;CarServic…

第十四章 Redis之全局唯一ID(分布式集群)

目录 一、概念 ‌二、全局唯一ID的生成方法‌ 三、Redis生成全局ID 3.1. 生成策略 3.2. 代码 一、概念 全局唯一ID是指在分布式系统中&#xff0c;每个实体都有一个唯一的标识符&#xff0c;确保在不同的节点或服务之间能够唯一标识一个实体。这种唯一性对于数据的一致性…

软件系统建设方案案例(word原件,文档系统)

文档管理系统建设的主要意义在于提升组织内部文档管理的效率、安全性和便利性。首先&#xff0c;通过集中存储和分类管理&#xff0c;文档管理系统能够迅速检索和共享文件&#xff0c;大幅提高工作效率。其次&#xff0c;系统内置的权限控制功能确保文档的安全&#xff0c;防止…

QT调用最新的libusb库

一&#xff1a;下载libusb文件 下载最新的库的下载网站&#xff1a;https://libusb.info/ 下载&#xff1a; 解压后目录如下&#xff1a; 二&#xff1a;库文件添加QT中 根据自己的编译器选择库&#xff1a; ①将头文件中添加libusb.h ②源文件中添加libusb-1.0.lib ③添加…

Linux:进程的创建、终止和等待

一、进程创建 1.1 fork函数初识 #include pid_t fork(void); 返回值&#xff1a;子进程中返回0&#xff0c;父进程返回子进程id&#xff0c;出错返回-1 调用fork函数后&#xff0c;内核做了下面的工作&#xff1a; 1、创建了一个子进程的PCB结构体、并拷贝一份相同的进程地址…

【C++】继承(万字详细总结)

「前言」 &#x1f308;个人主页&#xff1a; 代码探秘者 &#x1f308;C语言专栏&#xff1a;C语言 &#x1f308;C专栏&#xff1a; C &#x1f308;喜欢的诗句:天行健,君子以自强不息. 前言&#xff1a;面向对象三大特性是&#xff1a;封装、继承、多态&#xff0c;今天的篇…

【社保通-注册安全分析报告-滑动验证加载不正常导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

MES系统在数字化转型中的重要性

实现生产过程的数字化与智能化&#xff1a; 实时监控与数据采集&#xff1a;MES系统通过实时监控和数据采集&#xff0c;将传统的手工记录和管理转变为数字化的自动化过程&#xff0c;实现了生产过程的数字化和智能化管理。这种转变使得生产数据更加准确、及时&#xff0c;为生…