阅读完TypeScript入门教程后,你现在应该能够在支持TypeScript的IDE中编写自己的TypeScript代码,然后将其编译为JavaScript。在本教程中,你将了解TypeScript中可用的不同种类的数据类型。
JavaScript有七种不同的数据类型。空、未定义、布尔、数字、字符串、符号(在ES6中引入)和对象。TypeScript还定义了一些类型,本教程将详细介绍所有这些类型。
空数据类型
就像在JavaScript中一样,TypeScript中的null 数据类型只能有一个有效值:null 。空变量不能包含其他数据类型,如数字和字符串。将一个变量设置为null将抹去它的内容,如果它有任何内容的话。
请记住,当strictNullChecks 标志在tsconfig.json中被设置为true ,只有null值可以被分配给null类型的变量。这个标志在默认情况下是关闭的,这意味着你也可以将null值分配给其他类型的变量,比如number 或void 。
// With strictNullChecks set to true
let a: null = null; // Ok
let b: undefined = null; // Error
let c: number = null; // Error
let d: void = null; // Error
// With strictNullChecks set to false
let a: null = null; // Ok
let b: undefined = null; // Ok
let c: number = null; // Ok
let d: void = null; // Ok
未定义的数据类型
任何你没有指定值的变量都会被设置为undefined 。然而,你也可以明确地将一个变量的类型设置为未定义,如下面的例子。
请记住,一个将type 设置为undefined 的变量只能将未定义作为其值。如果将strictNullChecks 选项设置为false ,你也可以将undefined 赋予数字和字符串类型的变量,等等。
// With strictNullChecks set to true
let a: undefined = undefined; // Ok
let b: undefined = null; // Error
let c: number = undefined; // Error
let d: void = undefined; // Ok
// With strictNullChecks set to false
let a: undefined = undefined; // Ok
let b: undefined = null; // Ok
let c: number = undefined; // Ok
let d: void = undefined; // Ok
空白数据类型
空白数据类型是用来表示一个变量没有type 。将变量设置为void 类型可能不是很有用,但你可以将不返回任何东西的函数的返回类型设置为void 。当与变量一起使用时,void 类型只能有两个有效值:null 和undefined 。
// With strictNullChecks set to true
let a: void = undefined; // Ok
let b: void = null; // Error
let c: void = 3; // Error
let d: void = "apple"; // Error
// With strictNullChecks set to false
let a: void = undefined; // Ok
let b: void = null; // Ok
let c: void = 3; // Error
let d: void = "apple"; // Error
布尔数据类型
与number 和string 数据类型不同,boolean 只有两个有效值。你只能把它的值设置为true 或false 。这些值在控制结构中经常使用,如果一个条件是true ,就执行一段代码,如果一个条件是false ,就执行另一段代码。
下面是一个非常基本的声明布尔变量的例子。
let a: boolean = true;
let b: boolean = false;
let c: boolean = 23; // Error
let d: boolean = "blue"; // Error
数字数据类型
number 数据类型用于表示JavaScript以及TypeScript中的整数和浮点值。然而,你应该记住,所有的数字在内部都表示为浮点值。数字也可以被指定为十六进制、八进制或二进制字样。请记住,八进制和二进制表示法是在ES6中引入的,这可能会导致不同的JavaScript代码输出,基于你所针对的版本。
还有三个额外的特殊符号值,属于number 类型。+Infinity,-Infinity, 和NaN 。下面是一些使用number 类型的例子。
// With strictNullChecks set to true
let a: number = undefined; // Error
let b: number = null; // Error
let c: number = 3;
let d: number = 0b111001; // Binary
let e: number = 0o436; // Octal
let f: number = 0xadf0d; // Hexadecimal
let g: number = "cat"; // Error
// With strictNullChecks set to false
let a: number = undefined; // Ok
let b: number = null; // Ok
let c: number = 3;
let d: number = 0b111001; // Binary
let e: number = 0o436; // Octal
let f: number = 0xadf0d; // Hexadecimal
let g: number = "cat"; // Error
当目标版本设置为ES6时,上述代码将编译为以下JavaScript。
let a = undefined;
let b = null;
let c = 3;
let d = 0b111001;
let e = 0o436;
let f = 0xadf0d;
let g = "cat";
你应该注意到,JavaScript的变量仍然使用let ,这是在ES6中引入的。你也不会看到任何与不同变量的type 有关的错误信息,因为JavaScript代码对我们在TypeScript代码中使用的类型没有了解。
如果目标版本设置为ES5,我们之前写的TypeScript代码就会编译成下面的JavaScript。
var a = undefined;
var b = null;
var c = 3;
var d = 57;
var e = 286;
var f = 0xadf0d;
var g = "cat";
正如你所看到的,这次所有出现的let 关键字都被改成了var 。还请注意,八进制和二进制的数字已经被改为十进制的形式。
字符串数据类型
字符串数据类型是用来存储文本信息的。JavaScript和TypeScript都使用双引号(")和单引号(')来环绕你的文本信息作为一个字符串。一个字符串可以包含零个或更多的字符,并被包围在引号内。
// With strictNullChecks set to true
let a: string = undefined; // Error
let b: string = null; // Error
let c: string = "";
let d: string = "y";
let e: string = "building";
let f: string = 3; // Error
let g: string = "3";
// With strictNullChecks set to false
let a: string = undefined; // Ok
let b: string = null; // Ok
let c: string = "";
let d: string = "y";
let e: string = "building";
let f: string = 3; // Error
let g: string = "3";
TypeScript也支持模板字符串或模板字面。这些模板字面允许你在一个字符串中嵌入表达式。模板字元由反切字符(`)包围,而不是由双引号和单引号包围常规字符串。它们是在ES6中引入的。这意味着你会根据你所针对的版本得到不同的JavaScript输出。下面是一个在TypeScript中使用模板字面的例子。
let e: string = "building";
let f: number = 300;
let sentence: string = `The ${e} in front of my office is ${f} feet tall.`;
编译后,你会得到以下的JavaScript。
// Output in ES5
var e = "building";
var f = 300;
var sentence = "The " + e + " in front of my office is " + f + " feet tall.";
// Output in ES6
let e = "building";
let f = 300;
let sentence = `The ${e} in front of my office is ${f} feet tall.`;
正如你所看到的,在ES5中,模板字面被改成了一个普通字符串。这个例子显示了TypeScript是如何让你有可能使用所有最新的JavaScript特性,而不用担心兼容性问题。
阵列和元组数据类型
你可以在JavaScript中以两种不同的方式定义数组类型。在第一种方法中,你指定数组元素的类型,然后是[] ,表示该类型的数组。另一种方法是使用通用数组类型Array<elemType> 。下面的例子显示了如何用这两种方法来创建数组。当strictNullChecks 标志为true 时,指定null 或undefined 作为其中一个元素将产生错误。
// With strictNullChecks set to false
let a: number[] = [1, 12, 93, 5];
let b: string[] = ["a", "apricot", "mango"];
let c: number[] = [1, "apple", "potato"]; // Error
let d: Array<number> = [null, undefined, 10, 15];
let e: Array<string> = ["pie", null, ""];
// With strictNullChecks set to true
let a: number[] = [1, 12, 93, 5];
let b: string[] = ["a", "apricot", "mango"];
let c: number[] = [1, "apple", "potato"]; // Error
let d: Array<number> = [null, undefined, 10, 15]; // Error
let e: Array<string> = ["pie", null, ""]; // Error
元组数据类型允许你创建一个数组,其中固定数量的元素的类型是预先知道的。其余元素的类型只能是你已经为元组指定的类型之一。这里有一个例子会让你更清楚。
let a: [number, string] = [11, "monday"];
let b: [number, string] = ["monday", 11]; // Error
let c: [number, string] = ["a", "monkey"]; // Error
let d: [number, string] = [105, "owl", 129, 45, "cat"];
let e: [number, string] = [13, "bat", "spiderman", 2];
e[13] = "elephant";
e[15] = false; // Error
对于我们例子中的所有图元,我们将第一个元素的type 设置为number ,将第二个元素的type 设置为string 。由于我们只为前两个元素指定了type ,其余元素可以是字符串或数字。创建图元b 和c 的结果是错误的,因为我们试图使用字符串作为第一个元素的值,而我们曾提到第一个元素将是一个数字。
同样,我们不能在指定了一个元组只包含字符串和数字之后,将元组元素的值设为false 。这就是为什么最后一行的结果是错误的。
枚举数据类型
enum 数据类型存在于许多编程语言中,如C和Java。它在JavaScript中一直缺失,但TypeScript允许你创建和使用枚举。如果你不知道什么是enums ,它们允许你使用令人难忘的名字创建一个相关值的集合。
enum Animals {cat, lion, dog, cow, monkey}
let c: Animals = Animals.cat;
console.log(Animals[3]); // cow
console.log(Animals.monkey); // 4
默认情况下,枚举的编号从0开始,但你也可以为第一个或任何其他成员手动设置一个不同的值。这将改变后面所有成员的值,使它们的值增加1。你也可以在一个enum ,手动设置所有的值。
enum Animals {cat = 1, lion, dog = 11, cow, monkey}
let c: Animals = Animals.cat;
console.log(Animals[3]); // undefined
console.log(Animals.monkey); // 13
与前面的例子不同,这次Animals[3] 的值是undefined 。这是因为值3本来是分配给dog的,但是我们明确地把它的值设置为11。cow的值保持在12,而不是3,因为这个值应该是比最后一个成员的值大一个。
Any和Never类型
假设你正在编写一个程序,其中一个变量的值是由用户或第三方库中编写的代码决定的。在这种情况下,你将无法正确设置该变量的类型。该变量可以是任何类型,如字符串、数字或布尔值。这个问题可以通过使用any 类型来解决。当你创建具有混合类型元素的数组时,这也很有用。
let a: any = "apple";
let b: any = 14;
let c: any = false;
let d: any[] = ["door", "kitchen", 13, false, null];
b = "people";
在上面的代码中,我们能够给b ,然后把它的值改为字符串,而没有得到任何错误,因为any 类型可以接受所有类型的值。
never 类型用于表示那些不应该出现的值。例如,你可以将never 作为一个从未返回的函数的返回类型。当一个函数总是抛出一个错误或陷入一个无限循环时,就会发生这种情况。
let a: never; // Ok
let b: never = false; // Error
let c: never = null; // Error
let d: never = "monday"; // Error
function stuck(): never {
while (true) {
}
}
联合类型
当你在编写程序时,总有一些时候你必须使用可能是多种类型的变量。例如,一个用于存储UI元素宽度的变量可以是一个数字或一个字符串。同样地,你可以用一个变量来跟踪元素周围的填充物。在这种情况下,将一个变量定义为一个单一的类型是不行的,使用any ,只会让它接受各种类型的变量而不会产生错误。
你可以在union 类型的帮助下克服这些缺点。顾名思义,它们基本上是两个或多个类型的联合。
let elemWidth: number|string = 10; // Ok
elemWidth = "50%"; // Ok
elemWidth = [12, 30]; // Error
let elemPadding: number|number[] = 20; // Ok
elemPadding = [5, 10, 5, 20]; // Ok
elemPadding = [5, "10", 15, 20]; // Error
所有的数据类型都有一套特定的方法,你可以调用。例如,你可以在JavaScript中使用includes() 方法来检查一个字符串是否包含另一个子串。然而,这个方法在数字上调用时是没有意义的。
使用union 类型定义一个变量,会自动限制你对那些只对所有包含的数据类型可用的方法的访问。由于这个原因,在上面的变量elemWidth 上调用includes() 方法会导致错误。下面是一个VS代码的截图,显示了当我们在includes() 上调用elemWidth 时的错误信息。



在函数定义中使用数据类型
函数处理了我们很多的编程逻辑。这些函数通常也接受一些变量作为参数形式的输入,然后返回一个具有相同或不同类型数据的结果。TypeScript 允许我们指定每个参数的数据类型,以及我们期望函数返回的数据类型。当你在做有很多接受多个参数的函数的大型项目时,这可能非常有用。
你可以在每个参数的名字后面指定不同函数参数的数据类型。函数的返回类型在参数列表之后。下面是一个例子。
function clampNumber(n: number): number {
return Math.max(0, Math.min(n, 255));
}
function rgbToHex(r: number, g: number, b: number): string {
let cr = clampNumber(r);
let cg = clampNumber(g);
let cb = clampNumber(b);
let color = "#" + cr.toString(16).padStart(2, '0') + cg.toString(16).padStart(2, '0') + cb.toString(16).padStart(2, '0');
return color;
}
let black: string = rgbToHex(0, 0, "0");
let red: number = rgbToHex(255, 0, 0);
let blue: string = rgbToHex(0, 0, 255);
我们在这里定义了两个函数。clampNumber() 函数接收一个输入数字,并将其数值夹在0和255之间。然后,rgbToHex() 函数接收三个不同的数字,在夹紧后将其转换为十六进制格式,并返回一个字符串。
我们在上面的代码中调用了三次rgbToHex() 。然而,前两次调用的结果是错误的,因为参数类型和返回类型都不正确。在我们解决这些错误之前,代码不会转译成JavaScript。这种对函数参数和返回值的类型检查有助于我们写出无错误的代码,最终提高生产力。
最后的思考
本教程向你介绍了TypeScript中可用的所有类型。我们了解到,在TypeScript中,为变量分配不同类型的值会显示错误。这种检查可以帮助你在编写大型程序时避免大量的错误。我们还学习了如何针对不同版本的JavaScript。
如果你正在寻找更多的资源来学习或在工作中使用,请查看我们在Envato市场上的内容。
在下一个教程中,你将学习TypeScript中的接口。如果你有任何与本教程相关的问题,请在评论中告诉我。