MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

TypeScript数据类型详解:number、string、boolean等基本类型

2023-04-215.3k 阅读

number 类型

在 TypeScript 中,number 类型用于表示数字。无论是整数还是浮点数,都可以用 number 类型来定义。这与 JavaScript 中的数字类型一致,因为 JavaScript 本身只有一种数字类型,即双精度 64 位二进制格式(IEEE 754)。

定义 number 类型变量

let myNumber: number;
myNumber = 42;
console.log(myNumber); 

let decimal: number = 6.28; 
console.log(decimal); 

let binary: number = 0b1010; 
console.log(binary); 

let octal: number = 0o755; 
console.log(octal); 

let hexadecimal: number = 0xf00d; 
console.log(hexadecimal); 

在上述代码中,首先声明了一个 myNumber 变量,并指定其类型为 number,然后为其赋值为整数 42。接着定义了 decimal 用于表示小数。同时,也展示了如何用二进制(前缀 0b)、八进制(前缀 0o)和十六进制(前缀 0x)的形式来表示数字。

常见的数学运算

number 类型支持常见的数学运算,如加、减、乘、除等。

let num1: number = 5;
let num2: number = 3;

let sum: number = num1 + num2; 
console.log(sum); 

let difference: number = num1 - num2; 
console.log(difference); 

let product: number = num1 * num2; 
console.log(product); 

let quotient: number = num1 / num2; 
console.log(quotient); 

let remainder: number = num1 % num2; 
console.log(remainder); 

在这段代码中,定义了两个 number 类型的变量 num1num2,然后进行了加法、减法、乘法、除法和取余运算,并输出结果。

特殊的数字值

JavaScript 中有一些特殊的数字值,在 TypeScript 中同样适用。

  • NaN:表示非数字值。它不等于任何值,包括自身。
let notANumber: number = NaN;
console.log(notANumber === NaN); 
console.log(isNaN(notANumber)); 
  • Infinity-Infinity:分别表示正无穷和负无穷。当一个数运算结果过大或过小超出 JavaScript 能表示的范围时,就会得到 Infinity-Infinity
let largeNumber: number = 1e1000; 
console.log(largeNumber); 

let smallNumber: number = 1e-1000; 
console.log(smallNumber); 

在上述代码中,1e1000 会得到 Infinity1e - 1000 会得到 -Infinity

string 类型

string 类型用于表示文本数据。在 TypeScript 中,string 类型和 JavaScript 中的字符串类型概念相同,都是由零个或多个 Unicode 字符组成的序列。

定义 string 类型变量

可以使用单引号、双引号或模板字符串来定义 string 类型变量。

let singleQuoted: string = 'Hello, world!';
let doubleQuoted: string = "Hello, world!";
let templateString: string = `Hello, ${singleQuoted}`;
console.log(singleQuoted); 
console.log(doubleQuoted); 
console.log(templateString); 

在代码中,singleQuoted 使用单引号定义,doubleQuoted 使用双引号定义,templateString 使用模板字符串定义。模板字符串允许嵌入表达式,通过 ${} 语法实现。

字符串操作

  1. 字符串拼接 可以使用 + 运算符或模板字符串来拼接字符串。
let part1: string = 'Hello';
let part2: string = 'world';

let concatenated1: string = part1 + ', ' + part2 + '!';
let concatenated2: string = `${part1}, ${part2}!`;
console.log(concatenated1); 
console.log(concatenated2); 
  1. 获取字符串长度 可以使用 length 属性获取字符串的长度。
let myString: string = 'TypeScript';
console.log(myString.length); 
  1. 字符串方法 JavaScript 提供了许多字符串方法,在 TypeScript 中同样可以使用。
  • charAt():返回指定位置的字符。
let str: string = 'example';
console.log(str.charAt(2)); 
  • indexOf():返回指定字符在字符串中首次出现的位置,如果不存在则返回 -1。
let searchStr: string = 'hello world';
console.log(searchStr.indexOf('world')); 
console.log(searchStr.indexOf('goodbye')); 
  • slice():提取字符串的一部分,并返回一个新字符串。
let original: string = 'TypeScript is great';
let sliced: string = original.slice(0, 9); 
console.log(sliced); 
  • toUpperCase()toLowerCase():分别将字符串转换为大写和小写。
let mixedCase: string = 'HeLLo';
console.log(mixedCase.toUpperCase()); 
console.log(mixedCase.toLowerCase()); 

boolean 类型

boolean 类型是一种基本的数据类型,只有两个值:truefalse。它通常用于逻辑判断。

定义 boolean 类型变量

