typeScript学习笔记(一)

news2025/1/19 7:53:26

学习资源来自:

类与接口 · TypeScript 入门教程 (xcatliu.com) 

一.TypeScript的安装和运行

1.安装TypeScript

  • 通过npm(Node.js包管理器)
  • 安装Visual Studio的TypeScript插件:(Visual Studio 2017和Visual Studio 2015 Update 3默认包含了TypeScript。 如果你的Visual Studio还没有安装TypeScript)

2.npm安装TypeScript

  • 安装教程 TypeScript环境搭建,并且部署到VSCode(亲测有效)_咖啡壶子的博客-CSDN博客
  • 安装过程中问题:

TypeScript- 解决(tsc 不是内部或外部命令,也不是可运行的程序或批处理文件)问题 - sanyekui - 博客园 (cnblogs.com)

3.将环境安装好之后,就可以尝试构建第一个typeScript程序

  • 新建Demo.ts文件
function greeter(person: string) {
  return 'Hello, ' + person
}

let user = 'Jane User'

document.body.innerHTML = greeter(user)
  • 在终端输入: 
    tsc greeter.ts
  • 就会输出一个 包含和输入内容一样的JavaScript代码

      

  • 新建文件demo.html 
<!DOCTYPE html>
<html>
    <head><title>TypeScript Greeter</title></head>
    <body>
        <script src="demo.js"></script>
    </body>
</html>
  •    执行结果会展示在界面上

二.基础类型

1.布尔值

  • true 或者 false
  • 在JS或者TS中叫boolean
  • 语法: let boolean = false
  • 注意:使用Boolean 创造的对象不是布尔值,比如:let createdByNewBoolean: Boolean = new Boolean(1);
  • 直接调用Boolean 也可以返回一个 boolean类型 let createdByBoolean: boolean = Boolean(1);
  • 在TypeScript中,boolean 是基本类型,Boolean 是构造函数 

2.数字类型

  • TypeScript里面所有数字都是浮点数,这些浮点数的类型是Number
  • 除了支持十进制和十六进制字面量,TypeScript还支持ECMAScript 2015 中引入的二进制和八进制
  • 二进制表示法:let binaryLiteral: number = 0b1010;
  • 八进制表示法:let octalLiteral: number = 0o744;
  • 二进制和八进制会被编译为十进制数字      

3.字符串

  • 使用string表示
  • 用单引号或者双引号包起来
  • 可以使用模板字符串 ${`XXX`}

4.数组

  • let list:number[] = [1, 2, 3]
  • let list:Array<number> = [1, 2, 3]

5.元组Tuple

  • 表示一个已知元素数量和类型的数组
  • 各个元素的类型不一定相同
  • let x:[string, number]
  • x = ['hello', 10]

6.枚举

  • enum类型是对JavaScript标准数据类型的一个补充
enum Color {
  Red,
  Green,
  Blue,
}
let c: Color = Color.Green
  • 默认情况下,从0开始为元素编号,可以手动指定成员的数值

enum Color {
  Red = 1,
  Green,
  Blue,
}
let c: Color = Color.Green
console.log(c) // 2
  • 全部采用手动赋值

enum Color {
  Red = 1,
  Green = 2,
  Blue = 4,
}
let c: Color = Color.Blue
console.log(c) // 4
  • 找出映射的名字

enum Color {
  Red = 1,
  Green,
  Blue,
}
let colorName: string = Color[2]
console.log(colorName) // Green

7.任意值 any

  • 需要在编译阶段还不清楚的变量指定一个类型
  • 不希望类型检查器对这些值进行检查,而是直接让它们通过编译阶段的检查
  • 就可以使用any类型来标记这些变量
  • 注意:Object类型的变量只是允许你给他赋任意值,却不能够在它上面调用任意的方法
  • 当你只知道一部分数据的类型时,any类型也是有用的, 比如:
    let list: any[] = [1, true, "free"]
  • 声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值

  • 在声明的之后,未指定其类型,就会被识别为任意值类型

8.空值 void

  • 表示没有任何类型
  • 当一个函数没有返回值时,就会见到void
  • 声明一个void变量没什么用,因为你只能赋予它undefined 和 null

