1. 变量
// let 变量名: 变量类型 = 值
let age: number = 18;
在 TS 中,为变量指定了类型,就只能给这个变量设置相同类型的值
上述中的 : number 称为类型注解
2. 数据类型
原有类型
- number
- string
- boolean
- undefined:表示声明但未赋值的变量值
- null:声明了变量并已赋值,值为
null
let aName: string = 'konsoue';
let age: number = 18;
let isDog: boolean: true;
let undef: undefined = undefined;
let n: null = null;
undefined
和null
是所有类型的子类型
let num: number = undefined;
- Array
// 方式一
let arrHeros: string[] = ['安琪拉', '亚索'];
// 方式二(泛型语法)
let arrHeros: Array<string> = ['安琪拉', '亚索'];
// 任意类型
let arr: any[] = [1, '123', false, undefined, null];
新增类型
tuple 元组
就是一个规定了元素数量和每个元素类型的“数组”,而每个元素的类型可以不相同
let tup1: [string, number, boolean] = ['1', 1, true];
// 访问元素和长度
tup1[0]
tup1.length
enum 枚举
枚举项一般用英文和数字,而枚举值用整型数字
enum GunType {
M416 = 1,
AK47 = 2,
Goza = 3
}
// 使用默认枚举值,从 0 开始
enum GunType {
M416, // 0
AK47, // 1
Goza // 2
}
// 编译后的 js 代码
var GunType;
(function(GunType) {
GunType[GunType['M416'] = 0] = 'M416';
GunType[GunType['AK47'] = 1] = 'AK47';
GunType[GunType['Goza'] = 2] = 'Goza';
})(GunType || (GunType = {}))
// 声明性别枚举
enum Gender {
Boy = 1,
Girl, // 2
Unknown // 3
}
// 创建用户性别变量
let userSex: Gender = Gender.Boy;
- 常量枚举
可以提高性能
const enum GunType {
M416, // 0
AK47, // 1
Goza // 2
}
any 任意值类型
any 代表任意类型,一般在获取 DOM 时使用 在接收用户输入 或 第三方代码库时,还不能确定会返回什么类型的值,此时也可以用 any 类型
let txtName: any = document.getElementById('txtN');
unknown 未知值类型
unknown
和any
是 TypeScript 的顶级类型
跟 any
一样能被各种类型赋值,但是它只能赋值给 any
和 unknown
类型。
这是因为在不知道 unknown
具体的值是什么类型的情况下,只能赋值给能够保存任意类型的容器。
// 设置为 unknown 类型后,这些操作将不再正确;
let value: unknown;
value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error
void 空值类型
void 代表没有类型,一般用在无返回值的函数
function sayhi(): string {
return 'hi,你好';
}
function sayhi1(): void {
console.log('111')
}
never 类型
never
类型是其他类型(包括 null
和 undefined
)的子类型,代表永远不会出现的值。
常用作为
抛出异常
或无限循环
的函数返回类型。 声明never
的变量只能被never
类型所赋值。
function test(): never {
while(true) {
// ...
}
}
function test2(): never {
throw new Error('error');
}
let a = (() => {
throw new Error('错误')
})()
never 类型是 ts 中的底部类型,所有类型都是 never 类型的父类,所以 never 类型值可以赋给任意类型的变量
let x: never = test();
let y: string = test();
在 TypeScript
中,可以利用 never
类型来实现全面性检查:
type Foo = string | number;
function controlFlowAnalysisWithNever(foo: Foo) {
if (typeof foo === "string") {
// 这里 foo 被收窄为 string 类型
} else if (typeof foo === "number") {
// 这里 foo 被收窄为 number 类型
} else {
// foo 在这里是 never
const check: never = foo;
}
}
3. 类型推论
如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
如果变量的声明和初始化是在同一行,可以省略掉变量类型的声明。
let 变量名 = 值;
// 相当于
let 变量名: 变量类型 = 值;
let age = 18;
age = 'string'; // error
4. 联合类型
表示可以取值为多种类型中的一种,通常与
null
或undefined
一起使用
let 变量名: 变量类型1 | 变量类型2 = 值;
let num: number | undefined;
console.log(num);
num = 123;
console.log(num);
5. 交叉类型
将多个类型合并为一个类型
interface IPerson {
id: string;
age: number;
}
interface IWorker {
companyId: string;
}
// 两者求并集,同时拥有 IPerson 和 IWorker 这两种类型的成员
type IStaff = IPerson & IWorker;
const staff: IStaff = {
id: 'E1006',
age: 33,
companyId: 'EFT'
};
console.dir(staff)
6. 类型保护
类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。
换句话说,类型保护可以保证一个字符串是一个字符串,尽管它的值也可以是一个数值。
类型保护与特性检测并不是完全不同,其主要思想是尝试检测属性、方法或原型,以确定如何处理值。
目前主要有四种的方式来实现类型保护:
interface Employee { name: string; startDate: Date; }
type UnknownEmployee = Employee | Admin;
function printEmployeeInformation(emp: UnknownEmployee) { console.log(“Name: “ + emp.name); if (“privileges” in emp) { console.log(“Privileges: “ + emp.privileges); } if (“startDate” in emp) { console.log(“Start Date: “ + emp.startDate); } }
<a name="TMPWm"></a>
## 6.2 typeof 关键字
typeof 返回的结果是以下字符串之一。<br />`"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"`
```typescript
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "function") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
6.3 instanof 关键字
interface Padder {
getPaddingString(): string;
}
class SpaceRepeatingPadder implements Padder {
constructor(private numSpaces: number) {}
getPaddingString() {
return Array(this.numSpaces + 1).join(" ");
}
}
class StringPadder implements Padder {
constructor(private value: string) {}
getPaddingString() {
return this.value;
}
}
let padder: Padder = new SpaceRepeatingPadder(6);
if (padder instanceof SpaceRepeatingPadder) {
// padder的类型收窄为 'SpaceRepeatingPadder'
padder.getPaddingString()
}
6.4 is 关键字——自定义类型保护谓词
function isNumber(x: any): x is number {
return typeof x === "number";
}
function isString(x: any): x is string {
return typeof x === "string";
}
interface IUserProps {
vType: 'userProps';
name: string;
email: string;
}
function isUserProps(x: any): x is IUserProps {
return x.vType === 'userProps';
}
class UserProps {
name: string;
email: string;
vType: string;
constructor(name: string, email: string) {
this.name = name;
this.email = email;
this.vType = 'userProps';
}
}
const obj = new UserProps('konsoue', 'xx@qq.com')
if (isUserProps(obj)) {
// to something
}