2024年最新前端工程师 TypeScript 基础知识点详细教程(更新中)

1. TypeScript 概述

TypeScript 是由微软开发的、基于 JavaScript 的一种强类型编程语言。它是在 JavaScript 的基础上添加了静态类型检查、面向对象编程等功能的超集,最终会被编译为纯 JavaScript 代码。由于其扩展了 JavaScript 的功能,TypeScript 特别适合大型项目和团队协作,能够提高代码的可读性、可维护性和开发效率。

TypeScript 是由微软开发的、基于 JavaScript 的一种强类型编程语言。它是在 JavaScript 的基础上添加了静态类型检查、面向对象编程等功能的超集,最终会被编译为纯 JavaScript 代码。由于其扩展了 JavaScript 的功能,TypeScript 特别适合大型项目和团队协作,能够提高代码的可读性、可维护性和开发效率。

1.1 TypeScript 优势

提高代码质量:通过静态类型检查,TypeScript 能在编译阶段捕捉潜在的错误,从而减少运行时错误,提高代码的稳定性。更好的协作:类型信息使得团队中的其他开发者能够更容易理解代码结构和预期行为,改善协作效率。增强的开发工具:由于 TypeScript 是强类型语言,编辑器可以提供更好的代码补全、重构支持,以及更加详细的错误提示。兼容 JavaScript:TypeScript 是 JavaScript 的超集,意味着所有的 JavaScript 代码都是合法的 TypeScript 代码。可以逐步将现有的 JavaScript 项目迁移到 TypeScript。面向大型项目:TypeScript 特别适合开发大型代码库,因为它提供了更严格的类型检查和结构化的开发方式,确保代码更易于维护。

1.2 TypeScript 和 JavaScript 区别

TypeScript 和 JavaScript 在类型系统、编译过程、特性支持以及开发体验等方面存在显著差异。TypeScript 通过引入静态类型系统和一系列新特性,为 JavaScript 开发提供了更好的支持和保障。然而 JavaScript 作为一种广泛应用的脚本语言,其灵活性和动态性也是其独特优势之一。因此,在选择使用 TypeScript 还是 JavaScript 时,需要根据具体的项目需求和团队技术栈来做出决策。

类型系统区别

JavaScript:JavaScript是一种动态类型语言,其变量的类型是在运行时确定的,并且可以随时更改。这意味着在JavaScript中,你不需要(也不能)在编写代码时显式地声明变量的类型。

TypeScript:TypeScript引入了静态类型系统,允许开发者在编写代码时显式地声明变量、函数参数和返回值的类型。这使得TypeScript能够在编译时检查代码中的类型错误,提供更早的错误检测和更好的代码健壮性。

编译过程区别

JavaScript:JavaScript 代码可以直接在浏览器或者 Node.js 环境中运行,无需编译。它是一种解释型语言,代码在执行过程中被逐行解释。

TypeScript:TypeScript 代码需要通过编译器(如TypeScript Compiler,简称 tsc)将其编译成 JavaScript 代码,然后才能在浏览器或 Node.js 环境中运行。这个编译过程包括了类型检查、代码转换等步骤,确保了代码的质量。

特性支持区别

JavaScript:虽然 JavaScript 拥有广泛的应用和强大的生态系统,但其本身在类型检查、模块化、面向对象编程等方面存在局限性。不过,随着 ECMAScript 标准的不断发展,JavaScript 也在逐渐引入新的特性和语法来弥补这些不足。

TypeScript:TypeScript 在 JavaScript 的基础上添加了类型注解、接口、类、泛型等特性,使得代码更加结构化、可组织性更强,并且更易于维护和重构。此外 TypeScript 还支持 ECMAScript 的各个版本,并添加了一些额外的语言特性和功能。

开发体验区别

JavaScript:由于 JavaScript 的动态类型和解释型特性,开发者在编写代码时可能会遇到一些难以追踪的错误。此外,缺乏类型检查也使得代码的可读性和可维护性受到一定影响。

TypeScript:TypeScript 的静态类型系统、类型注解和类型推断等功能能够显著提高代码的可读性和可维护性。同时,TypeScript 还提供了强大的开发工具支持(如 Visual Studio Code 等),这些工具能够提供代码补全、类型检查、重构等功能,从而进一步提升开发效率。

特性JavaScriptTypeScript
类型系统动态类型静态类型,可选
编译不需要编译,直接运行需要编译为 JavaScript 运行
支持面向对象编程有限支持完整支持类、接口、抽象类等
开发工具支持基础代码补全强大的代码补全、类型推断、错误提示
泛型不支持支持

1.3 TypeScript 适用场景

大型项目:在大型项目中,代码的复杂度增加,TypeScript 的类型系统和模块化特性能够极大提升代码的可维护性和可扩展性。团队合作:TypeScript 能够在多人协作时提供统一的类型约束,减少沟通成本,避免类型不匹配导致的问题。需要高代码质量和安全性:如果项目要求严格的代码质量和运行时安全,TypeScript 提供的类型检查和编译时错误提示非常有用。

1.4 TypeScript 官方网站