9.null和undefined

  • 与void的区别是,undefined和null是所有类型的子类型,也就是说undefined类型的变量可以赋值给所有类型
  • void的类型不可以

10.never

  • never类型标识永不存在的值的类型
  • never类型是那些总是会抛出异常,或者根本不会有返回值的函数表达式或箭头函数表达式的返回值类型
  • 变量也可能是never类型,当它们被永不为真的类型保护所约束的时候
  • never类型是任何类型的子类型:可以赋值给任何类型
  • 没有类型是never的子类型,就是只能将never类型赋值给never类型
  • any也不可以赋值给never
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) {
    }
}

12.联合类型

  • 表示取值可以为多种类型中的一种
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
  • 联合类型使用 | 分隔每个类型

  • let myFavoriteNumber: string | number;  的含义是允许 myFavoriteNumber 是string类型或者number类型,但是不能是其他类型

  • 当TypeScript不确定一个联合类型的变量到底是哪个类型的时候,只能访问此联合类型中所有属性里共有的属性和方法

11.类型断言

  • 类型断言就相当其他语言中的类型转换(显示转换)
  • 但是不进行特殊的数据检查和解构
  • 没有运行时的影响,只是在编译阶段起作用

  两种形式:

  • 尖括号语法
let someValue: any = 'this is a string'
let strLength: number = (<string>someValue).length
  • as 语法
let someValue: any = 'this is a string'
let strLength: number = (someValue as string).length

12.类型推论

下面代码虽然没有指定类型,但是在编译的时候会报错,TypeScript 会在没有明确的指定类型的时候推测出一个类型,这就是类型推论

let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
  • 如果在定义的时候没有赋值,不管之后有没有赋值,都会被推断为any类型而不被类型检查

三.变量声明

① var和let声明与JavaScript中一致

  • var 声明可以在包含它的函数,模块,命名空间或者全局作用域内部任何位置被访问
  • let 支持块作用域,在声明之前读或者写
  • var可以多次声明,只会取最后一个
  • let如果多次声明就会报错
  • 使用let替换var

② const 声明

  • 赋值后不能被改变
  • 和let的作用域规则相同,但是不能对它们重新赋值
  • 但是可以修改对象内部的值

③ let 和 const 的选择

  • 使用最小特权原则,所有变量除了你计划去修改的都应该使用const
  • 如果需要修改就使用let

④ 解构

解构数组

  • 最简单的解构数组
let input = [1, 2]
let [first, second] = input
console.log(first)
console.log(second)
  • 利用解构交换两个变量的值

let input = [1, 2]
let [first, second] = input
;[first, second] = [second, first]

console.log(first)
console.log(second)
  • 解构用在函数参数上
let input = [1, 2]
function f([first, second]: number[]) {
  console.log(first)
  console.log(second)
}
f(input)
  • 使用剩余参数解构

let [first, ...rest] = [1, 2, 3, 4]
console.log(first)
console.log(rest)
  • 只解构其中一个数据
let [first] = [1, 2, 3, 4]
console.log(first)
  • 将不关心的元素省略

let [, second, , fourth] = [1, 2, 3, 4]
console.log(second)

  解构对象

let o = {
  a: 'foo',
  b: 12,
  c: 'bar',
}
let { a, b } = o
console.log(a)
console.log(b)
  • 属性重命名

let o = {
  a: 'foo',
  b: 12,
  c: 'bar',
}
let { a: name1, b: name2 } = o
console.log(name1)
console.log(name2)
  • 默认值

  • 参数默认值(如果函数没有传参数,就使用初始化列表中的值)

  • 解构表达还是要尽量保持小而简单

⑤ 展开运算符

  • 允许将一个数组展开为另一个数组
let first = [1, 2]
let second = [3, 4]
let bothPlus = [0, ...first, ...second, 5]
console.log(bothPlus) // [0, 1, 2, 3, 4, 5]
  • 将一个对象展开为另一个对象
let defaults = { food: 'spicy', price: '$$', ambiance: 'noisy' }
let bothPlus = { ...defaults, food: 'rich' }
console.log(bothPlus) //