let isDone: boolean = false;
let isSuccess: boolean = true;
console.log(isDone); 
console.log(isSuccess); 

在上述代码中,定义了 isDoneisSuccess 两个 boolean 类型的变量,并分别赋值为 falsetrue

在条件判断中使用 boolean 类型

boolean 类型最常见的用途是在条件语句中,如 if - elsewhile 等。

let isLoggedIn: boolean = true;
if (isLoggedIn) {
    console.log('Welcome, user!');
} else {
    console.log('Please log in.');
}

let count: number = 0;
while (count < 5) {
    console.log(count);
    count++;
}

if - else 语句中,根据 isLoggedIn 的值来决定输出不同的信息。在 while 循环中,count < 5 是一个 boolean 表达式,当该表达式为 true 时,循环会继续执行。

null 和 undefined 类型

nullundefined 在 TypeScript 中有特殊的意义。它们本身是两种类型,同时也可以作为其他类型的子类型。

null 类型

null 类型只有一个值,即 null,表示空值。

let myNull: null = null;
console.log(myNull); 

undefined 类型

undefined 类型也只有一个值,即 undefined,表示未定义。当一个变量声明但未初始化时,它的值就是 undefined

let myUndefined: undefined;
console.log(myUndefined); 

function myFunction(): undefined {
    return;
}
let result: undefined = myFunction();
console.log(result); 

在上述代码中,首先声明了一个 myUndefined 变量,它的值是 undefined。然后定义了一个函数 myFunction,该函数没有返回值,所以返回类型是 undefined,并将函数的返回值赋给 result 变量。

严格空值检查

在 TypeScript 的严格模式下(strictNullChecks 开启),nullundefined 只能赋值给 nullundefined 类型的变量,除非明确进行了类型断言或使用 ! 后缀操作符。

let value: string | null | undefined;
value = 'hello';
value = null; 
value = undefined; 

let str: string = value!; 
console.log(str); 

在这段代码中,value 变量被定义为可以是 stringnullundefined 类型。如果要将 value 赋值给 str 变量(strstring 类型),在严格空值检查模式下,需要使用 ! 后缀操作符来断言 value 不是 nullundefined

any 类型

any 类型是 TypeScript 中一种特殊的数据类型,它允许赋值为任意类型的值。当你不确定一个值的类型,或者你希望它可以是任何类型时,可以使用 any 类型。

定义 any 类型变量

let myAny: any = 42;
myAny = 'hello';
myAny = true;
console.log(myAny); 

在上述代码中,myAny 变量被定义为 any 类型,所以可以先后赋值为 numberstringboolean 类型的值。

在函数参数和返回值中使用 any 类型

function printValue(value: any) {
    console.log(value);
}

printValue(10); 
printValue('text'); 
printValue(true); 

function getValue(): any {
    return 'default value';
}
let resultAny: any = getValue();
console.log(resultAny); 

printValue 函数中,参数 value 被定义为 any 类型,所以可以接受任何类型的参数。getValue 函数返回类型为 any,所以 resultAny 可以接收函数返回的任意类型的值。

慎用 any 类型

虽然 any 类型提供了很大的灵活性,但过度使用会失去 TypeScript 类型检查的优势。尽量在明确知道类型的情况下使用具体类型,只有在无法确定类型时才使用 any 类型。

void 类型

void 类型表示没有任何类型。通常用于函数返回值,当一个函数没有返回值时,其返回类型就是 void

定义 void 类型函数

function logMessage(message: string): void {
    console.log(message);
}
logMessage('This is a log message'); 

let voidValue: void; 
voidValue = undefined; 

在上述代码中,logMessage 函数打印一条消息但没有返回值,所以其返回类型为 void。同时,也可以声明一个 void 类型的变量,不过它只能赋值为 undefined(在严格模式下,null 不能赋值给 void 类型变量)。

never 类型

never 类型表示永远不会出现的值的类型。它通常出现在函数永远抛出异常或永远不会返回的情况下。

函数永远抛出异常

function throwError(message: string): never {
    throw new Error(message);
}
try {
    throwError('This is an error');
} catch (e) {
    console.log(e.message); 
}

throwError 函数中,它总是抛出一个错误,所以其返回类型是 never

函数永远不会返回

function infiniteLoop(): never {
    while (true) {
    }
}

infiniteLoop 函数进入了一个无限循环,永远不会返回,所以其返回类型也是 never

类型别名

TypeScript 允许使用类型别名来给一个类型起一个新名字。这在处理复杂类型或为已有类型创建更具描述性的名称时非常有用。

定义类型别名