官网提供了详尽的文档,包括TypeScript的入门指南、手册、教程等,帮助用户从基础到高级逐步掌握TypeScript。文档中包含了TypeScript的语法、类型系统、接口、泛型、枚举等核心概念的解释和示例。

中文官网:https://www.tslang.cn/
英文官网:https://www.typescriptlang.org/

在这里插入图片描述

2. TypeScript 特性

TypeScript 通过引入静态类型检查、提供更好的开发工具支持和增强代码可维护性等特性,提升了 JavaScript 的开发体验,使得代码更健壮、可靠,并且更易于协作和扩展。它适用于大型项目和团队开发,为 JavaScript 开发者提供了更强大的工具和能力。

2.1 静态类型(Static Typing)

TypeScript 允许开发者为变量、函数参数和返回值等指定类型,并在编译时进行类型检查。这有助于捕捉潜在的错误,并在编写代码时提供更好的代码提示和自动补全。

let age: number = 30;
let name: string = "John";
let isActive: boolean = true;function greet(userName: string): string {return `Hello, ${userName}`;
}

2.2 类型推断(Type Inference)

虽然 TypeScript 需要为变量指定类型,但如果没有明确指定类型,TypeScript 会根据上下文自动推断类型。这使得 TypeScript 在保证类型安全的同时,依然保持了编写 JavaScript 的简洁性。

let count = 10; // TypeScript 自动推断 count 的类型为 number

2.2 接口(Interfaces)

接口是 TypeScript 中的核心概念之一,它用于定义对象的结构。接口规定了对象必须包含的属性和方法。接口可以在类、函数参数、对象定义中使用,以确保代码的一致性和类型安全。

interface Person {name: string;age: number;greet(): void;
}let user: Person = {name: "Alice",age: 25,greet() {console.log("Hello!");}
};

2.3 类和继承(Classes and Inheritance)

TypeScript 完全支持面向对象编程,包括类、继承、接口实现、访问控制修饰符(例如: publicprivateprotected)。TypeScript 的类与 ES6 类语法非常类似,但它提供了更多功能,如抽象类和成员可见性控制。

class Animal {constructor(public name: string) {}move(distance: number) {console.log(`${this.name} moved ${distance} meters.`);}
}class Dog extends Animal {bark() {console.log("Woof! Woof!");}
}const dog = new Dog("Buddy");
dog.bark();
dog.move(10);

2.4 泛型(Generics)

TypeScript 支持泛型(Generics),使得函数、类和接口可以更灵活地处理不同的数据类型,同时保持类型安全。这对于创建可重用的组件非常有用,特别是在处理集合或映射类型时。

function identity<T>(arg: T): T {return arg;
}let output = identity<string>("Hello");
let output2 = identity<number>(123);

2.5 枚举(Enums)

枚举允许为一组相关的值定义有意义的名字,提供了更具可读性的代码。

enum Color {Red,Green,Blue}let c: Color = Color.Green;

2.6 类型别名(Type Aliases)

类型别名可以为类型定义一个简洁的名称,尤其适用于联合类型(Union Types)、交叉类型(Intersection Types)等复杂类型的场景。

   type StringOrNumber = string | number;let value: StringOrNumber = "Hello";value = 123; // 也可以是数字

2.7 模块系统(Modules)

TypeScript 使用 ES6 的模块系统,可以使用 importexport 来组织代码。模块使得代码更加模块化、易于管理和复用。

utils.ts

export function add(x: number, y: number): number {return x + y;
}

main.ts

import { add } from './utils';
console.log(add(2, 3));

2.8 工具支持和开发体验

TypeScript 通过静态类型和类型检查,提供了强大的代码自动补全、重构和错误检测功能。大多数现代 IDE(如 Visual Studio Code、WebStorm)都提供了对 TypeScript 的良好支持,能够极大提升开发体验。

TypeScript 是一种在 JavaScript 之上扩展的语言,通过引入静态类型检查、面向对象特性和丰富的工具支持,极大地提升了代码的可维护性、可读性和开发效率。无论是大型项目还是小型应用,TypeScript 都能为开发者提供更好的编程体验。

3. 编译 TypeScript

要编译 TypeScript 代码,需要使用 TypeScript 编译器(tsc),这是 TypeScript 官方提供的编译工具。编译 TypeScript 非常简单,主要步骤包括安装 TypeScript 编译器、编写 .ts 文件、使用 tsc 命令编译,并运行编译生成的 JavaScript 文件。通过 tsconfig.json,可以定制编译选项和简化编译流程。下面是编译 TypeScript 代码的详细步骤。

3.1 安装 TypeScript 编译器

首先,你需要在本地环境中安装 TypeScript 编译器。可以通过 npm(Node.js 的包管理工具)来安装 TypeScript。此命令会全局安装 TypeScript 编译器,安装完成后,可以在命令行中使用 tsc 命令。

npm install -g typescript

3.2 编写 TypeScript 代码

创建一个扩展名为 .ts 的文件,例如 example.ts,并编写一些 TypeScript 代码。

example.ts

function greet(name: string): string {return `Hello, ${name}!`;
}const user = "World";
console.log(greet(user));

3.3 编译 TypeScript 文件

