TypeScript数据类型详解:number、string、boolean等基本类型
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
类型的变量 num1
和 num2
,然后进行了加法、减法、乘法、除法和取余运算,并输出结果。
特殊的数字值
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
会得到 Infinity
,1e - 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
使用模板字符串定义。模板字符串允许嵌入表达式,通过 ${}
语法实现。
字符串操作
- 字符串拼接
可以使用
+
运算符或模板字符串来拼接字符串。
let part1: string = 'Hello';
let part2: string = 'world';
let concatenated1: string = part1 + ', ' + part2 + '!';
let concatenated2: string = `${part1}, ${part2}!`;
console.log(concatenated1);
console.log(concatenated2);
- 获取字符串长度
可以使用
length
属性获取字符串的长度。
let myString: string = 'TypeScript';
console.log(myString.length);
- 字符串方法 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
类型是一种基本的数据类型,只有两个值:true
和 false
。它通常用于逻辑判断。
定义 boolean 类型变量
let isDone: boolean = false;
let isSuccess: boolean = true;
console.log(isDone);
console.log(isSuccess);
在上述代码中,定义了 isDone
和 isSuccess
两个 boolean
类型的变量,并分别赋值为 false
和 true
。
在条件判断中使用 boolean 类型
boolean
类型最常见的用途是在条件语句中,如 if - else
、while
等。
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 类型
null
和 undefined
在 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
开启),null
和 undefined
只能赋值给 null
和 undefined
类型的变量,除非明确进行了类型断言或使用 !
后缀操作符。
let value: string | null | undefined;
value = 'hello';
value = null;
value = undefined;
let str: string = value!;
console.log(str);
在这段代码中,value
变量被定义为可以是 string
、null
或 undefined
类型。如果要将 value
赋值给 str
变量(str
是 string
类型),在严格空值检查模式下,需要使用 !
后缀操作符来断言 value
不是 null
或 undefined
。
any 类型
any
类型是 TypeScript 中一种特殊的数据类型,它允许赋值为任意类型的值。当你不确定一个值的类型,或者你希望它可以是任何类型时,可以使用 any
类型。
定义 any 类型变量
let myAny: any = 42;
myAny = 'hello';
myAny = true;
console.log(myAny);
在上述代码中,myAny
变量被定义为 any
类型,所以可以先后赋值为 number
、string
和 boolean
类型的值。
在函数参数和返回值中使用 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
类型别名,表示 string
或 number
类型,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
变量被定义为 string
或 number
类型,所以可以分别赋值为字符串和数字。
在函数中使用联合类型
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
函数中,参数 value
是 string
或 number
类型。通过 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);
在上述代码中,首先定义了 A
和 B
两个类型,然后通过 &
运算符创建了交叉类型 AB
,它同时具有 A
和 B
类型的属性。接着定义了 person
对象,其类型为 AB
,所以必须包含 name
和 age
属性。
交叉类型在函数参数中的应用
function printPerson(person: { name: string } & { age: number }) {
console.log(`${person.name} is ${person.age} years old.`);
}
printPerson({ name: 'Jane', age: 25 });
在 printPerson
函数中,参数 person
的类型是一个交叉类型,要求对象同时具有 name
和 age
属性。
字面量类型
字面量类型是指使用具体的字面量值(如字符串字面量、数字字面量、布尔字面量)来定义类型。
字符串字面量类型
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
类型被定义为 true
或 false
这两个布尔字面量类型的联合。isActive
变量只能赋值为 true
或 false
,赋值为 'yes'
会导致类型错误。
类型断言
类型断言是告诉编译器“相信我,我知道自己在做什么”。它允许你手动指定一个值的类型,而不是让 TypeScript 自动推断。
两种类型断言语法
- 尖括号语法
let someValue: any = 'this is a string';
let strLength: number = (<string>someValue).length;
console.log(strLength);
在上述代码中,someValue
是 any
类型,通过 <string>
断言将其转换为 string
类型,然后可以访问 length
属性。
as
语法
let anotherValue: any = 'this is another string';
let anotherStrLength: number = (anotherValue as string).length;
console.log(anotherStrLength);
as
语法和尖括号语法功能相同,as
语法在 JSX 中更常用,因为尖括号在 JSX 中有其他用途。
非空断言
非空断言使用 !
后缀操作符,用于断言一个值不是 null
或 undefined
。
let maybeNull: string | null = 'test';
let length: number = maybeNull!.length;
console.log(length);
maybeNull = null;
// let newLength: number = maybeNull!.length;
在上述代码中,通过 !
断言 maybeNull
不是 null
或 undefined
,从而可以访问其 length
属性。当 maybeNull
被赋值为 null
后,再次使用 !
断言会导致运行时错误,因为此时断言不符合实际情况。
类型推断
TypeScript 具有类型推断的能力,它可以在很多情况下自动推断出变量的类型,而无需显式声明。
基础类型推断
let num = 42;
// num 的类型被推断为 number
let str = 'hello';
// str 的类型被推断为 string
let bool = true;
// bool 的类型被推断为 boolean
在上述代码中,没有显式指定 num
、str
和 bool
的类型,但 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
事件的上下文,推断出 event
是 MouseEvent
类型,所以可以访问 pageX
属性。
数组类型
TypeScript 提供了多种方式来定义数组类型。
类型 + 方括号语法
let numbers: number[] = [1, 2, 3, 4, 5];
let strings: string[] = ['a', 'b', 'c'];
console.log(numbers);
console.log(strings);
在上述代码中,numbers
是 number
类型的数组,strings
是 string
类型的数组。
数组泛型语法
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
,其他成员会自动递增,Down
为 2
,Left
为 3
,Right
为 4
。
字符串枚举
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 类型系统的优势,提高代码的可读性和可维护性。