# 2. 基础类型

ts常用类型及基本概念

# 基本数据类型

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

# boolean

let isOk: boolean = false

let createdBoolean: boolean = new Boolean(1) // Error
// typeof new Boolean(1)  is 'object'
// typeof Boolean(false) is 'boolean'

// 类似的可以new的还有 String, Number
// Symbol、BigInt 没有new 构造函数

# number

let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// ES6 中的二进制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的八进制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;

// 编译后,不同的是 二进制、八进制 会被编译为10进制
// let 也会转为 var
var decLiteral = 6;
var hexLiteral = 0xf00d;
// ES6 中的二进制表示法
var binaryLiteral = 10;
// ES6 中的八进制表示法
var octalLiteral = 484;
var notANumber = NaN;
var infinityNumber = Infinity;

# string

let name: string = 'Tom'
let str: string = `Hello, ${name}`

// tsc 编译后
var namestr = 'Tom';
var str = "Hello, " + namestr;

# null 与 undefined

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

let u: undefined = undefined
let n: null = null
let num2: string = null

// 转换后
var u = undefined
var n = null
var num2 = null

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

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

ts有两种方式定义数组:

# 元素类型后面接上[]

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

# 使用数组泛型

uses a generic array type, Array<elemType>

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

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

# 元组 tuple

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

// Declare a tuple type 声明一个元组类型
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly 错误的初始化
x = [10, 'hello']; // Error

// 当访问越界的元素,会使用联合类型代替(后面后讲到)
x[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型

console.log(x[5].toString()); // OK, 'string' 和 'number' 都有 toString

x[6] = true; // Error, 布尔不是(string | number)类型

# 枚举 enum

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

enum Color {Red, Green, Blue} // 默认从0开始为元素编号
let c: Color = Color.Green;  // 获取该枚举的索引值
let colorName: string = Color[2]; // 获取枚举字符串
console.log(c, colorName) // 1 'Blue'

// 编译为
var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
    Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {})); // 默认从0开始为元素编号
var c = Color.Green;
var colorName = Color[2];
console.log(c, colorName);

// 可以改变开始索引
enum Color {Red = 1, Green, Blue} 
let c: Color = Color.Green;

// 也可以全部索引手动赋值
enum Color { Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green

# any 任意值

let notSure: any = 4
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

// 数组元素类型为any
let list: any[] = [1, true, "free"];

list[1] = 100;

# void 空值

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

function alertName(): void {
  alert('My name is Tom')
}
// 单独声明一个void类型没有什么用处,只能赋值为 undefined或null
let unusable: void = undefined
unusable = null; // OK if `--strictNullChecks` is not given

let u: void = undefined
let num: number = u // Error

# never

never类型

  • 总是会抛出异常
  • 根本就不会有返回值的函数表达式
  • 箭头函数表达式的返回值类型
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
  throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
  return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
  while (true) {
  }
}

# object

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

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

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

# 类型断言(Type assertions)

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

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

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

# “angle-bracket” syntax ('尖括号'语法)

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

# as syntax(as语法)

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;

# 关于let

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

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

# 类型推论

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

let testNumber = 'six'  // 这里会根据值的类型,推断出testNumber为string
testNumber = 6 // Error

// 声明时不赋值
let testNumber; // 等价于 let testNumber: any
testNumber = 'six'
testNumber = 6

# 联合类型(Union Types)

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

let myNumber: string | number
myNumber = 'six'
myNumber = 6

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

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


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

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

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

let myNumber = myNumber: string | number
myNumber = 'six' // myNumber被推断为 string 类型
console.log(myNumber.length) // OK
myNumber = 6 // myNumber被推断为 number 类型
console.log(myNumber.length) // Error
上次更新: 2022/12/19 02:18:42