TypeScript入门—第二部分基本数据类型

119 阅读12分钟

阅读完TypeScript入门教程后,你现在应该能够在支持TypeScript的IDE中编写自己的TypeScript代码,然后将其编译为JavaScript。在本教程中,你将了解TypeScript中可用的不同种类的数据类型。

JavaScript有七种不同的数据类型。空、未定义、布尔、数字、字符串、符号(在ES6中引入)和对象。TypeScript还定义了一些类型,本教程将详细介绍所有这些类型。

空数据类型

就像在JavaScript中一样,TypeScript中的null 数据类型只能有一个有效值:null 。空变量不能包含其他数据类型,如数字和字符串。将一个变量设置为null将抹去它的内容,如果它有任何内容的话。

请记住,当strictNullChecks 标志在tsconfig.json中被设置为true ,只有null值可以被分配给null类型的变量。这个标志在默认情况下是关闭的,这意味着你也可以将null值分配给其他类型的变量,比如numbervoid

// 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 类型只能有两个有效值:nullundefined

// 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

布尔数据类型

numberstring 数据类型不同,boolean 只有两个有效值。你只能把它的值设置为truefalse 。这些值在控制结构中经常使用,如果一个条件是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 时,指定nullundefined 作为其中一个元素将产生错误。

// 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 ,其余元素可以是字符串或数字。创建图元bc 的结果是错误的,因为我们试图使用字符串作为第一个元素的值,而我们曾提到第一个元素将是一个数字。

同样,我们不能在指定了一个元组只包含字符串和数字之后,将元组元素的值设为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 Union Data TypeTypeScript Union Data TypeTypeScript Union Data Type

在函数定义中使用数据类型

函数处理了我们很多的编程逻辑。这些函数通常也接受一些变量作为参数形式的输入,然后返回一个具有相同或不同类型数据的结果。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中的接口。如果你有任何与本教程相关的问题,请在评论中告诉我。