type UserID = number;
let userId: UserID = 12345;
console.log(userId); 

type StringOrNumber = string | number;
let value: StringOrNumber = 'text';
value = 42;
console.log(value); 

在上述代码中,首先定义了 UserID 类型别名,它是 number 类型的别名,然后使用 UserID 类型别名定义了 userId 变量。接着定义了 StringOrNumber 类型别名,表示 stringnumber 类型,value 变量可以是这两种类型之一。

类型别名用于函数类型

type AddFunction = (a: number, b: number) => number;
let add: AddFunction = (num1, num2) => num1 + num2;
console.log(add(5, 3)); 

在这段代码中,AddFunction 是一个函数类型别名,它表示接受两个 number 类型参数并返回一个 number 类型值的函数。然后定义了 add 函数,其类型符合 AddFunction 类型别名。

联合类型

联合类型允许一个变量具有多种类型。通过使用 | 运算符来分隔不同的类型。

定义联合类型变量

let myValue: string | number;
myValue = 'hello';
console.log(myValue); 
myValue = 42;
console.log(myValue); 

在上述代码中,myValue 变量被定义为 stringnumber 类型,所以可以分别赋值为字符串和数字。

在函数中使用联合类型

function printValueUnion(value: string | number) {
    if (typeof value ==='string') {
        console.log(value.length); 
    } else {
        console.log(value.toFixed(2)); 
    }
}

printValueUnion('test'); 
printValueUnion(12.345); 

printValueUnion 函数中,参数 valuestringnumber 类型。通过 typeof 运算符判断 value 的实际类型,然后执行不同的操作。如果是 string 类型,打印其长度;如果是 number 类型,将其保留两位小数后打印。

交叉类型

交叉类型是将多个类型合并为一个类型。它表示一个对象同时具有多个类型的所有属性和方法。通过使用 & 运算符来创建交叉类型。

定义交叉类型

type A = { name: string };
type B = { age: number };
type AB = A & B;

let person: AB = { name: 'John', age: 30 };
console.log(person.name); 
console.log(person.age); 

在上述代码中,首先定义了 AB 两个类型,然后通过 & 运算符创建了交叉类型 AB,它同时具有 AB 类型的属性。接着定义了 person 对象,其类型为 AB,所以必须包含 nameage 属性。

交叉类型在函数参数中的应用

function printPerson(person: { name: string } & { age: number }) {
    console.log(`${person.name} is ${person.age} years old.`);
}

printPerson({ name: 'Jane', age: 25 }); 

printPerson 函数中,参数 person 的类型是一个交叉类型,要求对象同时具有 nameage 属性。

字面量类型

字面量类型是指使用具体的字面量值(如字符串字面量、数字字面量、布尔字面量)来定义类型。

字符串字面量类型

type Fruit = 'apple' | 'banana' | 'cherry';
let myFruit: Fruit = 'apple';
// myFruit = 'grape'; 

在上述代码中,Fruit 类型被定义为 'apple''banana''cherry' 这几个字符串字面量类型的联合。myFruit 变量只能赋值为这三个值之一,尝试赋值为 'grape' 会导致类型错误。

数字字面量类型

type Direction = 1 | -1;
let move: Direction = 1;
// move = 2; 

在这段代码中,Direction 类型被定义为 1-1 这两个数字字面量类型的联合。move 变量只能赋值为 1-1,赋值为 2 会引发类型错误。

布尔字面量类型

type Status = true | false;
let isActive: Status = true;
// isActive = 'yes'; 

Status 类型被定义为 truefalse 这两个布尔字面量类型的联合。isActive 变量只能赋值为 truefalse,赋值为 'yes' 会导致类型错误。

类型断言

类型断言是告诉编译器“相信我,我知道自己在做什么”。它允许你手动指定一个值的类型,而不是让 TypeScript 自动推断。

两种类型断言语法

  1. 尖括号语法
let someValue: any = 'this is a string';
let strLength: number = (<string>someValue).length;
console.log(strLength); 

在上述代码中,someValueany 类型,通过 <string> 断言将其转换为 string 类型,然后可以访问 length 属性。

  1. as 语法
let anotherValue: any = 'this is another string';
let anotherStrLength: number = (anotherValue as string).length;
console.log(anotherStrLength); 

as 语法和尖括号语法功能相同,as 语法在 JSX 中更常用,因为尖括号在 JSX 中有其他用途。

非空断言

非空断言使用 ! 后缀操作符,用于断言一个值不是 nullundefined

let maybeNull: string | null = 'test';
let length: number = maybeNull!.length; 
console.log(length); 