四.接口

  • 在TypeScript中,使用接口(Interfaces)来定义对象的类型
  • 在TypeScript中,除了可用于对类的一部分行为进行抽象以外,也常用于对【对象的形状】进行描述
  • TypeScript核心原则:对值所具有的结构进行类型检查
  • 接口的作用是为这些类型命名和为你的代码或第三方代码定义契约
  • 下面的例子:定义了一个接口,接着定义了一个变量tom,类型是Person,  约束tom的形状必须和接口 Person 一致
  • 定义的变量比接口少了一些属性或者多了一些属性都不被允许,必须和接口的形状保持一致

      

 

  • 可选属性

    ① 有时候希望不要完全匹配一个形状,可以用可选属性

    ② 可选属性的含义就是该属性可以不存在

    ③ 但是仍然不允许添加未定义的属性

  

  • 任意属性  

     ① 有时候我们希望一个接口允许有任意的属性,上面是使用 [propName: string]  定义了任意属性取string 类型的值

    ② 一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集

    ③ 所以下面的案例中,如果任意属性中的值允许是string, 但是可选属性age的值是number,不是string的子属性,所以报错了

④ 一个接口中只能定义一个任意属性,如果接口中有多个类型的属性,则可以在任意属性中使用联合类型

  • 只读属性

  ① 有时候我们希望对象中的一些字段只能在创建的时候被赋值,就使用 readonly 定义只读属性

  ② 只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候

  ③ 只读属性不能进行赋值(无法修改)

interface Point {
  readonly x: number
  readonly y: number
}

let p1: Point = { x: 10, y: 10 }
p1.x = 10   // 会报错,属性是只读属性

③ 只读属性在第一次初始化对象的时候,必须进行初始化

 

  • 数组只读属性

let a: number[] = [1, 2, 3, 4]
// 限制数组是只读类型
let ro: ReadonlyArray<number> = a

ro[0] = 1 // 报错
  • readonly 和 const

    ① 作为变量使用的话就用const

    ② 作为属性就使用  readonly

  •  额外的属性检查

解决方法 ① 

解决方法 ② :添加一个字符串索引签名

解决方法③ 将这个对象赋值给另一个变量,不会经过额外属性检查

五.数组类型

   ①【类型 + 方括号】表示法

let fibonacci: number[] = [1, 1, 2, 3, 5];

  ② 数组的项中不允许出现其他类型

     

  ③ 数组中的一些方法的参数也会根据数组在定义时约定的类型进行限制

   

④ 可以使用数组泛型   Array<elemType>  来表示数组

let fibonacci: Array<number> = [1, 1, 2, 3, 5];

⑤ 用接口表示数组

interface NumberArr {
  [index: number]: number
}
let fib: NumberArr = [1, 2, 3, 4]

   用接口表示数组比较少见,但是经常用它表示类数组(伪数组)

    

使用普通数组不能定义为数组,所以使用接口的形式

   

常用的类数组都有自己的接口定义,比如 IArgumentsNodeListHTMLCollection

function sum() {
  let args: IArguments = arguments
}

IArgument 是TypeScript定义好的类型,实际上就是

interface IArguments {
    [index: number]: any;
    length: number;
    callee: Function;
}

⑥ any在数组中的应用:any表示数组中允许出现任意类型

let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];

六.函数的类型

① 函数声明:

  • 输入多余或者少于的参数,是不被允许的
function sum(x: number, y: number): number {
    return x + y;
}

②  函数表达式

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

TypeScript 中的 => 和 ES6中的箭头不一样,TypeScript中,=>用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型

③ 用接口定义函数的形状

interface SearchFunc {
  (source: string, subString: string): boolean
}

let mySearch: SearchFunc
mySearch = function (source: string, subString: string) {
  return source.search(subString) !== -1
}
  • 用函数表达式或者接口定义函数时,对等号左侧进行类型限制,可以保证对函数名赋值时保证参数的个数,参数类型和返回值类型不变

④ 可选参数

  • 在参数名后面加问号
  • 可选参数后面不允许再出现必选参数

