ts常用类型及基本概念

基本数据类型

js 类型分两种,基本数据类型(primitive data types)和对象类型(object types), 这里除了介绍js的5中基本数据类型外,还将介绍ts新增的void, any 等 , (js新增的两种基本类型 symbol (ES2015), bigint (ES2019) 这里暂不介绍)

boolean

  1. let isOk: boolean = false
  2. let createdBoolean: boolean = new Boolean(1) // Error
  3. // typeof new Boolean(1) is 'object'
  4. // typeof Boolean(false) is 'boolean'
  5. // 类似的可以new的还有 String, Number
  6. // Symbol、BigInt 没有new 构造函数

number

  1. let decLiteral: number = 6;
  2. let hexLiteral: number = 0xf00d;
  3. // ES6 中的二进制表示法
  4. let binaryLiteral: number = 0b1010;
  5. // ES6 中的八进制表示法
  6. let octalLiteral: number = 0o744;
  7. let notANumber: number = NaN;
  8. let infinityNumber: number = Infinity;
  9. // 编译后,不同的是 二进制、八进制 会被编译为10进制
  10. // let 也会转为 var
  11. var decLiteral = 6;
  12. var hexLiteral = 0xf00d;
  13. // ES6 中的二进制表示法
  14. var binaryLiteral = 10;
  15. // ES6 中的八进制表示法
  16. var octalLiteral = 484;
  17. var notANumber = NaN;
  18. var infinityNumber = Infinity;

string

  1. let name: string = 'Tom'
  2. let str: string = `Hello, ${name}`
  3. // tsc 编译后
  4. var namestr = 'Tom';
  5. var str = "Hello, " + namestr;

null 与 undefined

默认情况下,null 和 undefined是所有类型的子类型,也就是可以将null或undefined赋值给number、string等类型的变量

  1. let u: undefined = undefined
  2. let n: null = null
  3. let num2: string = null
  4. // 转换后
  5. var u = undefined
  6. var n = null
  7. var num2 = null

然而,当你指定了—strictNullChecks标记,null和undefined只能赋值给void和它们各自。 这能避免很多常见的问题。 也许在某处你想传入一个string或null或undefined,你可以使用联合类型string | null | undefined。 再次说明,稍后我们会介绍联合类型。 注意:我们鼓励尽可能地使用—strictNullChecks,但在本手册里我们假设这个标记是关闭的。

数组: Array<类型> 或 类型[]

ts有两种方式定义数组:

元素类型后面接上[]

  1. let list: number[] = [1, 2, 3]
  2. // var list = [1, 2, 3];

使用数组泛型

uses a generic array type, Array

泛型(Generic)所操作的数据类型被指定为一个参数

  1. let list2: Array<number> = [1, 2, 3]
  2. // var list2 = [1, 2, 3];

元组 tuple

