Skip to content

1-基础类型

参考珠峰笔记:珠峰架构师成长计划 (zhufengpeixun.com)

TypeScript 支持与 JavaScript 几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。

typescript 日常类型文档https://www.typescriptlang.org/docs/handbook/2/everyday-types.html

一、JavaScript 原始数据类型

JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)

所有的原始数据类型都没有属性(property)

  • Boolean:布尔类型
  • Number:数值类型
  • String:字符串类型
  • Null:空值类型
  • Undefined:未定义类型
  • Symbol:唯一值类型

包装对象

typescript
let name = "zhufeng";
console.log(name.toUpperCase());

console.log(new String("zhufeng").toUpperCase());

当调用基本数据类型方法的时候,JavaScript 会在原始数据类型和对象类型之间做一个迅速的强制性切换

typescript
let isOK: boolean = true; // 编译通过
let isOK: boolean = Boolean(1) // 编译通过
let isOK: boolean = new Boolean(1); // 编译失败   期望的 isOK 是一个原始数据类型

let name5: string | number;
name5 = 'zhufeng';
name5.toLowerCase();
name5 = 5:
name5.toFixed(3);

object 对象类型

object 表示非原始类型,也就是除 numberstringboolean之外的类型。

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

typescript
function fn2(obj: object): object {
	console.log("fn2()", obj);
	return {};
	// return undefined
	// return null
}
console.log(fn2(new String("abc")));
// console.log(fn2('abc') // error
console.log(fn2(String));

二、TypeScript 数据类型注解

布尔值类型(boolean)

最基本的数据类型就是简单的 true/false 值,在 JavaScript 和 TypeScript 里叫做 boolean(其它语言中也一样)。

typescript
let isDone: boolean = false;
isDone = true;
// isDone = 2 // error

数字类型(number)

和 JavaScript 一样,TypeScript 里的所有数字都是浮点数。 这些浮点数的类型是 number。 除了支持十进制和十六进制字面量,TypeScript 还支持 ECMAScript 2015 中引入的二进制和八进制字面量。

typescript
let a1: number = 10; // 十进制
let a2: number = 0b1010; // 二进制
let a3: number = 0o12; // 八进制
let a4: number = 0xa; // 十六进制
// 可以赋值undefined和null

字符串类型(string)

JavaScript 程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样,我们使用 string 表示文本数据类型。 和 JavaScript 一样,可以使用双引号(")或单引号(')表示字符串。

typescript
let name: string = "tom";
name = "jack";
// name = 12 // error
let age: number = 12;
const info = `My name is ${name}, I am ${age} years old!`;

undefined 和 null

TypeScript 里,undefinednull 两者各自有自己的类型分别叫做 undefinednull。 它们的本身的类型用处不是很大:

typescript
let u: undefined = undefined;
let n: null = null;

默认情况下 nullundefined 是所有类型的子类型。 就是说你可以把 nullundefined 赋值给 number 类型的变量。

数组类型(array)

TypeScript 像 JavaScript 一样可以操作数组元素。 有两种方式可以定义数组。

第一种,可以在元素类型后面接上[],表示由此类型元素组成的一个数组:

typescript
let list1: number[] = [1, 2, 3];

第二种方式是使用数组泛型,Array<元素类型>

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

数组里面的对象定义

typescript
interface Person2 {
	// 索引访问操作符 我们可以通过[]来获取一个类型的子类型
	name: string;
	age: number;
	job: {
		name: string;
	};
	// 数组里面的对象类型
	interests: { name: string; level: number }[];
	// interests: Array<name: string; level: number>
}

let myname: Person2["job"]["name"] = "fe";
let mylevel: Person2["interests"][o]["level"] = 10; // 赋值数组里的对象属性

元组(tuple)

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 stringnumber 类型的元组。

typescript
let t1: [string, number];
t1 = ["hello", 10]; // OK
t1 = [10, "hello"]; // Error

当访问一个已知索引的元素,会得到正确的类型:

typescript
console.log(t1[0].substring(1)); // OK
console.log(t1[1].substring(1)); // Error, 'number' 不存在 'substring' 方法

枚举类型(enum)

  • 事先考虑某一个变量的所有的可能的值,尽量用自然语言中的单词表示它的每一个值
  • 比如性别、月份、星期、颜色、单位、学历

普通枚举

typescript
enum Gender {
	GIRL,
	BOY,
}
console.log(`李雷是${Gender.BOY}`);
console.log(`韩梅梅是${Gender.GIRL}`);

enum Week {
	MONDAY = 1,
	TUESDAY = 2,
}
console.log(`今天是星期${Week.MONDAY}`);

常数枚举

  • 常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员。
  • 假如包含了计算成员,则会在编译阶段报错
typescript
const enum Colors {
	Red,
	Yellow,
	Blue,
}

let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];
const enum Color {
	Red,
	Yellow,
	Blue = "blue".length,
}