⑤ 参数默认值

  • 允许给函数添加默认值,TypeScript会将添加了默认值的参数识别为可选参数
  • 不受【可选参数必须在必选参数后面】限制了

⑥ 剩余参数

  • ...rest的方式获取函数中的剩余参数
  • rest只能是最后一个参数
function push(array: any[], ...items: any[]) {
  items.forEach(function (item) {
    array.push(item)
  })
}

let a: any[] = []
push(a, 1, 2, 3)

⑦ 重载

  • 重载允许一个函数接受不同数量或类型的参数时,作出不同的处理
  • 注意:多个函数定义如果有包含关系,需要优先把精确的定义写在前面,因为TypeScript会优先从最前面的函数定义开始匹配
function reverse(x: number): number
function reverse(x: string): string
function reverse(x: number | string): number | string | void {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''))
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('')
  }
}

七.类型断言

① 概念

  • 类型断言含义:可以手动指定一个值类型

  • 语法:值 as 类型     <类型>值

  • 在 tsx(React 的 jsx 语法的 ts 版)  语法中必须使用前者

  • <类型>这种语法在ts中除了表示类型断言之外,也有可能是表示一个泛型

  • 所以在使用断言的时候,统一使用 值 as 这样的语法

② 类型断言的用途

(1) 将一个联合类型断言为其中一个类型

  • 此时可以使用类型断言,将 animal 断言成 Fish

  • 使用断言的时候一定要格外小心,尽量避免断言后调用方法或者引用深层属性,减少不必要的运行时的错误

(2)将一个父类断言为更加具体的子类

(3)将任何一个类型断言为any

  • 在any类型的变量上,访问任何属性都是允许的
  • 但是它可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用as any
  • 不能滥用 as any, 也不要完全否定它的作用,需要在类型的严格性和开发的便利性之间掌握平衡

(4)将as断言为一个具体的类型

  • 明确tom的类型之后,提高代码的可维护性

总结

  • 联合类型可以被断言为其中一个类型
  • 父类可以被断言为子类
  • 任何类型都可以被断言为any
  • any可以被断言为任何类型

③ 类型断言的限制

  • 并不是任何一个类型都可以被断言为任何另一个类型
  • 如果A兼容B,那么A能够被断言成B, B也能被断言成A
interface Animal {
  name: string
}
interface Cat {
  name: string
  run(): void
}

function testAnimal(animal: Animal) {
  return animal as Cat
}
function testCat(cat: Cat) {
  return cat as Animal
}
  • 允许animal as Cat 是因为 [父类可以被断言为子类]
  • 允许cat as Animal 是因为既然子类拥有父类的属性和方法,那么被断言为父类,获取父类的方法,就不会有任何问题,所以子类可以被断言为父类
  • 要使A能够被断言成B, 只需要A兼容B或者B兼容A即可

综上所述:

  • 联合类型可以被断言为其中一个类型
  • 父类可以被断言为子类
  • 任何类型都可以被被断言为any
  • any可以被断言为任何类型
  • 要使得 A 能够被断言为 B,只需要 A 兼容 B 或 B 兼容 A 即可

④ 双重断言

interface Cat {
  run(): void
}
interface Fish {
  swim(): void
}

function testCat(cat: Cat) {
  return cat as any as Fish
}
  • 会导致运行时错误,除非迫不得已,千万别使用双重断言

⑤ 类型断言和类型转换

  • 类型断言只会影响到TypeScript编译时的类型,类型断言语句在编译结果中会被删除

  • 类型断言不是类型转换,它不会真的影响到变量的类型
  • 如果要进行类型转换,需要直接调用类型转换的方法

 

 ⑥ 类型断言和类型声明

类型断言

 

  • animal断言为Cat,只需要满足Animal 兼容 Cat 或 Cat 兼容 Animal 即可
  • animal赋值为Cat, 需要满足Cat兼容Animal才行,但是Cat并不兼容Animal
  • 类型声明比类型断言更加严格,最好优先使用类型声明

⑦ 类型断言和泛型

  •  更加规范的实现对 getCacheData 返回值的约束
  • 同时去掉了代码中的any,是最优的一个解决方案