在终端或命令行中,使用 tsc 命令编译 TypeScript 文件。运行此命令后,TypeScript 编译器会将 example.ts 编译为 JavaScript 文件,生成一个名为 example.js 的文件。

tsc example.ts

example.js(编译后 JavaScript)

function greet(name) {return "Hello, " + name + "!";
}
var user = "World";
console.log(greet(user));

3.4 执行编译后 JavaScript

编译完成后,生成的 JavaScript 文件可以直接在任何支持 JavaScript 的环境中运行,例如 Node.js 或浏览器。用 Node.js 来运行编译后的 example.js 文件。

node example.js

输出结果

Hello, World!

3.5 使用 tsconfig.json 文件(可选)

在实际项目中,可以通过创建一个 tsconfig.json 文件来配置 TypeScript 编译选项,从而简化编译过程。首先运行以下命令来生成 tsconfig.json 文件。

tsc --init

生成的 tsconfig.json 文件会包含多种编译选项,可以根据项目需求修改。

{"compilerOptions": {"target": "es6",                // 指定 ECMAScript 目标版本"module": "commonjs",           // 指定模块系统"strict": true,                 // 启用所有严格类型检查选项"outDir": "./dist",             // 输出文件夹"rootDir": "./src",             // 输入文件夹"esModuleInterop": true         // 支持 ES 模块的互操作性},"include": ["src/**/*"],          	// 要编译的文件"exclude": ["node_modules"]       	// 排除的文件
}

当前工作目录有 tsconfig.json 文件后,你只需在当前工作目录运行 tsc 命令即可编译整个项目,不需要再进行逐个指定文件操作。

tsc

3.6 监视文件自动编译(可选)

可以使用 --watch 选项,让 TypeScript 在文件更改时自动重新编译。

tsc --watch

3.7 TypeScript 编译选项

TypeScript 编译器提供了很多选项,你可以在 tsconfig.json 中配置,也可以在命令行中使用。

--target:指定 ECMAScript 目标版本(如 ES5、ES6)。
--module:指定模块系统(如 `commonjs`、`esnext`)。
--outDir:指定编译输出的文件夹。
--strict:启用严格模式,包括所有类型检查规则。

4. 基本数据类型语法

TypeScript 的类型声明用于为变量、函数、类等指定数据类型,使得代码更加严谨和可读。类型声明是 TypeScript 区别于 JavaScript 的重要特性之一,它帮助开发者在编译时发现潜在的类型错误。

4.1 常用基本类型

number: 			用于数字类型(包括整数和浮点数)。
string: 			用于字符串类型。
boolean: 			用于布尔类型,truefalse。
array: 				用于数组类型,可以指定数组中元素的类型。
tuple: 				元组类型,可以指定不同索引上的元素类型。
enum: 				枚举类型,用于定义一组命名常量。
any: 				任意类型,用于绕过类型检查。
void: 				用于函数没有返回值时。
null 和 undefined: 	分别表示空值和未定义值。
never: 				表示永远不会发生的类型(如抛出异常或无限循环的函数)。

基本类型

let age: number = 30;
let username: string = "Alice";
let isActive: boolean = true;

数组类型

let numbers: number[] = [1, 2, 3, 4];
let names: string[] = ["Alice", "Bob", "Charlie"];

元组类型

let person: [string, number] = ["Alice", 30];

枚举类型

enum Direction {Up = 1,Down,Left,Right
}
let dir: Direction = Direction.Up;

any 类型

let anything: any = 42;
anything = "hello";  // 可以赋值为任何类型

void 类型

function logMessage(message: string): void {console.log(message);
}

never 类型

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

TypeScript 类型推断(Type Inference)是指在不显式声明类型的情况下,TypeScript 编译器自动推断出变量、函数等的类型。类型推断能够减少代码中的显式类型声明,使代码更加简洁,同时仍然保持强类型检查的优势。

4.2 any 数据类型语法

any 是 TypeScript 中的一个特殊数据类型,它可以表示任意类型的数据。使用 any 类型时,相当于关闭了 TypeScript 的类型检查机制,允许该变量持有任意类型的值。虽然 any 提供了极大的灵活性,但会牺牲掉 TypeScript 的类型安全优势,因此建议在必要时使用。

声明变量 any 类型

let value: any;value = 123;         // 可以是 number
value = "hello";     // 可以是 string
value = true;        // 可以是 boolean
value = {};          // 可以是 object
value = [1, 2, 3];   // 可以是 array

在这个例子中,value 变量可以存储任何类型的数据,因为它被显式地声明为 any 类型。

跳过类型检查

使用 any 类型时,TypeScript 不会对该变量进行类型检查。这使得可以绕过一些严格的类型规则。

let value: any = 5;value = "hello";  // 类型检查器不会报错
value.foo();      // 即使调用不存在的方法,也不会报错

上面的代码不会引发 TypeScript 的类型检查错误,即使 value 是一个字符串而不是对象,也不会对 foo() 方法进行类型检查。

函数参数和返回值类型: any

你可以将函数的参数或返回值声明为 any 类型,允许传入或返回任意类型的数据。

function processData(data: any): any {return data;
}let result = processData("hello");  // 返回值可以是任意类型
result = processData(123);

any 和 其他类型混合使用

在需要灵活性的情况下,可以将 any 类型与其他类型混合使用。例如,当你处理外部库的输入、解析 JSON 数据或者在逐步迁移到 TypeScript 的代码中,你可能需要使用 any

let mixed: any[] = [1, "hello", true];  // 数组可以包含任意类型的元素

any 类型安全问题

尽管 any 可以提供极大的灵活性,但过度使用它可能会导致类型错误难以捕捉。下面是一个例子,展示了如何使用 any 会导致潜在的错误。

let data: any = "hello";
console.log(data.toFixed(2));

问题:编译时不会报错,但运行时会抛出错误,因为 data 实际上是一个字符串,而不是数字。

anyunknown 区别

any 是最宽松的类型,不进行任何检查。unknown 是一种更安全的任意类型,使用 unknown 时必须进行类型检查,确保使用的值类型是正确的。

let valueAny: any = "hello";
let valueUnknown: unknown = "hello";valueAny.trim();           // 不会报错
valueUnknown.trim();       // 报错,必须先进行类型检查if (typeof valueUnknown === "string") {valueUnknown.trim();   // 类型检查后才允许操作
}