enum 类型是对 JavaScript 标准数据类型的一个补充。 使用枚举类型可以为一组数值赋予友好的名字

typescript
enum Color {
	Red,
	Green,
	Blue,
}

// 枚举数值默认从0开始依次递增
// 根据特定的名称得到对应的枚举数值
let myColor: Color = Color.Green; // 0
console.log(myColor, Color.Red, Color.Blue);

默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1 开始编号:

typescript
enum Color {
	Red = 1,
	Green,
	Blue,
}
let c: Color = Color.Green;

或者,全部都采用手动赋值:

typescript
enum Color {
	Red = 1,
	Green = 2,
	Blue = 4,
}
let c: Color = Color.Green;

枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为 2,但是不确定它映射到 Color 里的哪个名字,我们可以查找相应的名字:

typescript
enum Color {
	Red = 1,
	Green,
	Blue,
}
let colorName: string = Color[2];

console.log(colorName); // 'Green'

任意类型(any)

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量:

typescript
let notSure: any = 4;
notSure = "maybe a string";
notSure = false; // 也可以是个 boolean

在对现有代码进行改写的时候,any 类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。并且当你只知道一部分数据的类型时,any 类型也是有用的。 比如,你有一个数组,它包含了不同的类型的数据:

typescript
let list: any[] = [1, true, "free"];

list[1] = 100;

void 类型 - 空的,没有的

某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型

当一个函数没有返回值时,你通常会见到其返回值类型是 void

typescript
/* 表示没有任何类型, 一般用来说明函数的返回值不能是undefined和null之外的值 */
function fn(): void {
	console.log("fn()");
	// return undefined
	// return null
	// return 1 // error
}

声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefinednull

在 typescript.typescripton 配置中的strictNullChecks 选项,配置返回 null 是否报错,true 就报错

typescript
let unusable: void = undefined;

never 类型

never 是其它类型(null undefined)的子类型,代表不会出现的值

  • 作为不会返回( return )的函数的返回值类型
typescript
// 返回never的函数 必须存在 无法达到( unreachable ) 的终点
function error(message: string): never {
	throw new Error(message);
}
let result1 = error("hello");
// 由类型推论得到返回值为 never
function fail() {
	return error("Something failed");
}
let result = fail();

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

strictNullChecks

  • 在 TS 中, null 和 undefined 是任何类型的有效值,所以无法正确地检测它们是否被错误地使用。于是 TS 引入了 --strictNullChecks 这一种检查模式
  • 由于引入了 --strictNullChecks ,在这一模式下,null 和 undefined 能被检测到。所以 TS 需要一种新的底部类型( bottom type )。所以就引入了 never。
typescript
// Compiled with --strictNullChecks
function fn(x: number | string) {
	if (typeof x === "number") {
		// x: number 类型
	} else if (typeof x === "string") {
		// x: string 类型
	} else {
		// x: never 类型
		// --strictNullChecks 模式下,这里的代码将不会被执行,x 无法被观察
	}
}

never 和 void 的区别

  • void 可以被赋值为 null 和 undefined 的类型。 never 则是一个不包含值的类型。
  • 拥有 void 返回值类型的函数能正常运行。拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。