function getCacheData<T>(key: string): T {
  return (window as any).cache[key]
}

interface Cat {
  name: string
  run(): void
}

const tom = getCacheData<Cat>('tom')
tom.run()

八. 声明文件

① 当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全,接口提示等功能

② 声明语句

③ 声明文件:把声明语句放到一个单独的文件中

文件以 .d.ts 为结尾 ,其他所有*.ts文件就可以获得 jQuery 的类型定义了

declare var jQuery: (selector: string) => any;

④ 第三方声明文件

  • 使用 @type 统一管理第三方库的声明文件
  • 直接使用npm 安装对应的声明模块 
    npm install @types/jquery --save-dev

⑤ 书写声明文件

库的使用场景:

  • 全局变量:通过<script>标签引入第三方库,注入全局变量
  • npm: 通过 import foo from 'foo' 导入,符合ES6模块规范
  • UMD 库:既可以通过 <script> 标签引入,又可以通过 import 导入
  • 直接扩展全局变量:通过 <script> 标签引入后,改变一个全局变量的结构
  • 在 npm 包或 UMD 库中扩展全局变量:引用 npm 包或 UMD 库后,改变一个全局变量的结构
  • 模块插件:通过 <script> 或 import 导入后,改变另一个模块的结构

(1)全局变量

declare var/let/const

  • 定义全局变量
  • 使用 declare var 和 declare let 没有区别
  • 使用 declare const 时,表示此时的全局变量是一个常量,不允许再修改它的值了
  • 一般来说,全局变量都是禁止修改的常量,所以大部分情况都应该使用const而不是var 或者 let
  • 声明语句中只能定义类型,不要定义具体的实现

declare function

  • 定义全局函数 
  • declare function jQuery(selector: string): any;
  • 函数类型的声明语句中,函数重载也是支持的

declare function jQuery(selector: string): any;
declare function jQuery(domReadyCallback: () => any): any;

declare class

  • 定义的全局变量是一个类
  • declare class Animal {
        name: string;
        constructor(name: string);
        sayHi(): string;
    }
  •  只能用来定义类型,不能用来定义具体的实现

declare enum

  • 定义枚举类型,也被称为外部枚举
declare enum Directions {
    Up,
    Down,
    Left,
    Right
}
  • declare enum 仅用来定义类型,而不是具体的值

declare namespace

  • 用来表示全局变量是一个对象,包含很多子属性
declare namespace jQuery {
    function ajax(url: string, settings?: any): void;
    const version: number;
    class Event {
        blur(eventType: EventType): void
    }
    enum EventType {
        CustomClick
    }
}
jQuery.ajax('/api/get_something');

嵌套的命名空间

  • 如果对象拥有深层的层级,需要使用嵌套的 namespace 来声明深层的属性的类型
declare namespace jQuery {
    function ajax(url: string, settings?: any): void;
    namespace fn {
        function extend(object: any): void;
    }
}

jQuery.ajax('/api/get_something');
jQuery.fn.extend({
    check: function() {
        return this.each(function() {
            this.checked = true;
        });
    }
});
  • 如果 jQuery 下仅有fn这一个属性,可以不需要嵌套  namespace

declare namespace jQuery.fn {
    function extend(object: any): void;
}


jQuery.fn.extend({
    check: function() {
        return this.each(function() {
            this.checked = true;
        });
    }
});

interface 和 type

  • 声明一个全局的接口或者类型
  • interface AjaxSettings {
        method?: 'GET' | 'POST'
        data?: any;
    }
    declare namespace jQuery {
        function ajax(url: string, settings?: AjaxSettings): void;
    }
    
    
    // src/index.ts
    
    let settings: AjaxSettings = {
        method: 'POST',
        data: {
            name: 'foo'
        }
    };
    jQuery.ajax('/api/post_something', settings);
  • type 与 interface类似

防止命名冲突

  • 暴露在外层 interface 或 type 会作为全局类型作用于整个项目中,应该尽可能减少全局变量或全局类型的数量
  • 所以将他们最好放到 namespace 下