any 允许你绕过 TypeScript 的类型检查系统,但滥用它会导致类型安全性降低。为了在代码中保持类型安全,应该尽量少用 any,或者在必要的场景下使用。

any 使用场景

逐步迁移 JavaScript 代码到 TypeScript:当你将 JavaScript 代码迁移到 TypeScript,但还没有足够时间为所有内容添加类型时,可以临时使用 any

处理动态内容:例如解析 JSON 数据或使用第三方库时,输入可能是不确定的类型,这时可以使用 any 来表示动态类型。

4.3 unknown 数据类型语法

unknown 是 TypeScript 中用于表示未知类型的类型。它比 any 更安全,因为在使用 unknown 类型的值之前,必须先进行类型检查。这让 unknown 成为一种更严格的 “任意类型”。

使用 unknown 时,你不能随意对其进行操作,必须先确定它的具体类型,否则编译器会报错。这有助于在处理不确定类型时增加类型安全性。

声明 unknown 类型

let value: unknown;value = 123;       // 可以是 number
value = "hello";   // 可以是 string
value = true;      // 可以是 boolean
value = {};        // 可以是 object
value = [1, 2, 3]; // 可以是 array

unknown 类似于 any,它可以保存任何类型的值,但你不能对其进行操作,除非先进行类型检查。

unknown 类型检查

在对 unknown 类型的值进行任何操作之前,必须先进行类型检查。TypeScript 强制要求在调用方法或进行其他操作前明确类型。

let value: unknown = "hello";value.trim();  						// 错误: 类型“unknown”上不存在属性“trim”// 进行类型检查
if (typeof value === "string") {console.log(value.trim());  		// 正确:value 现在被认为是 string
}if (typeof value === "number") {console.log(value.toFixed(2));  	// 正确:value 现在被认为是 number
}

函数参数和返回值:unknown

你可以将函数的参数或返回值声明为 unknown,这样调用者必须先检查类型,才能对返回的值进行操作。

function processValue(value: unknown) {if (typeof value === "string") {return value.trim();} else if (typeof value === "number") {return value.toFixed(2);}return null;
}let result = processValue("  hello  ");  // 正确:返回 "hello"
let result2 = processValue(123);         // 正确:返回 "123.00"

unknown 类型断言

如果你确定某个 unknown 类型的值是某种类型,你可以使用类型断言来告诉 TypeScript 编译器这个值的类型。

let value: unknown = "hello";
console.log((value as string).trim());  // 使用类型断言,告诉编译器这是一个 string

类型断言不会做运行时检查,但它允许你在编译时绕过类型检查。使用时需要谨慎,确保类型断言是正确的。

unkown 与 never 的区别

unknown:表示一个未知的类型,使用前需要进行类型检查。
never:表示不可能的类型,例如永远不会返回的函数。
function throwError(message: string): never {throw new Error(message);  		// 这个函数永远不会正常结束
}	let value: unknown = "hello";
if (typeof value === "string") {console.log(value);  			// value 现在是 string
}

unknown 总结

unknown 是处理未知类型时的一种推荐选择,它在提供灵活性的同时,确保了类型安全。unknown 是一个比 any 更安全的类型,当你需要处理任意类型的值但又希望保留类型安全时,使用 unknown 是一种更好的选择。在操作 unknown 类型的值之前,必须进行类型检查,否则会引发编译错误。unknown 强制开发者在使用值时明确其类型,减少了潜在的类型错误。

4.4 never 数据类型语法

never 是 TypeScript 中的一个特殊类型,表示那些永远不会有返回值的类型。never 类型不同于 void,因为 void 表示函数可以正常返回 undefined,而 never 表示函数永远不会成功地返回。

never 数据类型 使用场景

1. 无法到达的代码:例如总是抛出错误的函数,或包含无限循环的函数。
2. 类型保护中的穷尽性检查:当你在 `switch` 或 `if` 语句中处理了所有可能的类型,`never` 可以帮助确保没有遗漏。

never 抛出异常函数

