Typescript的数据类型

typescript为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要提供了以下类型

数据类型

  • 布尔类型(boolean)
  • 数字类型(number)
  • 字符串类型(string)
  • 数组类型(array)
  • 元组类型(tuple)
  • 枚举类型(enum)
  • 任意类型(any)
  • null 和 undefined
  • void类型
  • never类型
  1. var flag = true;
  2. flag = 456; // ES5可以这样写,但在typescript中,此处会在编写时报错
  3. // 指定变量类型
  4. var flag:boolean = true; // 布尔类型
  5. var str:string = 'hello'; // 字符串类型
  6. var num1:number = 123; // 数字类型
  7. // any类型可以赋任意类型的值
  8. var num:any = 123;
  9. num = true;
  10. num = 'abc';
  11. // 第1种定义数组的方式
  12. var arr:number[] = [12, 5, 8];
  13. // 第2种定义数组的方式
  14. var arr:Array<number> = [12, 5, 8];
  15. // 元组类型,属于数组的一种,可以为数组中每一个位置元素指定一个类型
  16. let arr:[number, string, string] = [12, "abc","123"];
  1. // 枚举类型
  2. // 枚举类型中间没有等号
  3. enum Flag {success = 1, error = 2};
  4. // 如果定义一个数字枚举,第一个成员初始化为1,其余成员会自动从1开始增长
  5. enum Direction {
  6. Up = 1, // 如果不指定Up初始化值,则 Up的值为0,Down为1
  7. Down, // Up = 1时,Down会自动变成2
  8. Left,
  9. Right
  10. }
  11. // 使用
  12. let s:Flag = Flag.success;
  13. console.log(s); // 输出1
  14. // 如果枚举的标识符没有赋值,打印出来的为前一个的值加1。如果第一项没有值,则第一项值默认为0
  15. enum Color {blue, red, yellow = 3, green, 'white'};
  16. console.log(Color.blue); // 0
  17. console.log(Color.red); // 1
  18. console.log(Color.yellow); // 3
  19. console.log(Color.green); // 4
  20. console.log(Color.white); // 5
  1. // null和undefined 是其他数据类型(never类型)的子类型
  2. // 定义为具体类型的变量,不能为undefined,即不能不初始化一个值。但是定义为undefined类型的变量可以不进行初始化
  3. // 所以可以将变量定义为 具体类型变量 或 undefined类型
  4. var num: number | undefined | null ; // 此时num即可以为空,也可以赋数字的值
  5. // 类似的,一个变量可以定义为多种类型
  6. var a:number | string = 123;
  7. a = 'abc';
  1. // void类型: 表示没有任何类型,一般用于定义方法的时候没有返回值
  2. function run():void{
  3. console.log('run');
  4. }
  5. // 声明一个void类型的变量没有什么作用,因为它只能被赋予undefined和null
  6. let unusable: void = undefined;
  1. // undefined和null类型本身的类型用处不是很大
  2. // never类型: 是其他类型(包括null和undefined)的子类型,代表从不会出现的值,就是说可以把null和undefined赋值给number、string等类型的变量。然而一旦指定了 --strictNullChecks标记,null和undefined就只能赋值给void和它们各自,想给string传入一个null或undefined时需要指定联合类型: string | null | undefined
  3. // 这意味着声明never的变量只能被never类型所赋值
  4. // undefined只能赋值undefined,null只能赋值null
  5. var a:undefined;
  6. a = undefined;
  7. var b:null;
  8. b = null;
  9. // never表示从不会出现的值,例如throw一个错误
  10. // never类型是任何类型的子类型,可以赋值给任何类型
  11. // 没有类型是never类型的子类型或赋值给never类型(除了never本身)
  12. // 一般情况下用不到
  13. // 返回never的函数必须存在无法到达的终点:例如抛出异常、死循环
  14. var c:never;
  15. c = (() =>{
  16. throw new Error('错误');
  17. })();
  18. function infiniteLoop():never {
  19. while(true){
  20. }
  21. }

类型断言

当自己知道某个变量的类型时,可以通过类型断言这种方式告诉编译器。类型断言好比其他语言中的类型转换,但是不进行特殊的数据检查和结构,它没有运行时影响,只在编译阶段起作用。

  • 使用尖括号进行类型断言
    1. let someValue: any = 'I konw this is a string';
    2. let strLength: number = (<string>someValue).length; // 使用尖括号断言someValue为string类型
  • 使用as进行断言
    1. let someValue: any = 'I konw this is a string';
    2. let strLength: number = (someValue as string).length; // 使用as语法断言someValue为string类型
  • 使用感叹号后缀去除类型中的null和undefined ```typescript // indetifier! 从identifier类型中去除null和undefined

function fixed(name: string | null): string { //本例使用了嵌套函数,因为编译器无法去除嵌套函数的null(除非是立即调用的函数表达式)。 因为它无法跟踪所有对嵌套函数的调用,尤其是你将内层函数做为外层函数的返回值。 如果无法知道函数在哪里被调用,就无法知道调用时 name的类型。 function postfix(epithet: string) { return name!.charAt(0) + ‘. the ‘ + epithet; // ok } name = name || “Bob”; return postfix(“great”); }

  1. -
  2. 使用js的(+)操作符把字符串转换成数字
  3. ```typescript
  4. let a: string = '123';
  5. let b: number = +a; // 使用加号将字符串转换为数字

交叉类型

交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。 例如, Person & Serializable & Loggable同时是 Person Serializable Loggable。 就是说这个类型的对象同时拥有了这三种类型的成员

联合类型

联合类型与交叉类型很有关联,但是使用上却完全不同。 偶尔你会遇到这种情况,一个代码库希望传入 numberstring类型的参数。

  1. // 联合类型表示一个值可以是几种类型之一。 我们用竖线( |)分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean。
  2. function padLeft(value: string, padding: string | number) {
  3. // ...
  4. }

类型保护

  • typeof类型保护

    这些typeof类型保护只有两种形式能被识别: typeof v === "typename"typeof v !== "typename""typename"必须是 "number""string""boolean""symbol"。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。

  1. if (typeof padding === "number") {
  2. // ....
  3. }
  • instanceof类型保护

    instanceof类型保护是通过构造函数来细化类型的一种方式

  1. if (padder instanceof SpaceRepeatingPadder) {
  2. // ....
  3. }

类型别名

给类型起一个新的名字

  1. type Name = string;
  2. type NameResolver = () => string;
  3. type NameOrResolver = Name | NameResolver; // 联合类型
  4. type Container<T> = { value: T }; // 泛型
  5. type Easing = "ease-in" | "ease-out" | "ease-in-out"; // 字面量类型
  6. // 类型别名中可以使用自己
  7. type Tree<T> = {
  8. value: T;
  9. left: Tree<T>;
  10. right: Tree<T>;
  11. }
  12. // 错误用法:type Yikes = Array<Yikes>;

类别名与交叉类型一起使用:

  1. type LinkedList<T> = T & { next: LinkedList<T> };
  2. interface Person {
  3. name: string;
  4. }
  5. var people: LinkedList<Person>;
  6. var s = people.name;
  7. var s = people.next.name;
  8. var s = people.next.next.name;
  9. var s = people.next.next.next.name;