declare namespace jQuery {
    interface AjaxSettings {
        method?: 'GET' | 'POST'
        data?: any;
    }
    function ajax(url: string, settings?: AjaxSettings): void;
}
  • 在使用interface的时候,也应该加上 jQuery 前缀

let settings: jQuery.AjaxSettings = {
    method: 'POST',
    data: {
        name: 'foo'
    }
};
jQuery.ajax('/api/post_something', settings);

声明合并

  •  假如 jQuery 既是一个函数,可以直接被调用 jQuery('#foo'),又是一个对象,拥有子属性 jQuery.ajax()(事实确实如此),那么可以组合多个声明语句,他们会不冲突的合并起来
declare function jQuery(selector: string): any;
declare namespace jQuery {
    function ajax(url: string, settings?: any): void;
}

jQuery('#foo');
jQuery.ajax('/api/get_something');

npm 包

九.内置对象

① ECMAScript  标准提供的内置对象:BooleanErrorDateRegExp,可以在TypeScript中定义以下类型

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;

② DOM和BOM的内置对象

  • DocumentHTMLElementEventNodeList,TypeScript中会经常用到这些类型

③ TypeScript核心库的定义文件

  • 定义了所有浏览器环境需要用到的类型,并且是预置在 TypeScript中
  • 当使用一些常用的方法的时候,TypeScript实际上已经帮你做了很多类型判断的工作
  • TypeScript 核心库的定义中不包含 Node.js 部分
  • 如果想用TypeScript写Node.js,需要引入第三方声明文件 
    npm install @types/node --save-dev

十.类型别名

  • 就是给类型起一个别的名字
  • 使用type创建类型别名
  • 类型别名常用于联合类型
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    } else {
        return n();
    }
}

十一.字符串字面量类型

  • 用来约束取值只能是某几个字符串中的一个
  • 使用type定了一个 字符串字面量类型 EventNames, 只能取三种字符串中的一种
  • 类型别名和字符串字面量类型都是type进行定义的
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
    // do something
}

handleEvent(document.getElementById('hello'), 'scroll');  // 没问题
handleEvent(document.getElementById('world'), 'dblclick'); // 报错,event 不能为 'dblclick'

十二.元组

  • 数组合并了相同类型的对象,元组合并了不同类型的对象
let tom: [string, number] = ['Tom', 25];
let tom: [string, number];
tom[0] = 'Tom';
tom[1] = 25;

tom[0].slice(1);
tom[1].toFixed(2);
  • 也可以赋值其中一项

let tom: [string, number];
tom[0] = 'Tom';
  • 直接对元组类型变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项

  • 越界的元素

① 当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型

十三.枚举

  • 枚举类型用于取值被限定在一定范围内的场景
  • 使用enum关键字来定义
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
  • 手动赋值

     ① 未手动赋值的枚举项会接着上一个枚举递增

     ② 如果未手动赋值的枚举项与手动赋值的重复了,TypeScript是不会报错的

     ③ 所以使用的时候要注意,最好不要有这种情况 

enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};

     ④ 手动赋值的枚举项可以不是数字,这个时候需要使用类型断言来让tsc无视类型检查

enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = <any>"S"};

     ⑤ 手动赋值的枚举项也可以是小数或者负数,未赋值的项逐步增长1

  • 常数项和计算所得项

   ① 枚举项有两种类型,常数项和计算所得项

    常数项:上面的例子就是常数项

    计算所得项:Blue = "blue".length

enum Color {Red, Green, Blue = "blue".length};

② 但是如果紧接在计算所得项后面的是未手动赋值的项,就会因为无法获得初始值而报错

③ 当满足以下条件时,枚举成员被当作是常数

  •  不具有初始化函数并且之前的枚举成员是常数:当前枚举成员的值等于上一个枚举成员的值 + 1,第一个枚举元素的值是0
  • 枚举成员使用常数枚举表达式初始化

数字字面量,引用之前定义的常数枚举成员, 带括号的常数枚举表达式, +-~ 一元运算符应用于常数枚举表达式; +-*/%<<>>>>>&|^ 二元运算符,常数枚举表达式做为其一个操作对象

