引言
大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的各种数据类型,帮助读者深入理解每种数据类型的用法、内置属性和方法,以及在实际开发中的应用。💕💕😊
介绍
在 TypeScript 中,数据类型是构建可靠且可维护代码的基础。通过显式地声明变量的类型,开发者可以在编译时捕获潜在的错误,避免在运行时出现意外的类型错误。TypeScript 提供了丰富的内置数据类型,如 Number
、String
、Array
、Tuple
、Map
等,以及高级类型如 Union Types
,这些类型帮助开发者更好地组织和处理数据。
下面作者将逐一进行介绍!
一、基础数据类型
1. Number 类型
① 基本用法
在 TypeScript 中,Number
类型用于表示数值数据,包括整数和浮点数。Number
类型是 JavaScript 中 Number
对象的静态类型表示。以下是 Number
类型的基本用法:
- 整数和浮点数的声明:
let num1: number = 123; // 整数
let num2: number = 0.456; // 浮点数
- 特殊值:
let notANumber: number = NaN;
let infinity: number = Infinity;
let negativeInfinity: number = -Infinity;
- `NaN`(Not-a-Number):表示一个非数字值。
- `Infinity` 和 `-Infinity`:分别表示正无穷大和负无穷大。
- 不同进制表示法:
let binary: number = 0b1010; // 二进制
let octal: number = 0o744; // 八进制
let decimal: number = 6; // 十进制
let hex: number = 0xf00d; // 十六进制
- 二进制:以
0b
或0B
开头。 - 八进制:以
0o
或0O
开头。 - 十进制:直接表示。
- 十六进制:以
0x
或0X
开头。
② 内置属性
Number
类型在 TypeScript 中有一些内置属性,这些属性提供了关于数值范围和特殊值的信息。以下是一些常用的内置属性:
属性名 | 描述 |
---|---|
Number.MAX_VALUE | 表示 JavaScript 中最大的正数,约为 1.8e+308。 |
Number.MIN_VALUE | 表示 JavaScript 中最小的正数(即最接近 0 的正数),约为 5e-324。 |
Number.NaN | 表示 “Not-a-Number” 值。 |
Number.POSITIVE_INFINITY | 表示正无穷大。 |
Number.NEGATIVE_INFINITY | 表示负无穷大。 |
Number.EPSILON | 表示 1 和比 1 大的最小浮点数之间的差。 |
Number.MAX_SAFE_INTEGER | 表示在 JavaScript 中可以精确表示的最大整数,即 2^53 - 1。 |
Number.MIN_SAFE_INTEGER | 表示在 JavaScript 中可以精确表示的最小整数,即 -(2^53 - 1)。 |
③ 内置方法
Number
类型在 TypeScript 中有一些内置方法,这些方法提供了对数值进行操作和检查的功能。以下是一些常用的内置方法:
方法名 | 描述 |
---|---|
Number.isFinite() | 检查传入的参数是否是有限的数字。如果参数是有限的数字,则返回 true ,否则返回 false 。 |
Number.isInteger() | 检查传入的参数是否是整数。如果参数是整数,则返回 true ,否则返回 false 。 |
Number.isNaN() | 检查传入的参数是否是 NaN 。如果参数是 NaN ,则返回 true ,否则返回 false 。 |
Number.isSafeInteger() | 检查传入的参数是否是安全整数。如果参数是安全整数,则返回 true ,否则返回 false 。 |
Number.parseFloat() | 将字符串解析为浮点数。 |
Number.parseInt() | 将字符串解析整数。 |
Number.prototype.toFixed() | 将数字格式化为字符串,并保留到小数点后指定位数。 |
Number.prototype.toExponential() | 将数字转换为指数表示法。 |
Number.prototype.toPrecision() | 将数字格式化为字符串,并按指定的精度。 |
Number.prototype.toString() | 将数字转换为字符串。可以指定基数。 |
代码示例:
// Number.isFinite()
let finiteNumber = Number.isFinite(1000); // true
let infiniteNumber = Number.isFinite(Infinity); // false
console.log(finiteNumber, infiniteNumber);
// Number.isInteger()
let integerNumber = Number.isInteger(1000); // true
let floatNumber = Number.isInteger(1000.5); // false
console.log(integerNumber, floatNumber);
// Number.isNaN()
let notANumber = Number.isNaN(NaN); // true
let isANumber = Number.isNaN(1000); // false
console.log(notANumber, isANumber);
// Number.isSafeInteger()
let safeInteger = Number.isSafeInteger(Math.pow(2, 53) - 1); // true
let unsafeInteger = Number.isSafeInteger(Math.pow(2, 53)); // false
console.log(safeInteger, unsafeInteger);
// Number.parseFloat()
let floatFromString = Number.parseFloat("1000.5"); // 1000.5
console.log(floatFromString);
// Number.parseInt()
let integerFromString = Number.parseInt("1000", 10); // 1000
console.log(integerFromString);
// Number.prototype.toFixed()
let num1: number = 123.456;
console.log(num1.toFixed(2)); // "123.46"
// Number.prototype.toExponential()
let num2: number = 123456;
console.log(num2.toExponential(2)); // "1.23e+5"
// Number.prototype.toPrecision()
let num3: number = 123.456;
console.log(num3.toPrecision(2)); // "1.2e+2"
// Number.prototype.toString()
let num4: number = 123;
console.log(num4.toString(10)); // "123"
④ 注意事项
- IEEE 754 双精度浮点数标准的影响:
TypeScript 中的Number
类型是基于 IEEE 754 双精度浮点数标准实现的。这意味着它不能精确表示所有的实数,特别是对于非常大或非常小的数,或者需要高精度的计算(如金融计算)时,可能会出现精度问题。例如:
let a: number = 0.1;
let b: number = 0.2;
let sum: number = a + b;
console.log(sum); // 0.30000000000000004
在这个例子中,0.1 + 0.2
的结果并不是精确的 0.3
,而是 0.30000000000000004
。这是由于浮点数在计算机中的表示方式导致的精度损失。
法。
2. String 类型
① 基本用法
在 TypeScript 中,String
类型用于表示文本数据。字符串可以使用单引号('
)、双引号("
)或反引号(```)来创建。反引号用于创建模板字符串,模板字符串可以跨越多行并嵌入表达式。以下是 String
类型的基本用法:
- 单引号、双引号、反引号的使用:
let str1: string = 'Hello, world'; // 使用单引号
let str2: string = "Hello, world"; // 使用双引号
let str3: string = `Hello,
world`; // 使用反引号创建多行字符串
- 模板字符串和嵌入表达式:
模板字符串允许在字符串中嵌入表达式,表达式使用${}
语法。
let name: string = 'world';
let str4: string = `Hello, ${name}`; // 嵌入表达式
console.log(str4); // 输出 "Hello, world"
② 内置属性
String
类型在 TypeScript 中有一个内置属性 length
,用于返回字符串的长度。
属性名 | 描述 |
---|---|
length | 返回字符串的长度。 |
代码示例:
let str: string = "Hello, TypeScript!";
console.log(str.length); // 输出 18
③ 内置方法
String
类型在 TypeScript 中有许多内置方法,这些方法提供了对字符串进行操作和检查的功能。以下是一些常用的内置方法:
方法名 | 描述 |
---|---|
charAt(index) | 返回字符串中指定索引位置的字符。 |
charCodeAt(index) | 返回字符串中指定索引位置的字符的 Unicode 编码。 |
concat(...strings) | 连接两个或多个字符串,并返回一个新字符串。 |
indexOf(searchValue, fromIndex?) | 返回字符串中第一次出现指定值的索引,如果没有找到则返回 -1。 |
slice(start?, end?) | 提取字符串的一个片段,并返回一个新字符串。 |
substring(start, end?) | 提取字符串的一个子串,并返回一个新字符串。 |
toUpperCase() | 将字符串转换为大写。 |
toLowerCase() | 将字符串转换为小写。 |
代码示例:
// charAt()
let str: string = "Hello, TypeScript!";
console.log(str.charAt(0)); // 输出 'H'
// charCodeAt()
console.log(str.charCodeAt(0)); // 输出 72
// concat()
let str1: string = "Hello, ";
let str2: string = "TypeScript!";
console.log(str1.concat(str2)); // 输出 'Hello, TypeScript!'
// indexOf()
console.log(str.indexOf("Type")); // 输出 7
// slice()
console.log(str.slice(0, 5)); // 输出 'Hello'
// substring()
console.log(str.substring(0, 5)); // 输出 'Hello'
// toUpperCase()
console.log(str.toUpperCase()); // 输出 'HELLO, TYPESCRIPT!'
// toLowerCase()
console.log(str.toLowerCase()); // 输出 'hello, typescript!'
④ 注意事项
- 字符串的不可变性:
在 TypeScript 中,字符串是不可变的(immutable),这意味着一旦字符串被创建,它的值就不能被改变。任何对字符串的操作都会返回一个新的字符串,而不会修改原始字符串。例如:
let str: string = "Hello";
str.toUpperCase(); // 返回一个新的字符串 "HELLO",但不会修改 str
console.log(str); // 输出 "Hello"
在这个例子中,toUpperCase()
方法返回了一个新的字符串 "HELLO"
,但原始字符串 str
的值仍然是 "Hello"
。
3. Array 类型
① 基本用法
在 TypeScript 中,Array
类型用于表示一系列相同类型元素的数据结构。数组可以存储多个值,并且可以通过索引访问这些值。以下是 Array
类型的基本用法:
- 数组的声明和初始化:
数组可以通过多种方式声明和初始化。最常见的方式是使用数组字面量和数组构造函数。
// 使用数组字面量
let arr1: number[] = [1, 2, 3, 4, 5];
// 使用数组构造函数
let arr2: Array<number> = new Array(1, 2, 3, 4, 5);
② 内置属性
Array
类型在 TypeScript 中有一个内置属性 length
,用于返回数组的长度。
属性名 | 描述 |
---|---|
length | 返回数组的长度。 |
代码示例:
let arr: number[] = [1, 2, 3, 4, 5];
console.log(arr.length); // 输出 5
③ 内置方法
Array
类型在 TypeScript 中有许多内置方法,这些方法提供了对数组进行操作和检查的功能。以下是一些常用的内置方法:
方法名 | 描述 |
---|---|
push(...items) | 将一个或多个元素添加到数组的末尾,并返回数组新的长度。 |
pop() | 移除数组的最后一个元素并返回该元素。 |
shift() | 移除数组的第一个元素并返回该元素。 |
unshift(...items) | 将一个或多个元素添加到数组的开头,并返回数组新的长度。 |
indexOf(searchElement, fromIndex?) | 返回数组中第一次出现指定元素的索引,如果没有找到则返回 -1。 |
splice(start, deleteCount?, ...items) | 从数组中移除元素,并在指定位置添加新的元素。 |
slice(start?, end?) | 提取数组的一个片段,并返回一个新数组。 |
forEach(callbackfn) | 对数组的每个元素执行一次提供的函数。 |
map(callbackfn) | 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后的返回值。 |
filter(callbackfn) | 创建一个新数组,其包含通过所提供函数实现的测试的所有元素。 |
reduce(callbackfn, initialValue?) | 对数组中的每个元素执行一个 reducer 函数,将其结果汇总为单个返回值。 |
reduceRight(callbackfn, initialValue?) | 从右到左对数组中的每个元素执行一个 reducer 函数,将其结果汇总为单个返回值。 |
find(callbackfn) | 返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined 。 |
findIndex(callbackfn) | 返回数组中满足提供的测试函数的第一个元素的索引,否则返回 -1。 |
some(callbackfn) | 测试数组中是否至少有一个元素通过由提供的函数实现的测试。 |
every(callbackfn) | 测试数组中的所有元素是否都通过了由提供的函数实现的测试。 |
join(separator?) | 将数组的所有元素连接成一个字符串,可指定分隔符。 |
reverse() | 反转数组中元素的顺序。 |
sort(compareFunction?) | 对数组的元素进行排序,并返回排序后的数组。 |
concat(...arrays) | 合并两个或多个数组,并返回一个新数组。 |
fill(value, start?, end?) | 用一个固定值填充数组中从起始索引到终止索引的全部元素。 |
copyWithin(target, start?, end?) | 将数组的一部分浅复制到同一数组中的另一个位置,并返回它,不会改变数组的长度。 |
entries() | 返回一个新的数组迭代器对象,该对象包含数组中每个索引的键/值对。 |
keys() | 返回一个新的数组迭代器对象,该对象包含数组中每个索引的键。 |
values() | 返回一个新的数组迭代器对象,该对象包含数组中每个索引的值。 |
代码示例:
// push()
let arr: number[] = [1, 2, 3];
arr.push(4, 5);
console.log(arr); // 输出 [1, 2, 3, 4, 5]
// pop()
let lastElement = arr.pop();
console.log(lastElement); // 输出 5
console.log(arr); // 输出 [1, 2, 3, 4]
// shift()
let firstElement = arr.shift();
console.log(firstElement); // 输出 1
console.log(arr); // 输出 [2, 3, 4]
// unshift()
arr.unshift(1, 2);
console.log(arr); // 输出 [1, 2, 2, 3, 4]
// indexOf()
console.log(arr.indexOf(3)); // 输出 3
// splice()
arr.splice(2, 1, 6); // 从索引 2 开始移除一个元素,然后添加元素 6
console.log(arr); // 输出 [1, 2, 6, 3, 4]
// slice()
let slicedArr = arr.slice(1, 4);
console.log(slicedArr); // 输出 [2, 6, 3]
// forEach()
arr.forEach((value, index) => {
console.log(`Index: ${index}, Value: ${value}`);
});
// 输出:
// Index: 0, Value: 1
// Index: 1, Value: 2
// Index: 2, Value: 6
// Index: 3, Value: 3
// Index: 4, Value: 4
// map()
let doubledArr = arr.map(value => value * 2);
console.log(doubledArr); // 输出 [2, 4, 12, 6, 8]
// filter()
let filteredArr = arr.filter(value => value > 3);
console.log(filteredArr); // 输出 [6, 4]
// reduce()
let sum = arr.reduce((acc, value) => acc + value, 0);
console.log(sum); // 输出 16
// reduceRight()
let sumRight = arr.reduceRight((acc, value) => acc + value, 0);
console.log(sumRight); // 输出 16
// find()
let foundElement = arr.find(value => value > 3);
console.log(foundElement); // 输出 6
// findIndex()
let foundIndex = arr.findIndex(value => value > 3);
console.log(foundIndex); // 输出 2
// some()
let hasGreaterThan3 = arr.some(value => value > 3);
console.log(hasGreaterThan3); // 输出 true
// every()
let allGreaterThan0 = arr.every(value => value > 0);
console.log(allGreaterThan0); // 输出 true
// join()
let joinedStr = arr.join("-");
console.log(joinedStr); // 输出 "1-2-6-3-4"
// reverse()
arr.reverse();
console.log(arr); // 输出 [4, 3, 6, 2, 1]
// sort()
arr.sort((a, b) => a - b);
console.log(arr); // 输出 [1, 2, 3, 4, 6]
// concat()
let newArr = arr.concat([7, 8, 9]);
console.log(newArr); // 输出 [1, 2, 3, 4, 6, 7, 8, 9]
// fill()
arr.fill(0, 2, 4);
console.log(arr); // 输出 [1, 2, 0, 0, 6]
// copyWithin()
arr.copyWithin(0, 3, 5);
console.log(arr); // 输出 [0, 6, 0, 0, 6]
// entries()
let entries = arr.entries();
for (let entry of entries) {
console.log(entry);
}
// 输出:
// [0, 0]
// [1, 6]
// [2, 0]
// [3, 0]
// [4, 6]
// keys()
let keys = arr.keys();
for (let key of keys) {
console.log(key);
}
// 输出:
// 0
// 1
// 2
// 3
// 4
// values()
let values = arr.values();
for (let value of values) {
console.log(value);
}
// 输出:
// 0
// 6
// 0
// 0
// 6
④ 注意事项
④ 注意事项
- 数组的动态性:
在 TypeScript 中,数组是动态的,这意味着数组的长度可以动态改变。你可以随时向数组中添加或删除元素。例如:
let arr: number[] = [1, 2, 3];
arr.push(4); // 添加元素
console.log(arr); // 输出 [1, 2, 3, 4]
arr.pop(); // 删除元素
console.log(arr); // 输出 [1, 2, 3]
在这个例子中,数组的长度随着元素的添加和删除而动态变化。数组的动态性在许多应用中非常有用,例如在实现一个 TodoList
时,你可以动态地添加和删除待办事项:
let todoList: string[] = ["Buy groceries", "Clean the house"];
// 添加新的待办事项
todoList.push("Walk the dog");
console.log(todoList); // 输出 ["Buy groceries", "Clean the house", "Walk the dog"]
// 完成一个待办事项,将其从列表中移除
todoList.splice(1, 1); // 移除 "Clean the house"
console.log(todoList); // 输出 ["Buy groceries", "Walk the dog"]
在这个例子中,todoList
数组的长度随着待办事项的添加和完成而动态变化。这种动态性使得数组非常适合用于需要频繁更新和修改数据的应用场景。
二、高级数据类型
1. Map 对象
① 基本用法
在 TypeScript 中,Map
是一种键-值对的集合,其中键和值可以是任意类型。Map
对象允许你存储和检索数据,并且提供了一些内置方法来操作这些数据。以下是 Map
对象的基本用法:
- 创建和初始化 Map:
Map
对象可以通过new Map()
构造函数创建,并且可以通过传递一个包含键值对的数组来初始化。
// 创建一个空的 Map
let myMap = new Map<string, number>();
// 使用数组初始化 Map
let initialMap = new Map<string, number>([
["one", 1],
["two", 2]
]);
② 内置方法
Map
对象在 TypeScript 中有许多内置方法,这些方法提供了对键值对进行操作和检查的功能。以下是一些常用的内置方法:
方法名 | 描述 |
---|---|
set(key, value) | 向 Map 中添加一个新的键值对。如果键已经存在,则更新其值。 |
get(key) | 根据键获取对应的值,如果键不存在则返回 undefined 。 |
has(key) | 检查 Map 中是否包含指定的键。如果键存在,则返回 true ,否则返回 false 。 |
delete(key) | 从 Map 中移除指定键的键值对,如果键存在则返回 true ,否则返回 false 。 |
clear() | 移除 Map 中的所有键值对。 |
forEach(callbackfn) | 对 Map 中的每个键值对执行一次提供的函数。 |
keys() | 返回一个包含 Map 中所有键的迭代器。 |
values() | 返回一个包含 Map 中所有值的迭代器。 |
entries() | 返回一个包含 Map 中所有键值对的迭代器。 |
代码示例:
// 创建一个空的 Map
let myMap = new Map<string, number>();
// set()
myMap.set("one", 1);
myMap.set("two", 2);
console.log(myMap); // 输出 Map { 'one' => 1, 'two' => 2 }
// get()
console.log(myMap.get("one")); // 输出 1
console.log(myMap.get("three")); // 输出 undefined
// has()
console.log(myMap.has("one")); // 输出 true
console.log(myMap.has("three")); // 输出 false
// delete()
console.log(myMap.delete("one")); // 输出 true
console.log(myMap.delete("three")); // 输出 false
console.log(myMap); // 输出 Map { 'two' => 2 }
// clear()
myMap.clear();
console.log(myMap); // 输出 Map {}
// 重新初始化 Map
myMap.set("one", 1);
myMap.set("two", 2);
// forEach()
myMap.forEach((value, key) => {
console.log(`Key: ${key}, Value: ${value}`);
});
// 输出:
// Key: one, Value: 1
// Key: two, Value: 2
// keys()
let keys = myMap.keys();
for (let key of keys) {
console.log(key);
}
// 输出:
// one
// two
// values()
let values = myMap.values();
for (let value of values) {
console.log(value);
}
// 输出:
// 1
// 2
// entries()
let entries = myMap.entries();
for (let entry of entries) {
console.log(`Key: ${entry[0]}, Value: ${entry[1]}`);
}
// 输出:
// Key: one, Value: 1
// Key: two, Value: 2
③ 注意事项
- Map 与对象的区别:
Map
对象与普通 JavaScript 对象(Object)有一些重要的区别:
代码示例:
// Map 的键可以是任意类型
let map = new Map<any, any>();
map.set({}, "object key");
map.set(() => {}, "function key");
map.set(123, "number key");
console.log(map.get({})); // 输出 undefined,因为 {} 是新的对象
console.log(map.get(123)); // 输出 "number key"
// 对象的键只能是字符串或 Symbol
let obj: any = {};
obj[123] = "number key";
console.log(obj["123"]); // 输出 "number key",因为数字键被转换为字符串
// Map 保留插入顺序
let map2 = new Map<string, number>();
map2.set("one", 1);
map2.set("two", 2);
map2.set("three", 3);
map2.forEach((value, key) => {
console.log(`Key: ${key}, Value: ${value}`);
});
// 输出:
// Key: one, Value: 1
// Key: two, Value: 2
// Key: three, Value: 3
// 对象的键值对顺序不保证
let obj2: any = {
one: 1,
two: 2,
three: 3
};
Object.keys(obj2).forEach(key => {
console.log(`Key: ${key}, Value: ${obj2[key]}`);
});
// 输出顺序可能不同,取决于 JavaScript 引擎
- 键的类型:
*Map
的键可以是任意类型,包括对象、函数、基本类型等。
* 对象的键只能是字符串或 Symbol 类型。 - 顺序:
*Map
会保留键值对的插入顺序。
* 对象的键值对顺序在不同 JavaScript 引擎中可能不同,且不保证顺序。 - 性能:
*Map
在频繁的插入和删除操作中性能更好。
* 对象在某些情况下可能更适合简单的键值存储。 - 迭代:
*Map
提供了内置的迭代方法,如keys()
、values()
和entries()
。
* 对象需要使用Object.keys()
、Object.values()
和Object.entries()
进行迭代。
④ 应用场景
Map
对象在许多实际应用场景中非常有用,特别是在需要高效地存储和检索键值对数据时。以下是一些常见的应用场景:
- 缓存管理:
在需要缓存数据的应用中,Map
可以用来存储缓存数据,并根据键快速检索数据。
let cache = new Map<string, any>();
function getData(key: string): any {
if (cache.has(key)) {
console.log("Cache hit");
return cache.get(key);
} else {
console.log("Cache miss");
let data = fetchDataFromServer(key); // 模拟从服务器获取数据
cache.set(key, data);
return data;
}
}
function fetchDataFromServer(key: string): any {
// 模拟从服务器获取数据
return `Data for ${key}`;
}
console.log(getData("user1")); // 输出 "Cache miss" 和 "Data for user1"
console.log(getData("user1")); // 输出 "Cache hit" 和 "Data for user1"
- 配置管理:
在需要管理配置项的应用中,Map
可以用来存储配置项,并根据键快速检索配置值。
let config = new Map<string, string>();
config.set("apiUrl", "https://api.example.com");
config.set("timeout", "5000");
function getConfig(key: string): string | undefined {
return config.get(key);
}
console.log(getConfig("apiUrl")); // 输出 "https://api.example.com"
console.log(getConfig("timeout")); // 输出 "5000"
- 事件管理:
在需要管理事件监听器的应用中,Map
可以用来存储事件名称和对应的处理函数。
let eventListeners = new Map<string, Function[]>();
function on(eventName: string, handler: Function): void {
if (!eventListeners.has(eventName)) {
eventListeners.set(eventName, []);
}
eventListeners.get(eventName)!.push(handler);
}
function emit(eventName: string, ...args: any[]): void {
if (eventListeners.has(eventName)) {
eventListeners.get(eventName)!.forEach(handler => handler(...args));
}
}
on("click", () => console.log("Button clicked"));
on("click", () => console.log("Button clicked again"));
emit("click"); // 输出 "Button clicked" 和 "Button clicked again"
- 数据映射:
在需要将一种数据类型映射到另一种数据类型的应用中,Map
可以用来存储映射关系。
let userRoles = new Map<string, string>();
userRoles.set("user1", "admin");
userRoles.set("user2", "editor");
function getUserRole(userId: string): string | undefined {
return userRoles.get(userId);
}
console.log(getUserRole("user1")); // 输出 "admin"
console.log(getUserRole("user2")); // 输出 "editor"
通过以上详细的介绍和代码示例,读者可以更好地理解和掌握 TypeScript 中的 Map
对象及其相关属性和方法,并了解其在实际应用中的使用场景。
2. 元组(Tuple)
① 基本用法
在 TypeScript 中,元组(Tuple)是一种固定长度且每个元素类型可以不同的数组。元组允许你存储多个不同类型的值,并且每个位置的类型是固定的。以下是元组的基本用法:
- 元组的声明和初始化:
元组可以通过数组字面量来声明和初始化。元组的类型注解使用方括号[]
,并在其中指定每个元素的类型。
// 声明一个包含字符串、数字和布尔值的元组
let tuple: [string, number, boolean] = ["Hello", 42, true];
// 访问元组中的元素
console.log(tuple[0]); // 输出 "Hello"
console.log(tuple[1]); // 输出 42
console.log(tuple[2]); // 输出 true
② 内置属性
Tuple
类型在 TypeScript 中有一个内置属性 length
,用于返回元组的长度。
属性名 | 描述 |
---|---|
length | 返回元组的长度。 |
代码示例:
let tuple: [string, number, boolean] = ["Hello", 42, true];
console.log(tuple.length); // 输出 3
③ 内置方法
Tuple
类型在 TypeScript 中有一些内置方法,这些方法提供了对元组进行操作和检查的功能。以下是一些常用的内置方法:
方法名 | 描述 |
---|---|
concat(...items: ConcatArray[]): T[] | 连接两个或多个数组或值,并返回一个新数组。 |
join(separator?: string): string | 将元组的所有元素连接成一个字符串,可指定分隔符。 |
slice(start?: number, end?: number): T[] | 提取元组的一个片段,并返回一个新数组。 |
toString(): string | 将元组转换为字符串。 |
indexOf(searchElement: T, fromIndex?: number): number | 返回元组中第一次出现指定元素的索引,如果没有找到则返回 -1。 |
push(...items: T[]): number | 向元组末尾添加一个或多个元素,并返回新的长度。 |
`pop(): T | undefined` |
代码示例:
// 声明一个元组
let tuple: [string, number, boolean] = ["Hello", 42, true];
// concat()
let newTuple = tuple.concat(["world", 123]);
console.log(newTuple); // 输出 ["Hello", 42, true, "world", 123]
// join()
let joinedStr = tuple.join("-");
console.log(joinedStr); // 输出 "Hello-42-true"
// slice()
let slicedTuple = tuple.slice(1, 2);
console.log(slicedTuple); // 输出 [42]
// toString()
let tupleStr = tuple.toString();
console.log(tupleStr); // 输出 "Hello,42,true"
// indexOf()
console.log(tuple.indexOf(42)); // 输出 1
// push()
tuple.push("world");
console.log(tuple); // 输出 ["Hello", 42, true, "world"]
// pop()
let lastElement = tuple.pop();
console.log(lastElement); // 输出 "world"
console.log(tuple); // 输出 ["Hello", 42, true]
④ 注意事项
- 元组的固定长度特性:
元组的一个重要特性是它的长度是固定的,一旦声明,元组的长度就不能改变。这意味着你不能随意添加或删除元组中的元素。例如:
let tuple: [string, number, boolean] = ["Hello", 42, true];
// 尝试添加元素会导致错误
// tuple.push("world"); // 错误:类型 '[string, number, boolean]' 上不存在属性 'push'
// 尝试删除元素会导致错误
// tuple.pop(); // 错误:类型 '[string, number, boolean]' 上不存在属性 'pop'
元组的固定长度特性使得它在需要固定结构的数据场景中非常有用,例如函数返回多个值时:
function getUserInfo(): [string, number, boolean] {
return ["Alice", 30, true];
}
let userInfo = getUserInfo();
console.log(userInfo[0]); // 输出 "Alice"
console.log(userInfo[1]); // 输出 30
console.log(userInfo[2]); // 输出 true
3. 联合类型(Union Types)
① 基本用法
在 TypeScript 中,联合类型(Union Types)是指一个变量可以具有多种不同的类型。联合类型使用竖线 |
来分隔不同的类型。以下是联合类型的基本用法:
- 联合类型的声明:
联合类型可以通过在类型注解中使用竖线|
来声明。例如,一个变量可以是字符串或数字类型:
let value: string | number;
value = "Hello"; // 合法
value = 42; // 合法
// value = true; // 错误:类型 'true' 不能赋值给类型 'string | number'
② 内置方法
联合类型在 TypeScript 中有一些内置方法和技巧,可以帮助你在使用联合类型时更安全地处理属性和方法。以下是一些常用的内置方法:
方法名 | 描述 |
---|---|
typeof 类型保护 | 使用 typeof 类型保护来缩小联合类型的范围。通过检查变量的类型,可以在相应分支中安全地访问特定类型的属性和方法。 |
类型断言 | 使用类型断言来告诉 TypeScript 编译器一个变量的确切类型,从而可以安全地访问该类型的属性和方法。 |
共有属性检查 | 在联合类型上使用共有属性,确保所有类型都具有相同的属性。 |
函数重载 | 通过函数重载定义多个函数签名,使 TypeScript 能够根据输入值的类型正确调用相应的函数。 |
代码示例:
// typeof 类型保护
function printLength(value: string | number): void {
if (typeof value === "string") {
console.log(value.length); // 在这个分支中,value 被 TypeScript 理解为字符串类型
} else {
console.log(value.toFixed(2)); // 在这个分支中,value 被 TypeScript 理解为数字类型
}
}
printLength("Hello"); // 输出 5
printLength(42); // 输出 "42.00"
// 类型断言
let value: string | number = "Hello";
let len = (value as string).length; // 在这里使用类型断言将 value 明确指定为字符串类型
console.log(len); // 输出 5
// 共有属性检查
type StringOrNumber = string | number;
function printValue(value: StringOrNumber): void {
console.log(value.toString()); // toString 是 string 和 number 共有的方法
}
printValue("Hello"); // 输出 "Hello"
printValue(42); // 输出 "42"
// 函数重载
function processValue(value: string): void;
function processValue(value: number): void;
function processValue(value: string | number): void {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
processValue("Hello"); // 输出 "HELLO"
processValue(42); // 输出 "42.00"
③ 注意事项
- 联合类型的类型安全:
在使用联合类型时,确保类型安全非常重要。联合类型的类型安全可以通过以下几种方式来实现:- 类型保护:
使用typeof
、instanceof
或其他类型保护机制来缩小联合类型的范围,确保在特定分支中变量的类型是明确的。
- 类型保护:
function printLength(value: string | number): void {
if (typeof value === "string") {
console.log(value.length); // value 是字符串类型
} else {
console.log(value.toFixed(2)); // value 是数字类型
}
}
- **类型断言**:
在某些情况下,你可以使用类型断言来明确指定变量的类型,从而避免类型错误。
let value: string | number = "Hello";
let len = (value as string).length; // 类型断言
console.log(len); // 输出 5
- **共有属性检查**:
确保在联合类型上使用共有属性,避免访问不存在的属性。
type StringOrNumber = string | number;
function printValue(value: StringOrNumber): void {
console.log(value.toString()); // toString 是 string 和 number 共有的方法
}
- **函数重载**:
通过函数重载定义多个函数签名,使 TypeScript 能够根据输入值的类型正确调用相应的函数。
function processValue(value: string): void;
function processValue(value: number): void;
function processValue(value: string | number): void {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
相关链接
- 项目地址:TypeScript-CookBook
- 相关文档:专栏地址
- 作者主页:GISer Liu-CSDN博客
如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.