Symbol

  • 我们在使用 Symbol 的时候,必须添加 es6 的编译辅助库
  • Symbol 是在 ES2015 之后成为新的原始类型,它通过 Symbol 构造函数创建
  • Symbol 的值是唯一不变的
typescript
const sym1 = Symbol("key");
const sym2 = Symbol("key");
Symbol("key") === Symbol("key"); // false

BigInt

  • 使用 BigInt 可以安全地存储和操作大整数
  • 我们在使用 BigInt 的时候,必须添加 ESNext 的编译辅助库
  • 要使用1n需要 "target": "ESNext"
  • number 和 BigInt 类型不一样,不兼容
typescript
const max = Number.MAX_SAFE_INTEGER; // 2**53-1
console.log(max + 1 === max + 2);
const max = BigInt(Number.MAX_SAFE_INTEGER);
console.log(max + 1n === max + 2n);
let foo: number;
let bar: bigint;
foo = bar;
bar = foo;

联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种

需求 1:定义一个一个函数得到一个数字或字符串值的字符串形式值

typescript
function toString2(x: number | string): string {
	return x.toString();
}

需求 2:定义一个一个函数得到一个数字或字符串值的长度

typescript
function getLength(x: number | string) {
	// return x.length // error

	if (x.length) {
		// error
		return x.length;
	} else {
		return x.toString().length;
	}
}

交叉类型

typescript
type Obj1 = { username: string }
type Obj2 = { age: number }
let obj1: 0bj1 = { username: "abc" }
let obj2: 0bj2 = { age: 23 }
let obj3: 0bj1 & 0bj2 = { username: "wangwu", age: 40 }

字面量类型和类型字面量

  • 字面量类型的要和实际的值的字面量一一对应,如果不一致就会报错
  • 类型字面量和对象字面量的语法很相似
typescript
const up: "Up" = "Up";
const down: "Down" = "Down";
const left: "Left" = "Left";
const right: "Right" = "Right";

type Direction = "Up" | "Down" | "Left" | "Right";

function move(direction: Direction) {}
move("Up");

type Person = {
	name: string;
	age: number;
};

字符串字面量 vs 联合类型

  • 字符串字面量类型 用来约束取值只能是某几个字符串中的一个;联合类型(Union Types)表示取值可以为 多种类型 中的一种
  • 字符串字面量 限定了使用该字面量的地方仅接受特定的值;联合类型 对于值并没有限定,仅仅限定值的类型需要保持一致

TypeScript 类型断言

通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。

类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。

它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你,程序员,已经进行了必须的检查。

类型断言有两种形式。 其一是“尖括号”<>语法,另一个为 as 语法

typescript
/*
类型断言(Type Assertion): 可以用来手动指定一个值的类型
语法:
    方式一: <类型>值
    方式二: 值 as 类型  tsx中只能用这种方式
*/

/* 需求: 定义一个函数得到一个字符串或者数值数据的长度 */
function getLength(x: number | string) {
	if ((<string>x).length) {
		return (x as string).length;
	} else {
		return x.toString().length;
	}
}
console.log(getLength("abcd"), getLength(1234));

!非空断言

typescript
// 直接!非空断言
let root: HTMLElement | null = document.getElementById("root");
root!.style.color = "red"; // !感叹号为非空断言

TypeScript 类型推断|推导

类型推断: TS 会在没有明确的指定类型的时候推测出一个类型 有下面 2 种情况: 1. 定义变量时赋值了, 推断为对应的类型. 2. 定义变量时没有赋值, 推断为 any 类型

typescript
/* 定义变量时赋值了, 推断为对应的类型 */
let b9 = 123; // number
// b9 = 'abc' // error

/* 定义变量时没有赋值, 推断为any类型 */
let b10; // any类型
b10 = 123;
b10 = "abc";

总结:总共 24 种类型

基本类型

number,string,boolean,symbol,null,undefined

根类型

Object,{}

对象类型

Array,object,function

枚举

enum

其他特殊类型

any,unknown,never,void,元组 ( tuple) ,可变元组

合成类型

联合类型,交叉类型

字面量数据类型

Released under the MIT License.