所有其他情况的枚举成员被当作是需要计算得出的值

④ 常数枚举

  • 使用 const enum 定义的枚举类型
const enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
  • 与普通枚举的区别是,会在编译阶段被删除,并且不能包含计算成员

⑤ 外部枚举

  • 外部枚举是使用 declare enum 定义的枚举类型
declare enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
  • declare和const可以同时使用

declare const enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

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

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

相关文章

长胜证券:资本市场的含义是什么?

本钱商场是指企业和政府通过证券生意来筹集资金并进行出资活动的商场。本钱商场通常被分为两个部分&#xff1a;初级商场和二级商场。初级商场是新证券发行的商场&#xff0c;而二级商场则是已发行证券的生意商场。本钱商场的展开程度是一个国家经济展开的重要目标之一。 从宏…

智能时代的蜕变:人工智能发展历程

原创 | 文 BFT机器人 前沿 2022年底&#xff0c;一款名为ChatGPT的人工智能聊天应用引起了巨大轰动&#xff0c;迅速火遍互联网。与传统的聊天机器人不同&#xff0c;ChatGPT更像是一位能够理解人类的虚拟智能助手&#xff0c;它具备智能推断和学习的能力&#xff0c;能够与用…

长胜证券:主板或以震荡整理为主 结构性行情持续

长胜证券指出&#xff0c;技术面看&#xff0c;沪指3150点上方谨慎看多&#xff0c;缩量横盘整理代表强势&#xff0c;向上打破需市场放量且权重配合&#xff0c;后市若打破并站稳3230点可视为强势回转行情开启&#xff0c;考虑到短期人民币弱势格局&#xff0c;主板或以震动整…

京东方只有一个“王东升”,但需要更多“陈炎顺”

文&#xff5c;新熔财经 作者&#xff5c;谢逊 20多年前&#xff0c;京东方手握30亿元的巨额资产&#xff0c;站在企业发展的十字路口踌躇。 有人建议&#xff0c;买望京的地&#xff0c;进军房地产。 如果真是这样干了&#xff0c;那么今天的京东方应该会是一个吃喝不愁、…

el-tree 懒加载数据,展开的节点与查询条件联动

目录 效果描述实现原理步骤1&#xff1a;el-tree设置node-key步骤2&#xff1a;懒加载时对数据进行处理&#xff0c;给整个树形数据添加唯一值步骤3&#xff1a;(联动) 点击左侧树形结构&#xff0c;右侧对应查询框自动赋值步骤4&#xff1a;(联动) 右侧查询条件选择好后&#…

AWS实例上本地部署ChatGLM2-6B

此篇博客主要介绍如何在AWS上创建带GPU的instance&#xff0c;并在instance上部署ChatGLM大模型。 AWS上申请带GPU的instance ChatGLM虽然也支持在CPU的instance上部署&#xff0c;但这里选择在GPU的instance上部署。所以&#xff0c;先在AWS上选择带GPU的instance。AWS上区分…

Python八连冠!它的资本到底是什么?带你详解Python的牛逼之处

Python 连续八年名列前茅 根据榜单显示&#xff0c;Python 不仅在“Spectrum”综合排名中保持第一的位置&#xff0c;而且远超第二名 Java。 对此&#xff0c;IEEE Spectrum 在发布编程语言榜单时写道&#xff0c;Python 主导地位的增强似乎在很大程度上是以牺牲较小、更专业…

华为云API人脸识别服务FRS的感知力—偷偷藏不住的你

云服务、API、SDK&#xff0c;调试&#xff0c;查看&#xff0c;我都行 阅读短文您可以学习到&#xff1a;人工智能AI人脸的识别、检测、搜索、比对 1、IntelliJ IDEA 之API插件介绍 API插件支持 VS Code IDE、IntelliJ IDEA等平台、以及华为云自研 CodeArts IDE&#xff0c;…

发送信息到我的眼镜上

很久很久以前&#xff0c;购得一个Vufine单目眼镜显示器&#xff0c;最近又拿它来折腾。 通过Pi4的连接&#xff0c;现在可以让任意的网友发送图文到眼镜上。 当然更理想的是通过PiZero2W再加上一个电源即可移动使用。 这里讲了实现的代码&#xff0c;总体也不太复杂。 发送…