maybeNull = null;
// let newLength: number = maybeNull!.length; 

在上述代码中,通过 ! 断言 maybeNull 不是 nullundefined,从而可以访问其 length 属性。当 maybeNull 被赋值为 null 后,再次使用 ! 断言会导致运行时错误,因为此时断言不符合实际情况。

类型推断

TypeScript 具有类型推断的能力,它可以在很多情况下自动推断出变量的类型,而无需显式声明。

基础类型推断

let num = 42; 
// num 的类型被推断为 number
let str = 'hello'; 
// str 的类型被推断为 string
let bool = true; 
// bool 的类型被推断为 boolean

在上述代码中,没有显式指定 numstrbool 的类型,但 TypeScript 根据赋值自动推断出了它们的类型。

函数返回值类型推断

function addNumbers(a: number, b: number) {
    return a + b;
}
// addNumbers 的返回值类型被推断为 number
let result: number = addNumbers(5, 3);
console.log(result); 

addNumbers 函数中,没有显式指定返回值类型,但 TypeScript 根据 return 语句的表达式推断出返回值类型为 number

上下文类型推断

上下文类型推断是指 TypeScript 根据变量使用的上下文来推断其类型。

document.addEventListener('click', function (event) {
    console.log(event.pageX); 
});

addEventListener 的回调函数中,event 参数的类型没有显式声明,但 TypeScript 根据 addEventListener 的定义以及 click 事件的上下文,推断出 eventMouseEvent 类型,所以可以访问 pageX 属性。

数组类型

TypeScript 提供了多种方式来定义数组类型。

类型 + 方括号语法

let numbers: number[] = [1, 2, 3, 4, 5];
let strings: string[] = ['a', 'b', 'c'];
console.log(numbers); 
console.log(strings); 

在上述代码中,numbersnumber 类型的数组,stringsstring 类型的数组。

数组泛型语法

let booleans: Array<boolean> = [true, false, true];
console.log(booleans); 

Array<boolean> 表示 boolean 类型的数组,和 boolean[] 语法效果相同。

联合类型数组

let mixedArray: (string | number)[] = ['a', 1, 'b', 2];
console.log(mixedArray); 

mixedArray 中,元素可以是 string 类型或 number 类型。

多维数组

let matrix: number[][] = [
    [1, 2],
    [3, 4]
];
console.log(matrix); 

matrix 是一个二维数组,每个元素又是一个 number 类型的数组。

元组类型

元组类型是一种特殊的数组类型,它允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

定义元组类型

let user: [string, number] = ['John', 30];
console.log(user[0]); 
console.log(user[1]); 

在上述代码中,user 是一个元组类型,第一个元素是 string 类型,第二个元素是 number 类型。

访问和修改元组元素

let point: [number, number] = [10, 20];
let x: number = point[0];
let y: number = point[1];
point[0] = 15;
console.log(point); 

可以通过索引访问和修改元组元素,但要注意索引不能越界,并且类型要匹配。

元组类型的扩展

let extendedUser: [string, number, boolean] = ['Jane', 25, true];
console.log(extendedUser); 

元组类型可以扩展元素数量和类型,只要符合定义的顺序和类型要求。

枚举类型

枚举类型是 TypeScript 为 JavaScript 增加的一种数据类型,用于定义一组命名常量。

数字枚举

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

在上述代码中,定义了一个 Direction 枚举类型,Up 被赋值为 1,其他成员会自动递增,Down2Left3Right4

字符串枚举

enum Status {
    Success = 'success',
    Failure = 'failure'
}
console.log(Status.Success); 
console.log(Status.Failure); 

在字符串枚举中,每个成员必须手动赋值为字符串字面量。

异构枚举

异构枚举是指成员既有数字类型又有字符串类型的枚举,不过这种情况不常见且可能导致一些复杂性,应谨慎使用。

enum MixedEnum {
    Value1 = 1,
    Value2 = 'two'
}
console.log(MixedEnum.Value1); 
console.log(MixedEnum.Value2); 

MixedEnum 枚举中,Value1 是数字类型,Value2 是字符串类型。

反向映射

对于数字枚举,TypeScript 会创建反向映射,即可以通过枚举值获取枚举名。

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

在上述代码中,通过 Colors[2] 可以获取到枚举名 Green,因为 Green 的值是 2。而字符串枚举没有反向映射。

通过对以上 TypeScript 基本数据类型的详细介绍,希望能帮助你更深入地理解和运用 TypeScript 进行前端开发,充分发挥 TypeScript 类型系统的优势,提高代码的可读性和可维护性。