在 TypeScript 中,可以通过类型注释对变量、参数、返回值的类型进行标注。
- 声明变量如果不指定类型,则 TS 解析器会自动判断变量的类型为
any
(隐士 any),any 类型变量可以赋值给任意变量。
类型 | 说明 | 例子 |
---|---|---|
number | 任意数字 | 1, -33, 2.5 |
string | 任意字符串 | “h1”, “你好”, “1” |
boolean | 布尔值 | true, false |
object | 任意的 js 对象 | { “name”: “张三” } |
array | 任意 js 数组 | [1, 2, 3] |
null | 空 | * |
undefined | 未定义 | * |
字面量 | 限制变量的值就是该字面量的值 | 其本身 |
any | 任意类型 | * |
unknown | 类型安全的 any | * |
void | 没有值 (或 undefined) | 空值 (undefined) |
never | 不能是任何值 | 没有值 |
tuple | 元素,TS 新增类型,固定长度数组 | [4, 5] |
enum | 枚举,TS 新增类型 | enum{ A, B } |
类型声明
如果变量的声明和赋值同时进行,可以省略掉类型声明,TS可以自动对变量进行类型检测。
声明变量如果不指定类型,TS解析器会自动判断变量的类型为 any,相当于对该变量关闭了 TS 的类型检测。
// 定义变量
let 变量名: 类型;
let 变量名 = 值;
let 变量名: { 属性名: 类型, 属性名?: 类型 }; // 属性名后面加上?,表示可选类型
// 定义方法
function fn(参数名: 类型, 参数名: 类型): 返回值类型 {
...
};
let 变量名 = (参数名: 类型, 参数名: 类型) => 返回值类型;
// 数值类型
let apples: number = 5;
// 字符串类型
let speed: string = "fast";
// 布尔值类型
let hasName: bolean = true;
// 类型错误提示
apples = "5"; // 类型 'string' 不能功能类给类型 'number';
# 联合类型 > 联合类型:可以赋值为指定的多个类型。 > 当没有确定类型时,会把两种类型共有的方法列出来
let c: boolean | string;
c = true;
c = 'hello';
any 类型
变量中可以存储任何数据类型的值。
let anything: any = "Hello TypeScript";
anything = 10;
anything = false;
anything = function () {};
- 隐士 any:只定义了变量名,没有定义类型,也没有赋值。
let c;
Array 数组
在没有为数组显示标注类型时,变量的初始值又是一个空数组,此时该数组中可以存储任何类型的值。虽然写法正确,但丢失了 TypeScript 类型检查功能。
-
可以设置任意类型的值。
let colors = any[]; let colors = []; colors = [1, 2, 3, 4, 5]; colors = ["1", "2", "3", "4"]; colors = [false, true];
-
只能设置单个类型的数组。
# 语法格式 let 变量名: 类型[] = [值1, 值2, 值3]; let 变量名: Array<类型> = [值1, 值2]; // 也可以声明,比较麻烦 let colors: string[] = ["1", "2", "3", "4"]; // 只能设置数字数组 let colors: number[] = [1, 2, 3, 4, 5];
-
二维数组。
# 语法格式 let 变量名: 类型[][] = [ [值1, 值2], [值1, 值2] ]; let carMarkers: string[][] = [ ["奔驰", "奥迪"], ["宝马"] ];
Tuples 元组
元组是 TypeScript 引入的一种新数据类型,它像数组一样工作,但是有一些额外的限制:元素中个数是固定,元组找那个元素类型已知。
元组用来存储一些以特定顺序出现且相关关联的数据,通过元组可以约束元素的个数及元素类型。
// 元组数组存储RGB颜色
var rgb = [number, number, number, number] = [255, 0, 0, 0.2];
// 元组数组(二维数组)
var employee[number, string][] = [ [1, "Tom"], [2, "Cat"] ];
Enum 枚举
用于存储一组密切相关且有限的值,可以提升代码的可读性,可以限定值的范围。例:消息的阅读状态、比赛结果、考试成绩、颜色种类、性别。
约定:枚举变量首字母大写。
// 如果枚举没有设置值时,默认值从0开始
enum Sizes {
Small,
Medium,
Large
};
console.log(Sizes.Small); // 默认是:0 1 2
// 如果枚举设置默认值,则从设置的值开始往后依次+1,前面的值还是从0开始+1
enum Sizes {
Small, // 0
Medium = 2, // 2
Large // 3
};
console.log(Sizes.Large); // 3
注意:如果枚举为非数值,则每个属性都必须进行初始化。
enum Sizes {
Small = "Small",
Medium = "Medium",
Large = "Large"
};
console.log(Sizes.Small); // Small
枚举编译后变为 js 对象。
enum Sizes {
Small = "Small",
Medium = "Medium",
Large = "Large"
};
- 编译后的 js 对象。
var Sizes; (function (Sizes) { Sizes["Small"] = "s"; Sizes["Medium"] = "m"; Sizes["Large"] = "l"; })(Sizes || (Sizes = {}));
在声明枚举类型时,如果使用 const
关键字,TypeScript 编译器将输出更加简洁的代码。即:枚举本身不会被编译到 js 文件中。
const enum Sizes {
Small = "s",
Medium = "m",
Large = "l"
};
let selected = Sizes.Large;
console.log(selected);
// 编译结果
var selected = "l" /* Large */;
console.log(selected);
类型使用枚举
// 枚举
emun Gender {
Male = 0,
Female = 1
};
let i: { name: String, gender: Gender };
i = {
name: '张三',
gender: Gender.Male
};
Function 函数
通过类型注释可以显示设置函数将要接收的参数的类型,函数将要返回的值的类型。
// 普通写法
// function 方法名(参数1: 类型, 参数2: 类型): 返回值类型 {}
function add(a: number, b: number): number {
return a + b;
};
// 箭头函数写法
// const 变量名 = (参数1: 类型, 参数2: 类型) => 返回值类型
const add = (a: number, b: number): number => {
return a + b;
};
// 调用参数要和类型一样
add(10, 20);
// 没有返回值使用 void 进行标注
function log(): void {};
可选参数
可选参数格式:
参数名?:类型
。
function sum(a: number, b: number, c?: number): number {
// 可选参数c有值
if(typeof c !== "undefined") {
return a + b + c;
};
// 可选参数c没值
return a + b;
};
sum(10, 20, 30); // 60
// 默认值方式设置可选参数
function sum(a: number, b: number, c: number = 0): number {
return a + b + c;
};
sum(10, 20); // 30
解构语法设置类型
// 解构出来的值设置类型
function logWeather({ data, weatcher }: { date: Date; weatcher: string }) {
console.log(date, weatcher);
};
// 要传递的参数
const weatcher = {
date: new Date(),
weatcher: "sunny"
};
// 调用
logWeather(weatcher);
Object 对象
// 对象字面量:以{}的形式创建对象,而不是new Object()创建
let point: { x: number, y: number } = { x: 100, y: 200 };
// readonly 关键字把数据变为只读
let employee: { readonly id: number } = { id: 1 };
// 可选参数
let student = { age?: number } = {};
student.age = 20;
// 内置对象,类本身可以作为类实体的类型
let 变量名: 类名 = new 类();
let date: Date = new Date();
// 自定义类
class Car = {};
let car: Car = new Car();
只读属性
使用
readonly
修饰的属性是只读属性,不可以修改。
let person = { readonly name: string, age: number } = { name: "张三", age: 18 };
// 只能修改age
person.age = 20;
类型推断
TypeScript 编译器能根据一些简单的规则推断变量的类型,在没有显示设置变量类型的情况下,编译器将变量初始值的类型作为该变量的类型。
- 不推荐使用,这样就失去了类型约束的意义。
let apples = 5; // 类型为 number
let speed = "fast"; // 类型为 string
let anything = []; // 类型为 any[]
TypeScript 会试图推断函数返回值的类型。
使用函数返回值类型判断时,在编写函数内部代码时就会失去类型检测功能,所以函数返回值类型推荐明确指定。
如果函数的返回值是undefined
,可以指定函数的返回值为void
。
-
推断返回值类型为
number
。// const add = (a: number, b: number) => number const add = (a: number, b: number) => { return a + b; };
-
推断返回值类型为
void
。// const add: (a: number, b: number) => void const add = (a: number, b: number) => {};
-
推断返回值类型为
string | boolean
。// const find = (name: string) => string | boolean; const find = (name: string) => { if (name) { return name; } else { return false; }; };
在 TypeScript 编译器可以推断出变量类型的情况下,开发者不需要显式编写类型注释,也就是说只有在 TypeScript 不能正确推断变量类型的情况下开发者才需要编写类型注释。
-
如果变量声明后没有被立即初始化,TypeScript 编译器不能正确推断出它的类型。
// TypeScript 编译器认为是 any 类型,失去了 TypeScript 中的类型检查功能 let anything; // let anything: any; anything = 10; anything = "hello";
-
调用的函数返回值是 any 类型时,应该使用显式声明它的类型。
let json = '{"name": "张三"}'; // let person: any => let person: {name: string} let person = JSON.parse(json);