ChatGLM2_6b安装

Chatglm2_6b安装 一、安装要求 1、硬件 能否使用,或者以什么模式使用主要取决于显卡的显存 2、能否使用AMD显卡? 可以,甚至可以使用CPU,但是需要降低精度。 以CPU模式运行大概需要32GB 内存。 二:工程与下载 官方路径工程路径: 一代工程: https://github.com/TH…

期权的具体操作步骤详解(期权盈利技巧)

做期权买卖首先我们要清楚在期权中有四个交易方向,分别是期权买方&#xff1a;认购做多&#xff0c;认沽做空&#xff0c;两者互为对手方&#xff0c;期权卖方&#xff0c;卖认购做空&#xff0c;卖认沽做多&#xff0c;只要我们明白了期权的方向即可判断做出选择&#xff0c;下…

算法 数据结构 斐波那契数列 递归实现斐波那契数列 斐波那契递归的优化 斐波那契数列递归求解 多路递归实现 斐波那契算法系列 数据结构(十一)

1. 什么是斐波那契数列&#xff1a; 之前的例子是每个递归函数只包含一个自身的调用&#xff0c;这称之为 single recursion 如果每个递归函数例包含多个自身调用&#xff0c;称之为 multi recursion 递推关系 下面的表格列出了数列的前几项 F0F1F2F3F4F5F6F7F8F9F10F11F12…

空气传导耳机哪个牌子好?市面上热销火爆的气传导耳机推荐

​传统入耳式耳机佩戴着容易滑落&#xff0c;戴不稳&#xff0c;久戴耳朵酸痛等问题&#xff0c;气传导耳机的出现就避免了这些问题的发生&#xff0c;我来推荐几款市面上热销火爆且使用感不错的气传导耳机给到大家&#xff0c;来看看吧&#xff01; 推荐1&#xff1a;NANK南卡…

[ubuntu]给WSL子系统ubuntu安一个桌面环境

sudo apt install xorg sudo apt install xfce4 sudo apt install xrdp sudo sed -i s/port3389/port3390/g /etc/xrdp/xrdp.ini sudo echo xfce4-session >~/.xsession sudo service xrdp restart 查看自己ip地址&#xff1a; ifconfig 然后在windows上任务栏搜远程桌面 …

亚马逊鲲鹏系统全自动化功能有哪些

亚马逊鲲鹏系统可以批量注册亚马逊买家号、AI智能养号、自动绑定收货地址及支付卡、开通二步验证、自动添加购物车、自动购买、自动留评、评论点赞或举报、QA等。 下面就详细介绍一下一些比较常用的自动化功能&#xff1a; 1、全自动注册 想要注册买家号&#xff0c;那么需要…

自动化测试基础知识详解

前言 有颜色的标注主要是方便记忆&#xff0c;勾选出个人感觉的重点 块引用&#xff1a;大部分是便于理解的话&#xff0c;稍微看看就行&#xff0c;主要是和正常的文字进行区分的 1、什么是自动化测试 自动化测试是软件测试活动中一个重要分支和组成部分&#xff0c;随着软…

Leetcode128. 最长连续序列

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 题解&#…

java 版本企业招标投标管理系统源码+功能描述+tbms+及时准确+全程电子化

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

WINGREEN 034STN1-01-300-R 传感器模块

WINGREEN 034STN1-01-300-R 是一种传感器模块&#xff0c;通常用于监测和采集各种环境或过程参数的数据。以下是这种类型的传感器模块通常可能具备的一般功能和特点&#xff1a; 传感器接口&#xff1a;模块通常配备用于连接不同类型传感器的接口&#xff0c;如温度传感器、湿度…

贝塞尔曲线的一些资料收集

一本免费的在线书籍&#xff0c;供你在非常需要了解如何处理贝塞尔相关的事情。 https://pomax.github.io/bezierinfo/zh-CN/index.html An algorithm to find bounding box of closed bezier curves? - Stack Overflow https://stackoverflow.com/questions/2587751/an-algo…