tuple,也是一个数组,且已知数组长度,以及每个元素的类型,每个元素类型可以不一致

  1. // Declare a tuple type 声明一个元组类型
  2. let x: [string, number];
  3. // Initialize it
  4. x = ['hello', 10]; // OK
  5. // Initialize it incorrectly 错误的初始化
  6. x = [10, 'hello']; // Error
  7. // 当访问越界的元素,会使用联合类型代替(后面后讲到)
  8. x[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型
  9. console.log(x[5].toString()); // OK, 'string' 和 'number' 都有 toString
  10. x[6] = true; // Error, 布尔不是(string | number)类型

枚举 enum

枚举类型可以为一组数值赋予友好的名字

  1. enum Color {Red, Green, Blue} // 默认从0开始为元素编号
  2. let c: Color = Color.Green; // 获取该枚举的索引值
  3. let colorName: string = Color[2]; // 获取枚举字符串
  4. console.log(c, colorName) // 1 'Blue'
  5. // 编译为
  6. var Color;
  7. (function (Color) {
  8. Color[Color["Red"] = 0] = "Red";
  9. Color[Color["Green"] = 1] = "Green";
  10. Color[Color["Blue"] = 2] = "Blue";
  11. })(Color || (Color = {})); // 默认从0开始为元素编号
  12. var c = Color.Green;
  13. var colorName = Color[2];
  14. console.log(c, colorName);
  15. // 可以改变开始索引
  16. enum Color {Red = 1, Green, Blue}
  17. let c: Color = Color.Green;
  18. // 也可以全部索引手动赋值
  19. enum Color { Red = 1, Green = 2, Blue = 4}
  20. let c: Color = Color.Green

any 任意值

  1. let notSure: any = 4
  2. notSure = "maybe a string instead";
  3. notSure = false; // okay, definitely a boolean
  4. // 数组元素类型为any
  5. let list: any[] = [1, true, "free"];
  6. list[1] = 100;

void 空值

与any类型相反,它表示没有任何类型。一般用于没有任何返回值的函数,void类型只能赋值为 null 或undefined,不能将void类型的值赋值给 number 等

  1. function alertName(): void {
  2. alert('My name is Tom')
  3. }
  4. // 单独声明一个void类型没有什么用处,只能赋值为 undefined或null
  5. let unusable: void = undefined
  6. unusable = null; // OK if `--strictNullChecks` is not given
  7. let u: void = undefined
  8. let num: number = u // Error

never

never类型

  • 总是会抛出异常
  • 根本就不会有返回值的函数表达式
  • 箭头函数表达式的返回值类型
  1. // 返回never的函数必须存在无法达到的终点
  2. function error(message: string): never {
  3. throw new Error(message);
  4. }
  5. // 推断的返回值类型为never
  6. function fail() {
  7. return error("Something failed");
  8. }
  9. // 返回never的函数必须存在无法达到的终点
  10. function infiniteLoop(): never {
  11. while (true) {
  12. }
  13. }

object

object表示非原始类型,也就是除number,string,boolean,symbol,bigint, null或undefined之外的类型。

使用object类型,就可以更好的表示像Object.create这样的API。例如:

  1. declare function create(o: object | null): void;
  2. create({ prop: 0 }); // OK
  3. create(null); // OK
  4. create(42); // Error
  5. create("string"); // Error
  6. create(false); // Error
  7. create(undefined); // Error

类型断言(Type assertions)

通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。

一句话解释:手动指定一个值的类型。

Type assertions have two forms. 当在TypeScript里使用JSX时,只有as语法断言是被允许的。

“angle-bracket” syntax (‘尖括号’语法)

  1. let someValue: any = 'this is a string'
  2. let strLength: number = (<string>someValue).length

as syntax(as语法)

  1. let someValue: any = "this is a string";
  2. let strLength: number = (someValue as string).length;

关于let

不推荐使用var, 很多常见的问题都可以通过使用let来解决, 尽可能地使用let来代替var

ts官网用了一个章节(变量声明)来讲let和var,这些是js基础,所以这里不讨论,可以参考: TypeScript - Variable Declarations

类型推论

声明变量时如果没有指定类型,那ts会依照类型推论(Type Inference)的规则来推断出一个类型,如果声明时没有赋值,不管之后有没有赋值,都会被推断为 any类型

  1. let testNumber = 'six' // 这里会根据值的类型,推断出testNumber为string
  2. testNumber = 6 // Error
  3. // 声明时不赋值
  4. let testNumber; // 等价于 let testNumber: any
  5. testNumber = 'six'
  6. testNumber = 6

联合类型(Union Types)

联合类型,表示值可以为多种类型中的一种,以 | 分隔

  1. let myNumber: string | number
  2. myNumber = 'six'
  3. myNumber = 6

访问联合类型的属性和方法

当不确定联合类型到底是哪个类型时,只能访问此联合类型的所有类型里共有的属性或方法

  1. function fun(myNumber: string | number): number {
  2. console.log(myNumber.length) // Error
  3. console.log(myNumber.toString()) // OK
  4. }

联合类型的变量赋值时类型推断

联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型

  1. let myNumber = myNumber: string | number
  2. myNumber = 'six' // myNumber被推断为 string 类型
  3. console.log(myNumber.length) // OK
  4. myNumber = 6 // myNumber被推断为 number 类型
  5. console.log(myNumber.length) // Error