基础
TS
是JS
的超集,可以使用JS
中所有的特性,并在此基础上对JS
进行增强。TS
提供了和JS
一一对应的数据类型。
基础使用
类型注解
类型注解指的是显式指定变量的类型。
// 在变量声明后紧接着类型定义,用冒号隔开
let count: number = 0;
类型推断
由TS
根据上下文内容推断变量的类型。
// TS 推导出来slogan的类型是string
let slogan = "披金成王,伴坤远航";
// 用const定义的基础数据类型为字面量类型
// TS 推导idol的类型为字面量类型——kun
const idol = "kun";
通用类型和字面量类型
let
定义的原始数据类型是通用数据类型,比如string
、number
一类。const
定义的原始数据类型的TS
类型是字面量类型。
原始类型
boolean
布尔类型
let bool: boolean = true;
string
字符串类型
let str: string = "hello";
number
数字类型,不区分浮点、整数
let num: number = 123;
symbol
Symbol
类型,不可变且唯一的类型
let sym: symbol = Symbol("key");
null & undefined
let n: null = null;
let u1: undefined = undefined;
// undefined也可以用void 0来表示
let u2: undefined = void 0;
bigint
高精度整数类型,用于处理超过JS
数字范围的整数
let bigInt: bigint = 12345123456789012345678901234567890n;
对象类型
除基础类型外的类型,引用类型包括有数组、对象、函数。
object
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create([]); // OK 因为数组也是object类型的一种
create(null); // OK
create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error
WARNING
在开发中不推荐标注为object
,因为它表示一个任意对象,就像上面代码中给它一个空数组的值也不会报错,推荐标注明确的类型,但在这里可以为Object.create
类似的API
标注。
array 数组
const numArr: number[] = [1,2,3,4]
numArr.push(5) // OK
numArr.push("a") // Error 只允许存储number类型
tuple 元组
特殊的数组类型,表示一个固定长度的数组,并且已知每一项对应的类型。
当对元组类型的数据进行越界访问
或分配错误的类型值
时,TS
会报错。
const tuple: [string, number] = ["abc", 123]
tuple[0] = "hello" // OK
tuple[2] // Error
tuple[1] = false // Error
function 函数
定义函数的方式有三种:
- 函数声明
- 箭头函数
- 函数表达式
/* 函数声明 */
function fn1() {}
/* 函数表达式 */
const fn2 = function () {};
/* 箭头函数 */
const fn3 = () => {};
特殊类型
enum 枚举
将一组可能出现的常量值,挨个列举出来定义在一个类型中,可以是字符串、数字、布尔类型。
enum Direction{
UP,
DOWN,
LEFT,
RIGHT
}
let upDir: Direction.UP;
枚举值默认从0
开始递增,也可以给枚举值赋值
enum {
UP = "UP",
DOWN = "DOWN",
LEFT = "LEFT",
RIGHT = "RIGHT"
}
如果只想给其中一个枚举赋值,这个赋值的枚举必须出现在最后一位
// Error 枚举成员必须具有初始化表达式
enum Direction{
UP = "UP",
DOWN,
LEFT,
RIGHT = "RIGHT"
}
// Error 枚举成员必须具有初始化表达式
enum Direction{
UP = "UP",
DOWN,
LEFT,
RIGHT
}
// OK
enum Direction{
UP , // 0
DOWN, // 1
LEFT, // 2
RIGHT = "RIGHT"
}
枚举类型会参与JS
编译后的代码:
var Direction;
(function (Direction) {
Direction[Direction["UP"] = 0] = "UP";
Direction[Direction["DOWN"] = 1] = "DOWN";
Direction[Direction["LEFT"] = 2] = "LEFT";
Direction["RIGHT"] = "RIGHT";
})(Direction || (Direction = {}));
根据枚举会默认从0
开始递增赋默认值,我们可以正向获取枚举的值,也能反向获取枚举的键
console.log(Direction[0]); // UP
console.log(Direction.UP); // 0
any
任意值,当一个值是any
时,TS
不会对它进行类型检查
let notSure: any = 4;
notSure = "maybe a string instead";
DANGER
- 在
TS
中,所有类型都可以视为是any
的子类,如果不指定变量的类型同时TS
自动推导不出类型的类型会被归类为any
。 - 默认推荐为每一个数据标注类型,实在确定不了类型的情况下才使用
any
,因为它会使TS
失去准确的类型推断能力。
unknown
表示描述一个类型不确定的变量,除any
外的第二顶级类型
- 范围大的类型可以给范围小的类型赋值,反过来则不可以,比如
let n: unknown = "hello";
。 - 在
unknown
类型的值做的任何操作都是非法的,比如new
、方法等。 unknown
在操作前需要对类型进行检查。
let n1: unknown;
let n2: string;
n1 = "abc"; // OK
n2 = n1; // Error,不能将unknown的类型赋值给string类型
n1.split(""); // Error,不能调用unknown类型的值的方法
if (typeof n1 === "string") {
n1.split(""); // OK,在操作之前,先判断类型
}
void
表示没有返回值的函数或值是undefined
的变量
const foo = () => {}
// foo: ()=> void
let bar: void
bar = undefined
// void 0 也可以表示为 undefined 的意思
bar = void 0
never
never
表示永远不会发生值的类型,包括undefined
。开发中很少有用它的场景,在类型体操的时候可能会用上。
never
代表空集。- 常用于用于校验 "类型收窄" 是否符合预期,就是写出类型绝对安全的代码。
never
常被用来作 "类型兜底"。
function handleValue(val: "foo") {
switch (val) {
case 'foo':
// 这里 val 被收窄为 foo
break
default:
// val 在这里是 never
const exhaustiveCheck: never = val
break
}
}
字面量类型
字面量类型使用具体的值作为类型,这种类型会将变量的值或参数的值严格限制为指定的字面量值。
有数字、字符串、布尔类型三种字面量类型。
const msg = "success" // msg => "success"
const num = 1 // num => 1
常和联合类型结合使用形成枚举的用法,表示变量只能取多个固定值的其中之一。
type Status = "success" | "error" | "pending";
let currentStatus: Status = "success"; // 只能赋值这三个字符串
currentStatus = "unknown"; // ❌ Error 编译错误
在定义变量时是通用类型,但在某些场景下会不适用,可以使用as const
将变量的通用类型转成字面量类型
declare function request(url:string, method:"get" | "post"): Promise
let params = {
url: "http://api.com",
method: "get"
}
request(params) // Error 类型“string”的参数不能赋给类型“"get" | "post"”的参数
// => 给params参数转成字面量类型后通过校验
params = params as const
request(params)