TypeScript入门 (三)数据类型

news2024/9/22 7:29:43

head-bar

引言

大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的各种数据类型,帮助读者深入理解每种数据类型的用法、内置属性和方法,以及在实际开发中的应用。💕💕😊


介绍

在 TypeScript 中,数据类型是构建可靠且可维护代码的基础。通过显式地声明变量的类型,开发者可以在编译时捕获潜在的错误,避免在运行时出现意外的类型错误。TypeScript 提供了丰富的内置数据类型,如 NumberStringArrayTupleMap 等,以及高级类型如 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; // 十六进制
  • 二进制:以 0b0B 开头。
  • 八进制:以 0o0O 开头。
  • 十进制:直接表示。
  • 十六进制:以 0x0X 开头。
② 内置属性

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(): Tundefined`

代码示例

// 声明一个元组
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"
③ 注意事项
  • 联合类型的类型安全
    在使用联合类型时,确保类型安全非常重要。联合类型的类型安全可以通过以下几种方式来实现:
    • 类型保护
      使用 typeofinstanceof 或其他类型保护机制来缩小联合类型的范围,确保在特定分支中变量的类型是明确的。
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博客

thank_watch

如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.

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

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

相关文章

LabVIEW提高开发效率技巧----自动化测试和持续集成

在大型项目中&#xff0c;自动化测试和持续集成是提高开发效率和代码质量的关键手段。通过这些技术&#xff0c;开发者能够在开发的早期阶段快速发现问题&#xff0c;减少后期调试的工作量&#xff0c;并且能够确保代码的稳定性和可维护性。以下是这两个概念如何在LabVIEW开发中…

Docker Networking Tutorial (Bridge - None - Host - IPvlan - Macvlan )

In this article, We will talk about the network of docker. Therere have five types of docker network. 一、Bridge The default network of docker network type. You can use : docker network ls docker network create --driver bridge my_bridge_network ##The CID…

什么是 GPT?通过图形化的方式来理解 Transformer 架构

Predict, sample, repeat 预测、取样、重复 GPT 是 Generative Pre-trained Transformer 的缩写。首个单词较为直接&#xff0c;它们是用来生成新文本的机器人。“Pre-trained” 指的是模型经历了从大量数据中学习的过程&#xff0c;这个词暗示了该模型还有进一步在特定任务中…

移动技术开发:ListView水果列表

1 实验名称 ListView水果列表 2 实验目的 掌握自定义ListView控件的实现方法 3 实验源代码 布局文件代码&#xff1a; activity_main.xml: <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.androi…

Java 中Lock接口锁的使用

一. Lock接口下的实现类 在Java中&#xff0c;Lock 接口是 java.util.concurrent.locks 包中的一部分&#xff0c;它提供了比 synchronized 更丰富的锁操作。Lock 接口的实现类包括 ReentrantLock&#xff08;可重入锁&#xff09;、ReadWriteLock&#xff08;读写锁&#xff…

从零开始学习TinyWebServer

写在前面 项目参考&#xff1a;https://github.com/qinguoyi/TinyWebServer 写作框架/图参考&#xff1a;https://blog.csdn.net/qq_52313711/article/details/136356042?spm1001.2014.3001.5502 原本计划是&#xff0c;先将项目代码大概看一遍&#xff0c;然后再着手实现一下…

【hot100-java】【组合总和】

R8-回溯篇 印象题&#xff0c;很基本的回溯 class Solution {void backtrack(List<Integer> state,int target,int[] choices,int start,List<List<Integer>> ret){//子集和等于target&#xff0c;记录解if (target0){ret.add(new ArrayList<>(state)…

LeetCode讲解篇之1343. 大小为 K 且平均值大于等于阈值的子数组数目

文章目录 题目描述题解思路题解代码 题目描述 题解思路 题目让我们求长度为k的子数组并且该子数组的平均值大于threshold&#xff0c;对于这题&#xff0c;我们可以考虑维护一个长度为k的窗口&#xff0c;窗口不断向右滑动&#xff0c;遍历所有长度为k的子数组&#xff0c;我们…

低版本SqlSugar的where条件中使用可空类型报语法错误

SQLServer数据表中有两列可空列&#xff0c;均为数值类型&#xff0c;同时在数据库中录入测试数据&#xff0c;Age和Height列均部分有值。   使用SqlSugar的DbFirst功能生成数据库表类&#xff0c;其中Age、Height属性均为可空类型。   开始使用的SqlSugar版本较低&…

win11 wsl2安装ubuntu22最快捷方法

操作系统是win11&#xff0c;wsl版本是wsl2&#xff0c;wsl应该不用多介绍了&#xff0c;就是windows上的虚拟机&#xff0c;在wsl上可以很方便的运行Linux系统&#xff0c;性能棒棒的&#xff0c;而且wsl运行的系统和win11主机之间的文件移动是无缝的&#xff0c;就是两个系统…

力扣115-不同的子序列(Java详细题解)

题目链接&#xff1a;不同的子序列 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一个dp题目…

Spring IDEA 2024 安装Lombok插件

1.简介 Lombook插件的Data标签可以自动生成类的get和set以及toString方法。 2.安装步骤 在idead设置的插件中搜索lombok插件&#xff0c;安装。 在Spring项目的pom.xml中添加依赖项 <dependency><groupId>org.projectlombok</groupId><artifactId…

数据结构与算法——Java实现 7.习题——反转链表

当你穿过了暴风雨&#xff0c;你已不是原来那个人 —— 24.9.21 206. 反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输…

echarts标注legend的配置

代码&#xff1a; legend: [{top: bottom, //上下位置 top center bottom 还可以用百分比50%等orient: horizontal, // 竖立 vertical horizontal 水平的// right: 0, //靠右 还可以用百分比 50%等// left: 0,// 靠左 还可以用百分比 50%等// 左右位置 否则居中itemWidth: …

前端框架Vue、React、Angular、Svelte对比

在对比 React、Vue.js、Angular 和 Svelte 时&#xff0c;除了在高层次的特性上有显著差异&#xff0c;它们在核心设计理念和底层实现机制上也有明显的不同。为了清晰地理解这些框架&#xff0c;我们可以从以下几个方面来分析它们的核心不同点和底层不同点。 1. 框架类型和设计…

ARM 栈和函数调用

阅读本文前&#xff0c;可以先阅读下述文档&#xff0c;对函数栈、栈帧等的概念会有所了解&#xff0c;会对本文章的理解大有益处 X86_64 栈和函数调用 1、调试环境 Ubuntu&#xff1a; liangjieliangjie-virtual-machine:~/Desktop$ cat /proc/version Linux version 6.5.0…

WebRTC编译后替换libwebrtc.aar时提示找不到libjingle_peerconnection_so.so库

Loading native library: jingle_peerconnection_so 问题原因&#xff1a;编译的时候只编译了armeabi-v7a的版本&#xff0c;但是应用程序是arm64-v8a&#xff0c;所以无法运行 解决方法&#xff1a;更新编译脚本&#xff0c;加上arm64-v8a进行编译 ./tools_webrtc/android/bu…

OpenAI GPT o1技术报告阅读(5)-安全性对齐以及思维链等的综合评估与思考

✨继续阅读报告&#xff1a;使用大模型来学习推理(Reason) 原文链接&#xff1a;https://openai.com/index/learning-to-reason-with-llms/ 编码 我们训练了一个模型&#xff0c;在2024年国际信息学奥林匹克竞赛&#xff08;IOI&#xff09;中得分213分&#xff0c;排名在第…

Arthas sysenv(查看JVM的环境变量)

文章目录 二、命令列表2.1 jvm相关命令2.1.5 sysenv&#xff08;查看JVM的环境变量&#xff09;举例1&#xff1a;sysenv 查看所有环境变量举例2&#xff1a;sysenv java.version 查看单个属性&#xff0c;支持通过tab补全 二、命令列表 2.1 jvm相关命令 2.1.5 sysenv&#x…

saas收银系统源码

1. 线下门店多样化收银 ①门店有社区小店、也会有大店&#xff0c;甚至还会有夫妻店&#xff0c;同时还要有Windows版和安卓版&#xff0c;需满足不同门店的收银需求。 ②支持Windows收银、安卓收银、无人自助收银、聚合码收银等&#xff0c;支持ai智能称重、收银称重一体机等…