切换模式
TypeScript 类型声明
ts 中的数据类型
- 布尔类型(boolean)
- 数字类型(number)
- 字符串类型(string)
- 数组类型(array)
- 元组类型(tuple):属于数组的一种
- 枚举类型(enum)
- 任意类型(any)
- null 和 undefined
- void类型
- never类型
布尔类型(boolean)
ts
let flag:boolean = true;
flag = 123; // 错误,不能将number类型的值赋给boolean类型的变量
flag = false; // 正确,将boolean类型的值赋给boolean类型的变量
let flag:boolean = true;
flag = 123; // 错误,不能将number类型的值赋给boolean类型的变量
flag = false; // 正确,将boolean类型的值赋给boolean类型的变量
数字类型(number)
ts
let num:number = 123;
num = "123"; // 错误,不能将string类型的值赋给number类型的变量
num = 123; // 正确,将number类型的值赋给number类型的变量
let num:number = 123;
num = "123"; // 错误,不能将string类型的值赋给number类型的变量
num = 123; // 正确,将number类型的值赋给number类型的变量
字符串类型(string)
ts
let str:string = "hello";
str = 123; // 错误,不能将number类型的值赋给string类型的变量
str = "world"; // 正确,将string类型的值赋给string类型的变量
let str:string = "hello";
str = 123; // 错误,不能将number类型的值赋给string类型的变量
str = "world"; // 正确,将string类型的值赋给string类型的变量
数组类型(array)
ts
let arr:number[] = [1, 2, 3]; // 数字数组
let arr:string[] = ["a", "b", "c"]; // 字符串数组
let arr:any[] = [1, "a", true]; // 任意类型数组,可以包含不同类型的元素
let arr:Array<number> = [1, 2, 3]; // 泛型数组,可以包含数字类型的元素
let arr:Array<string> = ["a", "b", "c"]; // 泛型数组,可以包含字符串类型的元素
let arr:Array<any> = [1, "a", true]; // 泛型数组,可以包含任意类型的元素
let arr:number[] = [1, 2, 3]; // 数字数组
let arr:string[] = ["a", "b", "c"]; // 字符串数组
let arr:any[] = [1, "a", true]; // 任意类型数组,可以包含不同类型的元素
let arr:Array<number> = [1, 2, 3]; // 泛型数组,可以包含数字类型的元素
let arr:Array<string> = ["a", "b", "c"]; // 泛型数组,可以包含字符串类型的元素
let arr:Array<any> = [1, "a", true]; // 泛型数组,可以包含任意类型的元素
元组类型(tuple)
ts
let tuple:[string, number] = ["hello", 123]; // 包含字符串和数字的元组类型
tuple = ["world", 456]; // 正确,将包含字符串和数字的元组类型赋给元组变量tuple
tuple = [123, "hello"]; // 错误,不能将包含数字和字符串的元组类型赋给tuple变量,因为类型不匹配。
tuple = ["hello", 123, true]; // 错误,不能将包含三个元素的元组类型赋给tuple变量,因为长度不匹配。
tuple = ["hello", 123, 456]; // 错误,不能将包含三个元素的元组类型赋给tuple变量,因为类型不匹配。
let tuple:[string, number] = ["hello", 123]; // 包含字符串和数字的元组类型
tuple = ["world", 456]; // 正确,将包含字符串和数字的元组类型赋给元组变量tuple
tuple = [123, "hello"]; // 错误,不能将包含数字和字符串的元组类型赋给tuple变量,因为类型不匹配。
tuple = ["hello", 123, true]; // 错误,不能将包含三个元素的元组类型赋给tuple变量,因为长度不匹配。
tuple = ["hello", 123, 456]; // 错误,不能将包含三个元素的元组类型赋给tuple变量,因为类型不匹配。
枚举类型(enum)
- 基本类型
TIP
枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值
枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个。
ts
// 使用 enum 关键字定义枚举
// 约定枚举名称、枚举中的值以大写字母开头
// 枚举中的多个值之间通过 , (逗号)分隔
enum Direction {
Up,
Down,
Left,
Right,
}
// 定义好枚举后,直接使用枚举名称作为类型注释
// 形参direction的类型为枚举 Direction,那么实参的值应该是枚举 Direction 成员的任意一个。
function changeDirection(direction: Direction){
console.log(direction)
}
// 类似于JS中的对象,枚举直接通过点(.)语法访问枚举的成员。
changeDirection(Direction.Up); // 0
// 我们可以通过枚举的属性来访问枚举成员,和枚举的名字来访问枚举类型
enum Response {
No = 0,
Yes = 1,
}
console.log(Response.No) // 0
console.log(Response.Yes) // 1
// 使用 enum 关键字定义枚举
// 约定枚举名称、枚举中的值以大写字母开头
// 枚举中的多个值之间通过 , (逗号)分隔
enum Direction {
Up,
Down,
Left,
Right,
}
// 定义好枚举后,直接使用枚举名称作为类型注释
// 形参direction的类型为枚举 Direction,那么实参的值应该是枚举 Direction 成员的任意一个。
function changeDirection(direction: Direction){
console.log(direction)
}
// 类似于JS中的对象,枚举直接通过点(.)语法访问枚举的成员。
changeDirection(Direction.Up); // 0
// 我们可以通过枚举的属性来访问枚举成员,和枚举的名字来访问枚举类型
enum Response {
No = 0,
Yes = 1,
}
console.log(Response.No) // 0
console.log(Response.Yes) // 1
- 数字枚举
TIP
数字枚举: 枚举成员的值为数字的枚举
枚举成员是有值的,默认为:从0开始自增的数字
ts
// Up使用默认值为 0。 其余的成员会从 0 开始自动增长
enum Direction2 {
Up, // 此时 Direction.Up = 0
Down, // 此时 Direction.Down= 1
Left, // 此时 Direction.Left= 2
Right, // 此时 Direction.Right= 3
}
const arrayValues2 = Object.values(Direction2)
console.log(arrayValues2) // ['Up','Down','Left','Right', 0, 1, 2, 3]
// Up使用默认值为 0。 其余的成员会从 0 开始自动增长
enum Direction2 {
Up, // 此时 Direction.Up = 0
Down, // 此时 Direction.Down= 1
Left, // 此时 Direction.Left= 2
Right, // 此时 Direction.Right= 3
}
const arrayValues2 = Object.values(Direction2)
console.log(arrayValues2) // ['Up','Down','Left','Right', 0, 1, 2, 3]
数字枚举有自增长的行为,也可以设置他的初始值。
ts
// 设置初始值,Up使用初始化为 1。 其余的成员会从 1 开始自动增长
enum Direction1 {
Up = 1, // 此时 Up = 1
Down, // 此时 Down= 2
Left, // 此时 Left= 3
Right // 此时 Right= 4
}
const arrayValues1 = Object.values(Direction1)
console.log(arrayValues1) // ['Up','Down','Left','Right', 1, 2, 3, 4]
// 设置初始值,Up使用初始化为 1。 其余的成员会从 1 开始自动增长
enum Direction1 {
Up = 1, // 此时 Up = 1
Down, // 此时 Down= 2
Left, // 此时 Left= 3
Right // 此时 Right= 4
}
const arrayValues1 = Object.values(Direction1)
console.log(arrayValues1) // ['Up','Down','Left','Right', 1, 2, 3, 4]
取值问题,如果数字enum通过Object.values取值,会把键值对值都取到(字符串枚举没这个问题)
ts
enum values{
Yes = 1, // 此时 values.Yes = 1
No = 0, // 此时 values.No = 0
}
const arrayValues = Object.values(values)
console.log(arrayValues) // ['Yes','No',1,0]
enum values{
Yes = 1, // 此时 values.Yes = 1
No = 0, // 此时 values.No = 0
}
const arrayValues = Object.values(values)
console.log(arrayValues) // ['Yes','No',1,0]
然而我们要的是他的value值,他的键值我们是不需要的
ts
// 封装一个数字枚举转数组方法
function enum2arr(valueEnum: any[] | Record<string, any>) {
let values = Array.isArray(valueEnum) ? valueEnum : Object.values(valueEnum);
// 如果 enum 值为 number 类型,ts 生成的 js 对象会同时包含枚举的名称,针对该情形需提出枚举名称
const hasNum = values.some((v) => typeof v === 'number');
if (hasNum) {
values = values.filter((v) => typeof v === 'number');
}
return values;
}
enum values{
Yes = 0, // 此时 values.Yes = 1
No = 1, // 此时 values.No = 2
}
const arrayValues = enum2arr(values)
console.log(arrayValues) // [ 1, 2, ]
// 封装一个数字枚举转数组方法
function enum2arr(valueEnum: any[] | Record<string, any>) {
let values = Array.isArray(valueEnum) ? valueEnum : Object.values(valueEnum);
// 如果 enum 值为 number 类型,ts 生成的 js 对象会同时包含枚举的名称,针对该情形需提出枚举名称
const hasNum = values.some((v) => typeof v === 'number');
if (hasNum) {
values = values.filter((v) => typeof v === 'number');
}
return values;
}
enum values{
Yes = 0, // 此时 values.Yes = 1
No = 1, // 此时 values.No = 2
}
const arrayValues = enum2arr(values)
console.log(arrayValues) // [ 1, 2, ]
- 字符串枚举
TIP
字符串枚举:枚举成员的值是字符串
字符串枚举没有自增长的行为,每个成员必须进行初始化(设置值)
ts
// 可以用字符串字面量,或另外一个字符串枚举成员进行初始化
enum Direction {
Up = "up", // 此时 Direction.Up = "up"
Down = "down", // 此时 Direction.Down = "down"
Left = "left", // 此时 Direction.Left = "left"
Right = "right", // 此时 Direction.Right = "right"
}
const arrayValues = Object.values(Direction)
console.log(arrayValues) // ['up','down','left','right']
// 可以用字符串字面量,或另外一个字符串枚举成员进行初始化
enum Direction {
Up = "up", // 此时 Direction.Up = "up"
Down = "down", // 此时 Direction.Down = "down"
Left = "left", // 此时 Direction.Left = "left"
Right = "right", // 此时 Direction.Right = "right"
}
const arrayValues = Object.values(Direction)
console.log(arrayValues) // ['up','down','left','right']
- 异构枚举(不推荐)
TIP
混合字符串和数字成员,但是不建议这样做
ts
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
void类型
void:没有返回值,never 表示不存在的类型
ts
function fn(n:number, str:string): void {
return undefined
return null
return 1 // error 报错
}
function run():undefined{
console.log('run')
}
run(); // 错误,返回值不为 'viod' 或 'any' 必须要返回值
function run():number{
return 123;
}
run();
function fn(n:number, str:string): void {
return undefined
return null
return 1 // error 报错
}
function run():undefined{
console.log('run')
}
run(); // 错误,返回值不为 'viod' 或 'any' 必须要返回值
function run():number{
return 123;
}
run();
never类型
never:表示不存在的类型
ts
function fn(n:number, str:string): never { // 返回值类型为 never,表示不存在的类型,表示函数执行出错,或者无限循环等
throw new Error('报错了') // 返回值类型为 never,表示不存在的类型,表示函数执行出错,或者无限循环等
while(true) {} // 返回值类型为 never,表示不存在的类型,表示函数执行出错,或者无限循环等
return 1 // error 报错,返回值类型为
return undefined // error 报错,返回值类型为
return null // error 报错,返回值类型为
return 1 // error 报错,返回值类型为
return '1' // error 报错,返回值类型为
return true // error 报错,返回值类型为
return false // error 报错,返回值类型为
return {} // error 报错,返回值类型为
return [] // error 报错,返回值类型为
return function(){} // error 报错,返回值类型为
}
function fn(n:number, str:string): never { // 返回值类型为 never,表示不存在的类型,表示函数执行出错,或者无限循环等
throw new Error('报错了') // 返回值类型为 never,表示不存在的类型,表示函数执行出错,或者无限循环等
while(true) {} // 返回值类型为 never,表示不存在的类型,表示函数执行出错,或者无限循环等
return 1 // error 报错,返回值类型为
return undefined // error 报错,返回值类型为
return null // error 报错,返回值类型为
return 1 // error 报错,返回值类型为
return '1' // error 报错,返回值类型为
return true // error 报错,返回值类型为
return false // error 报错,返回值类型为
return {} // error 报错,返回值类型为
return [] // error 报错,返回值类型为
return function(){} // error 报错,返回值类型为
}
联合类型
ts
function fn(val:number | string){}
fn(1);
fn('str')
fn(null) // 错误
function fn(val:number | string){}
fn(1);
fn('str')
fn(null) // 错误
类型断言
方式一: <类型>值
方式二: 值 as 类型 (tsx 中只能用这种方式)
ts
function fn1(val: number | string):number {
if((val as string).length){
return (<string>val).length
}else{
return val.toString().length;
}
}
function fn1(val: number | string):number {
if((val as string).length){
return (<string>val).length
}else{
return val.toString().length;
}
}
const 断言
看以下示例:
tsx
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method); // 报错,参数2获得的是"string",而不是"GET" | "POST"
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method); // 报错,参数2获得的是"string",而不是"GET" | "POST"
你可以使用断言来传参:
tsx
// 1:在声明时断言他为"GET",防止后续被再次赋值。
const req = { url: "https://example.com", method: "GET" as "GET" };
// 2:传入时断言他为"GET",原来的对象还能赋值
handleRequest(req.url, req.method as "GET");
// 1:在声明时断言他为"GET",防止后续被再次赋值。
const req = { url: "https://example.com", method: "GET" as "GET" };
// 2:传入时断言他为"GET",原来的对象还能赋值
handleRequest(req.url, req.method as "GET");
也可以使用as const将整个对象转换为类型文字:
tsx
const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);
const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);