值类型
// 字符串
let myNname: string = "朝阳";// 数字
let num: number = 10;// 布尔类型
let ifLogin: boolean = true;
// 布尔类型支持赋值计算之后结果是布尔值的表达式
let bool: boolean = !!0// null
let n: null = null;// undefined
let u: undefined = undefined;// symbol
let s: symbol = Symbol();
TS 官方推荐使用 string , 不推荐用 String , 因为 String 是包装对象,Number,Boolean 等同理。
let myname: string = "朝阳";myname = new String("你好"); // 报错:不能将类型“String”分配给类型“string”。“string”是基元(基础数据类型),但“String”是包装器对象。
String 既能赋值基础字符串,也能赋值包装对象。
let myname: String = "朝阳";myname = new String("你好");
数组 []
// 空数组
let arr: [] = [];// 元素只能是数字的数组(其他类型的写法类似)
let arr1: number[] = [1, 2];// 元素只能是数字或字符串的数组(| 表示或的关系)
let arr2: (number | string)[] = [1, "朝阳"];// 即是number类型也可能是string数组
const numbers1: number[] | string[] = ['123', '333'] // 正确
const numbers2: number[] | string[] = [123, '333'] // 错误// 对象数组
let todoList: {id: number;label: string;done: boolean;
}[] = [{id: 1,label: "吃饭",done: false,},{id: 2,label: "编程",done: false,},
];// 使用类型别名(type alias)
type User = { name: string; age: number }// 存储对象类型的内容
const objectArr: User[] = [{name: 'zws',age: 18}
]// 构造函数声明类型
let arr_1: Array<number> = [1, 2];
let arr_2: Array<number | string> = [1, "朝阳"];
对象 {}
// 空对象
let o: {} = {};
let o2: object = {};// 必选属性的对象(赋值时,声明的属性必须有!)
let user: {name: string;age: number;
} = {name: "朝阳",age: 35,
};// 可选属性的对象(可选属性需写在必选属性的后面!)
let user2: {name: string;age?: number;
} = {name: "晚霞",
};
对象类型的描述,可以用 ,
;
或换行分隔,如
let user1: {name: string;age: number
};let user2: {name: string,age: number
};let user3: {name: stringage: number
};
Object 、object 和 {} 的区别
-
Object
(首字母大写)【用得很少,因类型太宽泛】 和{}
的类型声明最抽象,对象、数组、基础数据类型(除 null , undefined)都能赋值。 -
object
(首字母小写)【用得很少,因类型太宽泛】更具体些,类似于{ [key: string]: any }
,可以给它赋值对象和数组,不能分配基础数据类型 -
{ [key: string]: string }
则最具体,只能赋值键值为字符串的对象。
var p: {}; // 或 Object
p = { prop: 0 }; // OK
p = []; // OK
p = 42; // OK
p = "string"; // OK
p = false; // OK
p = null; // Error
p = undefined; // Errorvar o: object;
o = { prop: 0 }; // OK
o = []; // OK
o = 42; // Error
o = "string"; // Error
o = false; // Error
o = null; // Error
o = undefined; // Errorvar q: { [key: string]: any };
q = { prop: 0 }; // OK
q = []; // OK
q = 42; // Error
q = "string"; // Error
q = false; // Error
q = null; // Error
q = undefined; // Errorvar r: { [key: string]: string };
r = { prop: 'string' }; // OK
r = { prop: 0 }; // Error
r = []; // Error
r = 42; // Error
r = "string"; // Error
r = false; // Error
r = null; // Error
r = undefined; // Error
索引签名
允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于描述类型不确定的属性(具有动态属性的对象)。
let person: {name: string;age?: number;// 下方为索引签名,表示本对象可以有任意数量的属性,属性值可以为任意类型。[key: string]: any; // 通常用 key ,实际可以写任意名称,如 index 等。
};person = { name: "朝阳", age: 35, gender: "男", city: "成都" };
函数 function
// TS 语法,声明 add 变量为函数类型,此处 => 并不表示箭头函数,而是表示函数的定义
let add: (a: number, b: number) => number; // a,b 只是形式参数,可以用任意字符串代替add = (x, y) => {return x + y;
};// 命名函数
function add(arg1: number, arg2: number): number {return x + y;
}// 箭头函数
const add = (arg1: number, arg2: number): number => {return x + y;
};
类 class
class Person {}
const me: Person = new Person()class Teacher {name: stringage: number
}const objectArr: Teacher[] = [new Teacher(),{name: 'zws',age: 18}
]
任意类型 any
当不确定变量的类型时(比如来自用户输入或第三方代码库的动态内容),可以使用,但尽量少用。
- 任何类型的值都可以赋值给 any 类型的变量
let a: any = '你好'
a = 0// 多数据类型的数组
let list: any[] = [1, true, "free"];
- 未声明类型的变量,其类型就是 any
// 与 let myname:any 等效
let myname
- any 类型的变量,可以赋值给任意类型的变量
let myname: any = "朝阳";let yourName: number = 11;// 不会报错!
yourName = myname;
- 读取 any 类型数据的任何属性都不会报错
不确定的类型 unknown
-
任何类型的值都可以赋值给 unknown 类型的变量
-
unknown 可以理解为类型安全的 any ,即 unknown 类型的变量,无法像 any 类型的变量一样,随意赋值给其他类型的变量。
-
any 与 unknown 的区别 : unknown 需要明确类型后执行操作,any 则不需要
let a: unknown = 1;let b = a + 1; // 会报错 “a”的类型为“未知”
永不存在的类型 never
用于总会抛出异常或根本不会有返回值的函数表达式的返回值类型。
当变量被永不为真的类型保护所约束时,该变量也是 never 类型。
很少主动声明类型 never,通常是 TS 自行推导出类型 never
用途:
- 限制函数的返回类型(顺利执行的函数默认会返回 undefined,所以 never 仅适用于运行过程中会抛出异常,或永远调不完的函数)
- 控制流程
- 类型运算
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {throw new Error(message);
}// 推断的返回值类型为never
function fail() {return error("Something failed");
}// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {while (true) {}
}
空类型 void
通常用于描述函数没有返回值
// 实际函数的返回值为 undefined
function test(): void {
}
或
// 实际函数的返回值为 undefined
function test(): void {return;
}
或
// 明确指定函数的返回值为 undefined
function test(): void {return undefined;
}
void
类型的变量只能被赋予undefined
let test: void = undefined;
但 void 与 undefined 并不等效!
function test2(): void {}let result2 = test2();// 此处会报错,因为 TS 不建议对 void 类型的数据做进一步处理和判断!
if (result2) {
}
undefined 则不会报错
function test1(): undefined {}let result1 = test1();if (result1) {
}
这是 TS 官方的一种特殊处理
元组 Tuple
固定长度和类型(可以不同)的数组
let x: [string, number]; // 元组 -- 第一个元素是字符串,第二个元素是数字
x = ['hello', 10];
let x: [number, string?]; // 元组 -- 字符串元素是可选的,可有可无
let x: [number, ...string[]]; // 元组 -- 字符串元素可以是任意数量(含0个)
枚举 enum【重要】
一组常量值,不能修改,可提升语义,方便维护。
- 枚举类型的名称通常首字母大写!
数值枚举(默认)
- 枚举成员的值会默认递增
- 具有反向映射
enum Direction {Up,Down,Left,Right,
}console.log(Direction);
打印可见
{'0': 'Up','1': 'Down','2': 'Left','3': 'Right',Up: 0,Down: 1,Left: 2,Right: 3
}
// 枚举三原色
enum Color {Red, Green, Blue}
// 按枚举内容的字符串取值,得到的是对应的下标(类似数组的下标,从0开始)
let c: Color = Color.Green; // c的值为1
// 枚举方向:上下左右
enum Direction {Up,Down,Left,Right
}// 按下标取值,可得到枚举内容的字符串
console.log(Direction[0]) // "Up"
可以自定义下标的起点
// 将默认的下标 0 改为 下标 1,则后续下标会依次递增
enum Direction {Up = 1,Down, // 2Left, // 3Right // 4
}
也可以自定义任意下标,未定义的在上一个的基础上递增
enum Direction {Up = 11,Down, // 12Left = 6, Right, // 7
}
甚至下标可以相同
enum Direction {Up = 11,Down, // 12Left = 11,Right, // 12
}console.log(Direction.Down); // 打印 12console.log(Direction); // 打印 { '11': 'Left', '12': 'Right', Up: 11, Down: 12, Left: 11, Right: 12 }
如果下标使用了计算值或常量,那么该字段后面紧接着的字段必须设置初始值,不能默认递增值了!
const getValue = () => {return 0;
};
enum ErrorIndex {a = getValue(),b, // error 枚举成员必须具有初始化的值c
}
enum RightIndex {a = getValue(),b = 1,c
}
const Start = 1;
enum Index {a = Start,b, // error 枚举成员必须具有初始化的值c
}
字符串枚举
即给枚举成员赋值为字符串
- 当枚举成员为字符串时,其之后的成员也必须是字符串。
- 没有反向映射
enum Direction {Up, // 未赋值,默认为0Down = '南',Left = '西',Right = '东'
}
常量枚举
给枚举添加 const
标注,可减少编译的代码量。
enum Direction {Up,Down,Left,Right,
}console.log(Direction.Up);
编译为 js 后为
var Direction;
(function (Direction) {Direction[Direction["Up"] = 0] = "Up";Direction[Direction["Down"] = 1] = "Down";Direction[Direction["Left"] = 2] = "Left";Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
console.log(Direction.Up);
而
const enum Direction {Up,Down,Left,Right,
}
编译为 js 后为
console.log(0 /* Direction.Up */);
可见编译后的代码量,大大减少了!
事件 Event
如鼠标事件 MouseEvent
HTML元素 HTMLElement
如 input 元素 HTMLInputElement
字面量类型(了解即可)
let myname: "朝阳" = "朝阳";
则 myname 只能赋值 “朝阳” ,无法赋值其他值。