当函数抛出异常且永远不会正常返回时,返回类型为 never。在例子中,throwError 函数会抛出错误,而不会返回任何值,因此其返回类型是 never

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

never 无限循环函数

如果一个函数包含无限循环,它永远不会返回,因此返回类型也是 never。在这个例子中,infiniteLoop 函数将永远执行,不会返回任何值,因此其返回类型是 never

function infiniteLoop(): never {while (true) {// 无限循环,永远不会返回}
}

never 穷尽性检查

never 类型在类型保护和穷尽性检查中非常有用。假设我们有一个类型联合,并在 switch 语句中处理每个类型。never 可以确保所有的类型都被正确处理。

type Animal = 'cat' | 'dog';function checkAnimal(animal: Animal) {switch (animal) {case 'cat':console.log("It's a cat");break;case 'dog':console.log("It's a dog");break;default:// 如果没有处理完所有可能的情况,TS 编译器会报错const _exhaustiveCheck: never = animal;throw new Error(`Unhandled case: ${animal}`);}
}

在这个例子中,default 分支中的 animal 被赋值为 never 类型,因为理论上它应该已经处理了 Animal 类型的所有可能值。如果新增一种 Animal 类型但没有处理,TypeScript 会报错,提醒开发者更新代码。

never 区别 voidnever

void:表示函数可以返回,但返回值是 `undefined`,也就是说它是 "没有返回值" 的一种形式。
never:表示函数永远不会返回,即要么抛出异常,要么进入无限循环。
function returnVoid(): void {console.log("This function returns undefined implicitly.");
}function returnNever(): never {throw new Error("This function never returns.");
}

运行结果

returnVoid 函数可以正常执行并返回 `undefined`。
returnNever 函数永远不会执行到返回点。

never 数据类型总结

never 表示一个函数永远不会返回值,或者某些代码路径永远不会到达。它常用于抛出错误、无限循环以及类型保护中的穷尽性检查。never 提供了额外的类型安全,确保代码处理了所有可能的情况。

4.5 enum(枚举)数据类型语法

在 TypeScript 中,enum(枚举)是一种特殊的数据类型,用于定义一组命名的常量。通过使用枚举,可以为一组相关的值创建人类可读的名字,而不仅仅是使用简单的数字或字符串。枚举使代码更加可读和易于维护。

enum 枚举类型

数字枚举(Numeric Enums)
字符串枚举(String Enums)
异构枚举(Heterogeneous Enums)
常量枚举(Constant Enums)

enum 数字枚举:定义

数字枚举是最常见的枚举形式,枚举成员的值是自动递增的数字。在这个例子中,Direction.Up 的值默认为 0,接下来的 DownLeftRight 依次递增,分别为 123。如果你不提供初始值,TypeScript 会自动从 0 开始递增。

enum Direction {Up,Down,Left,Right
}let dir: Direction = Direction.Up;
console.log(dir);  // 输出 0

enum 数字枚举:手动赋值

你可以为枚举成员手动指定初始值,后续的成员依次递增。在这个例子中,Up 被显式设置为 1,而 DownLeftRight 的值依次递增为 234

enum Direction {Up = 1,Down,Left,Right
}console.log(Direction.Up);    // 输出 1
console.log(Direction.Down);  // 输出 2

enum 数字枚举:随机值

你也可以为每个成员手动指定值,而不依赖递增规则。

enum Direction {Up = 1,Down = 5,Left = 10,Right = 15
}console.log(Direction.Left);  // 输出 10

enum 字符串枚举

字符串枚举允许将每个成员定义为一个字符串字面量。这对于需要有明确文本表示的情况非常有用。在字符串枚举中,每个枚举成员都需要手动赋值为字符串,并且不再自动递增。

enum Direction {Up = "UP",Down = "DOWN",Left = "LEFT",Right = "RIGHT"
}let dir: Direction = Direction.Left;
console.log(dir);  // 输出 "LEFT"

enum 异构枚举

枚举也可以同时包含数字和字符串成员,这称为异构枚举。虽然可以定义异构枚举,但这种用法一般较少见,除非有特别的需求。

enum BooleanLikeHeterogeneousEnum {No = 0,Yes = "YES"
}console.log(BooleanLikeHeterogeneousEnum.No);   // 输出 0
console.log(BooleanLikeHeterogeneousEnum.Yes);  // 输出 "YES"

enum 反向映射

对于数字枚举,TypeScript 会为枚举成员生成双向映射(反向映射)。这意味着可以通过枚举的名称获取对应的值,也可以通过枚举的值获取对应的名称。这里,Direction[0] 返回 "Up",这是因为 TypeScript 自动创建了从数字到枚举名称的反向映射。

enum Direction {Up,Down,Left,Right
}console.log(Direction.Up);         // 输出 0
console.log(Direction[0]);         // 输出 "Up"

注意:字符串枚举没有反向映射。

enum 常量枚举

TypeScript 还提供了 const enum,用于定义常量枚举。常量枚举在编译时被内联,从而不会生成额外的 JavaScript 代码。常量枚举在编译后直接内联,生成的代码没有枚举对象,从而提高性能并减少代码量。

const enum Direction {Up,Down,Left,Right
}let dir: Direction = Direction.Up;
console.log(dir);  // 输出 0

enum 枚举类型

你可以将枚举作为类型使用,表示变量或参数只能是枚举中的值。

enum Direction {Up,Down,Left,Right
}function move(direction: Direction) {console.log("Moving", Direction[direction]);
}move(Direction.Up);   // 输出: "Moving Up"
move(5);              // 错误,5 不是 Direction 中的一个值

enum 枚举数据类型总结

enum 是 TypeScript 中用于定义一组命名常量的工具,可以是数字或字符串。数字枚举可以自动递增,字符串枚举需要显式赋值。枚举成员可以通过双向映射访问(数字枚举有反向映射,字符串枚举没有)。const enum 可以用于性能优化,在编译时直接内联枚举值。

4.6 元组(tuple)数据结构语法

在 TypeScript 中,元组(Tuple) 是一种特殊的数组类型,用于定义一组已知数量和类型的元素。与普通的数组不同,元组中的每个元素都可以有不同的类型,并且元素的数量是固定的。

元组(Tuple)定义

通过在方括号中指定类型列表来定义元组。

let myTuple: [string, number];
myTuple = ["hello", 42];  // 正确
myTuple = [42, "hello"];  // 错误:类型顺序不匹配

在这个例子中,myTuple 是一个包含两个元素的元组,第一个元素是 string 类型,第二个元素是 number 类型。

访问、操作 tuple 元组

普通数组一样访问和操作元组的元素。

let myTuple: [string, number];
myTuple = ["hello", 42];console.log(myTuple[0]); // 输出: "hello"
console.log(myTuple[1]); // 输出: 42

元组中的元素有各自的类型,可以使用这些类型进行操作。

myTuple[0] = "world"; // 正确
myTuple[1] = 99;      // 正确

tuple 可选元素

元组的某些元素可以是可选的,通过在类型后面加上 ? 表示可选元素。在这个例子中,元组的第二个元素是可选的,所以你可以只提供第一个元素。

let myTuple: [string, number?];
myTuple = ["hello"];    // 正确
myTuple = ["hello", 42]; // 正确

tuple 使用展开运算符

你可以在元组类型中使用展开运算符(...),以支持不定数量的某种类型的元素。举例这里,元组的第一个元素是字符串,接下来的元素可以是任意数量的数字。

let myTuple: [string, ...number[]];
myTuple = ["hello"];           // 正确
myTuple = ["hello", 1, 2, 3];  // 正确

tuple 元组类型使用场景

元组通常用于表示一个固定结构的数据,比如函数的返回值。

function useTuple(): [string, number] {return ["result", 200];
}const result = useTuple();
console.log(result[0]);  // 输出: "result"
console.log(result[1]);  // 输出: 200

tuple 元组类型限制

元组的长度是固定的,超出或少于指定长度都会导致编译错误。元组中的每个元素都有明确的类型和顺序。

let myTuple: [string, number];
myTuple = ["hello", 42];       // 正确
myTuple = ["hello"];           // 错误:缺少第二个元素
myTuple = ["hello", 42, 99];   // 错误:元素过多

tuple 元组类型总结

元组是一种已知长度和类型的数组,每个位置上的元素类型可以不同。元组常用于表示固定结构的数据,比如多类型的函数返回值。元组的长度和类型是严格受限的,不能随意更改。

5. 数据类型推断

TypeScript 类型推断(Type Inference)是指在不显式声明类型的情况下,TypeScript 编译器自动推断出变量、函数等的类型。类型推断能够减少代码中的显式类型声明,使代码更加简洁,同时仍然保持强类型检查的优势。

TypeScript 的类型推断机制可以自动为变量、函数、对象等推断出适当的类型,大大减少了显式类型声明的需求,同时保留了类型检查的优势。在绝大多数情况下,TypeScript 都能够根据代码的上下文推断出最合适的类型,从而使代码简洁、灵活并且安全。

5.1 变量声明类型推断

当声明变量时,如果初始化时赋值了某个值,TypeScript 会根据这个值推断出变量的类型,而不需要显式指定类型。

let age = 25;      		// 推断为 number
let name = "Alice";     // 推断为 string
let isActive = true;    // 推断为 booleanlet someVar;            // 推断为 any (如果没有赋值,推断为 `any` 类型)
someVar = 10;
someVar = "hello";

5.2 函数返回值类型推断

TypeScript 会根据函数的返回值自动推断出函数的返回类型,而不需要显式地指定返回类型。

function add(a: number, b: number) {return a + b;  // 推断为 number
}function greet() {return "Hello, World!";  // 推断为 string
}

在上面的例子中,add 函数返回 number 类型,greet 函数返回 string 类型,TypeScript 自动推断出返回值的类型,而不需要显式声明。

5.3 上下文类型推断

有时,类型是根据上下文来推断的。例如,事件处理函数、回调函数的参数类型可以由上下文自动推断出来。在这个例子中,TypeScript 根据 window.onmousedown 的上下文,推断出 event 是一个 MouseEvent 对象,自动为 event 提供了类型。

window.onmousedown = function(event) {console.log(event.button);  // `event` 自动推断为 MouseEvent 类型
};

5.4 数组类型推断

当声明数组时,TypeScript 会根据数组中的元素类型推断出整个数组的类型。

let numbers = [1, 2, 3];  					// 推断为 number[]
let names = ["Alice", "Bob", "Charlie"];  	// 推断为 string[]

如果数组包含不同类型的元素,TypeScript 会推断为联合类型。

let mixed = [1, "Alice", true];  // 推断为 (number | string | boolean)[]

5.5 对象字面量类型推断

TypeScript 可以根据对象字面量自动推断出对象的类型。

let person = {name: "Alice",age: 30
};  // 推断为 { name: string; age: number }

5.6 最佳通用类型 Best Common Type

最佳通用类型(Best Common Type)当一个数组中有多个不同类型的元素,TypeScript 会尝试推断出一个能够兼容所有元素的“最佳通用类型”。在这个例子中,TypeScript 根据数组中的元素自动推断出数组的类型为 string | number | boolean 的联合类型,因为这是最能兼容所有元素的类型。

let array = [1, 2, "hello", true];  // 推断为 (string | number | boolean)[]

5.7 返回值类型推断

函数的参数和返回值类型可以基于上下文进行推断。例如,回调函数的参数类型可以根据函数调用的上下文进行推断。

let numbers = [1, 2, 3];numbers.forEach((num) => {console.log(num);  // `num` 自动推断为 number
});

5.8 类型声明推断

在某些情况下,你可以同时使用类型推断和显式类型声明。例如,你可以为函数参数声明类型,而让 TypeScript 自动推断返回值类型。

function multiply(a: number, b: number) {return a * b;  // TypeScript 自动推断返回值为 number
}

5.9 类型兼容性推断

在推断过程中,TypeScript 会根据赋值的上下文检查类型的兼容性。如果推断出的类型与上下文不兼容,TypeScript 会报错。

let num = 10;  // 推断为 number
num = "hello"; // 报错:不能将类型 "string" 分配给类型 "number"

5.10 泛型类型推断

TypeScript 也可以在使用泛型时自动推断出类型。例如,当你调用一个泛型函数时,TypeScript 会根据传递的参数自动推断出泛型的类型。

function identity<T>(arg: T): T {return arg;
}let output1 = identity(10);   		// TypeScript 推断 T 为 number
let output2 = identity("hello");  	// TypeScript 推断 T 为 string

6. TypeScript 面向对象(更新中)

更新中···

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解锁亚马逊测评自养号防关联新技术

解锁亚马逊测评自养号防关联的新技术主要包括以下几个方面&#xff0c;这些技术旨在提高测评过程的安全性&#xff0c;降低账号被关联的风险&#xff1a; 1. 独立纯净IP技术 独立纯净IP&#xff1a;采用独立、纯净且未受污染的国外IP地址&#xff0c;确保这些IP未被标记或列入…

240922-MacOS终端访问硬盘

A. 最终效果 B. 操作步骤 在macOS中&#xff0c;可以通过命令行使用Terminal访问硬盘的不同位置。你可以按照以下步骤操作&#xff1a; 打开终端&#xff08;Terminal&#xff09;&#xff1a; 在应用程序中打开终端&#xff0c;或者使用 Spotlight 搜索“Terminal”来启动。 …

初学者的鸿蒙多线程并发之 TaskPool 踩坑之旅

1. 背景 目标群体&#xff1a;鸿蒙初学者 版本&#xff1a;HarmonyOS 3.1/4.0 背景&#xff1a;鸿蒙 App 的全局路由管理功能&#xff0c;需要在 App 启动时初始化对 raw 下的相关配置文件进行读取、解析并缓存。App 启动时涉及到了大量模块的初始化&#xff0c;好多模块都涉…

巨潮股票爬虫逆向

目标网站 aHR0cDovL3dlYmFwaS5jbmluZm8uY29tLmNuLyMvSVBPTGlzdD9tYXJrZXQ9c3o 一、抓包分析 请求头参数加密 二、逆向分析 下xhr断点 参数生成位置 发现是AES加密&#xff0c;不过是混淆的&#xff0c;但并不影响咱们扣代码 文章仅提供技术交流学习&#xff0c;不可对目标服…

Vue3+Element Plus:使用el-dialog,对话框可拖动,且对话框弹出时仍然能够在背景页(对话框外部的页面部分)上进行滚动以及输入框输入信息

【需求】 使用Element Plus中的el-dialog默认是模态的&#xff08;即它会阻止用户与对话框外部的元素进行交互&#xff09;&#xff0c;对话框弹出时仍然能够在背景页&#xff08;对话框外部的页面部分&#xff09;上进行滚动以及输入框输入信息&#xff0c;且对话框可拖动 【…

react hooks--React.memo

基本语法 React.memo 高阶组件的使用场景说明&#xff1a; React 组件更新机制&#xff1a;只要父组件状态更新&#xff0c;子组件就会无条件的一起更新。 子组件 props 变化时更新过程&#xff1a;组件代码执行 -> JSX Diff&#xff08;配合虚拟 DOM&#xff09;-> 渲…

STM32精确控制步进电机

目的&#xff1a;学习使用STM32电机驱动器步进电机&#xff0c;进行电机运动精确控制。 测试环境&#xff1a; MCU主控芯片STM32F103RCT6 &#xff1b;A4988步进电机驱动器模块&#xff1b;微型2相4线步进电机10mm丝杆滑台&#xff0c;金属丝杆安装有滑块。 10mm二相四线微型…

NtripShare测量机器人自动化监测系统测站更换仪器后重新设站

NtripShare测量机器人自动化监测系统投入商业运营已经很久了&#xff0c;在MosBox与自动优化网平差技术的加持下&#xff0c;精度并不让人担心&#xff0c;最近基于客户需求处理了两个比较大的问题。 1、增加对反射片和免棱镜的支持。 2、进一步优化测站更换仪器或重新整平后重…

Qemu开发ARM篇-5、buildroot制作根文件系统并在qemu中进行挂载启动

文章目录 1、 buildroot源码获取2、buildroot配置3、buildroot编译4、挂载根文件系统 在上一篇 Qemu开发ARM篇-4、kernel交叉编译运行演示中&#xff0c;我们编译了kernel&#xff0c;并在qemu上进行了运行&#xff0c;但到最后&#xff0c;在挂载根文件系统时候&#xff0c;挂…

[数据集][目标检测]文本表格检测数据集VOC+YOLO格式6688张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6688 标注数量(xml文件个数)&#xff1a;6688 标注数量(txt文件个数)&#xff1a;6688 标注…

Fyne ( go跨平台GUI )中文文档-绘图和动画(三)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

Easy Excel从入门到精通!!!

目录 1.文件导入 1.1基本方式读取excel文件内容 1.2注解模型映射器读取excel 1.3多行表头读取 1.4文件上传读取 2.文件导出 2.1基本方式导出 2.2模型映射导出 2.3设置行高、列宽等内容 2.4合并单元格 2.5导出设置超链接、批注、公式 2.6模板填充对象导出 2.7模板填…

Mybatis 返回 Map 对象

一、场景介绍 假设有如下一张学生表&#xff1a; CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,name varchar(100) NOT NULL COMMENT 姓名,gender varchar(10) NOT NULL COMMENT 性别,grade int NOT NULL COMMENT 年级,PRIMARY KEY (id) ) ENGINEInnoD…

【C++篇】引领C++模板初体验:泛型编程的力量与妙用

文章目录 C模板编程前言第一章: 初始模板与函数模版1.1 什么是泛型编程&#xff1f;1.1.1 为什么要有泛型编程&#xff1f;1.1.1 泛型编程的优势 1.2 函数模板的基础1.2.1 什么是函数模板&#xff1f;1.2.2 函数模板的定义格式1.2.3 示例&#xff1a;通用的交换函数输出示例&am…

华为HarmonyOS地图服务 11 - 如何在地图上增加点注释?

场景介绍 本章节将向您介绍如何在地图的指定位置添加点注释以标识位置、商家、建筑等&#xff0c;并可以通过信息窗口展示详细信息。 点注释支持功能&#xff1a; 支持设置图标、文字、碰撞规则等。支持添加点击事件。 PointAnnotation有默认风格&#xff0c;同时也支持自定…

文献阅读(220)MRCN

题目&#xff1a;MRCN: Throughput-Oriented Multicast Routing for Customized Network-on-Chips时间&#xff1a;2023期刊&#xff1a;TPDS研究机构&#xff1a;韩国成均馆大学 这篇论文探讨的问题是多播死锁问题&#xff0c;下图中Packet A分成两条路径&#xff0c;但在rou…

Leetcode—1014. 最佳观光组合【中等】

2024每日刷题&#xff08;164&#xff09; Leetcode—1014. 最佳观光组合 实现代码 class Solution { public:int maxScoreSightseeingPair(vector<int>& values) {int mxPre values[0] 0;int ans 0;for(int i 1; i < values.size(); i) {ans max(ans, mxP…

python绘制弦图-科研作图

一、背景 弦图以其直观、精美的展示方式受到越来越多人的关注&#xff0c;它不仅能够有效展示两个变量之间的联系&#xff0c;还能同时展现多个变量间的复杂互动&#xff0c;本文将通过Python语言中的pycirclize库&#xff0c;带你深入了解如何绘制弦图。 弦图是一种圆…

51单片机——矩阵键盘

一、矩阵键盘原理图 我们发现: P17,P16,P15,P14控制行&#xff0c; P13,P12,P11,P10控制列。 所以我们如果要选择第四列&#xff0c;只需要把整个P1先给高电位1&#xff0c;再把P10给低电位0。 二、代码 P10xFF; P100; if(P170){Delay(20);while(P170);Delay(20);KeyNum…

计算机毕业设计python+spark知识图谱房价预测系统 房源推荐系统 房源数据分析 房源可视化 房源大数据大屏 大数据毕业设计 机器学习

《PythonSpark知识图谱房价预测系统》开题报告 一、研究背景与意义 随着城市化进程的加速和房地产市场的不断发展&#xff0c;房价成为影响人们生活质量的重要因素之一。准确预测房价不仅有助于政府制定科学的房地产政策&#xff0c;还能为开发商提供市场参考&#xff0c;同时…