类型

基础类型 null, undefined, symbol, boolean, void

1
2
const count: number = 123
const teacherName: string = 'Dell'

对象类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person {}

const teacher: {
name: string;
age: number;
} = {
name: "Dell",
age: 18,
};

const numbers: number[] = [1, 2, 3];

const dell: Person = new Person();

const getTotal: () => number = () => {
return 123;
};

type annotation and inference

type annotation 类型注解, 我们告诉 TS 变量是什么类型

type inference 类型推断, TS 会自动地去尝试分析变量的类型

如果 TS 能够自动分析变量类型,就什么也不用做

1
2
3
4
5
// annotation
let count: number;
count = 123;

let countInference = 123;

如果 TS 无法分析变量类型的话,就需要使用类型注解

​```typescript
const firstNumber = 1;
const secondNumber = 2;
const total = firstNumber + secondNumber;// TS 推断出 total 是 number

1
2
3
4
5
6
7

```typescript
function getTotal(firstNumber: number, secondNumber: number) {// firstNumber 需要注解是number类型
return firstNumber + secondNumber;
}

const total = getTotal(1, 2) // total 推断出是number

函数相关类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function add(first: number, second: number): number {
return first + second;
}

function sayHello(): void {
console.log("hellp");
}

function errorEmitter(): never {
// 不会执行结束
while (true) {}
}

function add({ first, second }: { first: number; second: number }): number {
return first + second;
}

基础语法复习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let count: number;
count = 123;

const func = (str: string) => {
// 可以类型推断出func是number
return parseInt(str, 10);
};

const func1 = (str: string) =>
(number = (str) => {
// 语法限制不能省略number
return parseInt(str, 10);
});

const date = new Date(); // 类型推断出date就是Date类型

// 其他 case
interface Person {
name: string;
}
const rawData = { name: "dell" };
const newData: Person = JSON.parse(rawData); //TS不能推断出JSON.parse类型,需要注解

let temp: number | string = 123;
temp = "456";

数组和元组

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const arr: (number | string)[] = [1, "2", 3];
const stringArr: string[] = ["a", "b", "c"];
const undefinedArr: undefined[] = [undefined];

// type alias 类型别名
type User = { name: string; age: number };
const objectArr: User[] = [
{
name: "dell",
age: 13,
},
];

class Teacher {
name: string;
age: number;
}
const objectArr: Teacher[] = [
new Teacher(), //只要符合Teacher数据结构都可以
{
name: "dell",
age: 28,
},
];

元组 tuple

规定了数组的类型的顺序

1
2
3
4
5
6
const teacherInfo: [string, string, number] = ["Dell", "male", 18];
// csv
const teacherList: [string, string, number][] = [
["dell", "male", 18],
["sun", "female", 26],
];

interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface Person {
// interface 和 alias 的区别是, type Person = string, alias可以使用基础类型, 但是interface可以使用函数
readonly name: string; // 只读,如果更改会报错
age?: number; // 可选
}

const getPersonName = (person: Person): void => {
console.log(person.name);
};

const serPersonName = (person: Person, name: string): void => {
person.name = name; // readonly 不能修改
};

const person = {
name: "dell",
};

getPersonName(person);
setPersonName(person, "lee");

当实参直接传递字面量,会进行强校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
getPersonName({
name: "dell",
sex: "male",
}); // 报错, 强校验

const person = {
name: "dell",
sex: "male",
};
// 解决方法1 缓存下在传递
getPersonName(person); // 可以, interface person 只强制需要name
// 解决方法2 更改interface
interface Person {
name: string;
age?: number;
[propName: string]: any;
}

interface 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Person {
name: string;
age?: number;
[propName: string]: any;
say(): string;
}

const person = {
name: "dell",
sex: "male",
say() {
return "hello";
},
};

getPersonName(person);

Class 规范于 interface

1
2
3
4
5
6
class User implements Person {
name = "dell";
say() {
return "hello";
}
}

interface 继承

1
2
3
interface Teacher extends Person {
teach(): string;
}

interface 方法

1
2
3
4
5
6
7
interface SayHi {
(word: string): string; // 接受一个string类型,返回一个string类型
}

const say: SayHi = (word: string) => {
return word;
};

Class 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person {
name = "dell";
getName() {
return this.name;
}
}

class Teacher extends Person {
// 继承
getTeacherName() {
return "Teacher";
}
getName() {
// 重写
return super.getName() + "lee"; // 父类的方法
}
}

const teacher = new Teacher();
console.log(teacher.getName());
public 允许在类的内外被调用
private 允许在类的内部被调用
protected 允许在类内及继承的子类中使用

constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
public name: string;
constructor(name: string) {
this.name = name;
}
}

// 等同于这种写法
class Person {
constructor(public name: string) {}
}

const person = new Person("dell"); // new时构造函数会被调用
console.log(person.name);

super

如果想在子类中使用构造函数,需要调用super(),手动调用父类的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
class Person {
constructor(public name: string) {}
}

class Teacher extends Person {
constructor(public age: number) {
super("Shawn"); // 必须手动调用父类constructor才不会报错
}
}

const teacher = new Teahcer(24);
console.log(teacher.age, teacher.name);

setter 和 getter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
constructor(private _name: string) {}
get name() {
return this._name + " Ng";
}
set name(name: string) {
const realName = name.split(" ")[0];
this._name = realName;
}
}

const person = new Person("dell");
console.log(person.name);
person.name = "dell lee";

单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Demo {
private static instance: Demo;
private constructor() {}

static getInstance() {
if (!this.instance) {
this.instance = new Demo();
}
return this.instance;
}
}

const demo1 = Demo.getInstance(); // demo1和demo2相同
const demo2 = Demo.getInstance();

readonly

1
2
3
4
5
6
7
8
9
class Person {
public readonly name: string;
constructor(name: string) {
this.name = name;
}
}

const person = new Person("Dell"); // 正确
person.name = "hello"; // Error name readonly

抽象类

把几何属性抽象出来

抽象类的抽象方法和属性,继承类必须有
调用继承类的时候只能使用包含在抽象类中方法定义的和属性
抽象类不能直接实例化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
abstract class Geom {
width: number; // 可以写具体属性
getType() {
return "Geom";
}
abstract getArea(): number;
}

new Geom(); // Error. Only extends

class Circle extends Geom {
// 继承抽象类
getArea() {
// 定义了abstract方法,需要写出来,不然报错
return 12;
}
}

class Square {}

class Trangle {}

同理,抽象 Object 可以用 interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
interface Person {
name: string;
}

interface Teacher extends Person {
teachingAge: number;
}

interface Student extends Person {
age: number;
}

const teacher = {
name: "dell",
teachingAge: 3,
};
const student = {
name: "lee",
teachingAge: 13,
};

const getUserInfo = (user: Person) => {
console.log(user.name);
};

getUserInfo(teacher);
getUserInfo(student);

附一个官网例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
abstract class Department {
abstract width: number;

constructor(public name: string) {}

printName(): void {
console.log("Department name: " + this.name);
}

abstract printMeeting(): void; // must be implemented in derived classes
}

class AccountingDepartment extends Department {
width = 123;
height = 123;
constructor() {
super("Accounting and Auditing"); // constructors in derived classes must call super()
}

printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10am.");
}

generateReports(): void {
console.log("Generating accounting reports...");
}
}

let department: Department; // ok to create a reference to an abstract type
// department = new Department(); // error: cannot create an instance of an abstract class
department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass
department.printName();
department.printMeeting();
department.generateReports(); // error: method doesn't exist on declared abstract type
department.width;
department.height; // 类型“Department”上不存在属性“height”。

语法进阶

联合类型 和 类型保护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
interface Bird {
fly: boolean;
sing: () => {};
}

interface Dog {
fly: boolean;
bark: () => {};
}

// 类型断言的方式
function trainAnial(animal: Bird | Dog) {
// 联合类型, 可以是Bird 或者 Dog
animal.sing(); // Error 联合类型提示,只会用共有部分
if (animal.fly) {
(animal as Bird).sing(); // 类型断言的方式, 断言animal就是Bird
} else {
(animal as Dog).bark();
}
}

// 类型保护的方式
function trainAnialSecond(animal: Bird | Dog) {
if ("sing" in animal) {
// 当sing在animal中
animal.sing();
} else {
animal.bark();
}
}

// 使用 instanceof 语法来做类型保护
class NumberObj {
count: number = 123;
}

function addSecond(first: object | NumberObj, second: object | NumberObj) {
if (first instanceof NumberObj && second instanceof NumberObj) {
return first.count | second.count;
}
return 0;
}

元组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Status {
OFFLINE =1 , // 设置1默认开始,下面的增加一
ONLINE,
DELETED
}

console.log(Status)

╰─ npx ts-node ./src/enum.ts
{
'1': 'OFFLINE',
'2': 'ONLINE',
'3': 'DELETED',
OFFLINE: 1,
ONLINE: 2,
DELETED: 3
}

如果下面的设置为 5,则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Status {
OFFLINE,
ONLINE = 5,
DELETED,
}

console.log(Status);

╰─ npx ts-node ./src/enum.ts
{
'0': 'OFFLINE',
'5': 'ONLINE',
'6': 'DELETED',
OFFLINE: 0,
ONLINE: 5,
DELETED: 6
}

实际用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
enum Status {
OFFLINE,
ONLINE,
DELETED,
}

function getResult(status: Status) {
if (status === Status.OFFLINE) {
return "offline";
} else if (status === Status.ONLINE) {
return "online";
} else if (status === Status.DELETED) {
return "deleted";
}
}

const result = getResult(1); // online
// 等同于
// const result = getResult(Status.OFFLINE);

console.log(result);

泛型 generic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function join<T, P>(first: T, second: P) {
// 泛型一般使用T,P来定义,在调用时候指定类型
return `${first}${second}`;
}

function anotherJoin<T, P>(first: T, second: P): T {
// 可以指定返回值也是T泛型
return first;
}

// 泛型的数组的调用方式,等同于T[]
function map<T>(params: Array<T>) {
return params;
}

join<number, string>(1, "1");
join(1, "1"); // TS可以类型推断出来泛型为<number, string>

map<string>(["123"]);

命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace Home {
class Header {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Header";
document.body.appendChild(elem);
}
}

class Content {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Content";
document.body.appendChild(elem);
}
}

export class Page {
// 暴露出Page
constructor() {
new Header();
new Content();
}
}
}

new Home.Page(); // 调用Page, 其他未export的访问不到

文件划分

把多文件组合成一个文件输出

1
"outFile": "./build/page.js"

components.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace Components {
export namespace SubComponents {
// 子命名空间
export class Test {}
}

export interface User {
name: string;
}

export class Header {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Header";
document.body.appendChild(elem);
}
}
export class Content {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Header";
document.body.appendChild(elem);
}
}
export class Footer {
constructor() {
const elem = document.createElement("div");
elem.innerText = "This is Header";
document.body.appendChild(elem);
}
}
}

page.ts

reference 引入相应的 ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
///<reference path='./components.ts' />

// 分文件使用具名空间
namespace Home {
export class Pages {
user: Components.User = {
// 使用具名空间的interface
name: "dell",
};
constructor() {
new Components.Header();
new Components.Content();
new Components.Footer();
}
}
}

全局变量 和 手写类型定义文件 d.ts

先导入 jquery
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>

1
2
3
4
$(function () {
$("body").html("123");
new $.fn.init(); // $是对象
});
  1. 参数类型不一致使函数的重载,以及对象进行类型定义
1
2
3
4
5
6
7
8
9
10
11
// 定义全局函数
declare function $(readyFunc: () => void): void;

declare function $(selector: string): JqueryInstance;

// 如何对对象进行类型定义,以及对类进行类型定义,以及命名空间的嵌套
declare namespace $ {
namespace fn {
class init {}
}
}
  1. 使用 interface 的语法进行函数的重载, 如果$是类的话就不好写
1
2
3
4
5
6
7
interface JQuery {
(readyFunc: () => void): void;
(selector: string): JqueryInstance;
}

//定义全局变量$=JQuery
declare var $: JQuery;
  1. 通过 npm install jquery -S 安装的识别出

使用import $ from 'jquery'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 混合类型模块
declare module "jquery" {
interface JqueryInstance {
html: (html: string) => JqueryInstance;
}
function $(readyFunc: () => void): void;
function $(selector: string): JqueryInstance;
namespace $ {
namespace fn {
class init {}
}
}

// 导出变量
export = $;
}

keyof 和 泛型指定类型

使用泛型可以让 TS 推断出 test 值的类型

<T extends keyof Person>T 为 Person 中的键名, Person[T]则为 Person 中的值

getInfo就可以随着形参的改变而计算出值的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface Person {
name: string;
age: number;
gender: string;
}

class Teacher {
constructor(private info: Person) {}
getInfo<T extends keyof Person>(key: T): Person[T] {
return this.info[key];
}
}

const teacher = new Teacher({
name: "lee",
age: 18,
gender: "male",
});

const test = teacher.getInfo("name");
console.log(test);

类型可用指定字符串的值,abc 只能是 name

1
2
type NAME = "name";
const abc: NAME = "name";

装饰器

打开这两个选项开启装饰器功能

1
2
3
4
5
{
"experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
"emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,

}

类的装饰器

简单写法

1
2
3
4
5
类的装饰器
装饰器本身是一个函数
类装饰器接受的参数是构造函数
装饰器通过 @ 符号来使用
可以使用多个装饰器,从右往左执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function testDecorator(flag: boolean) {
if (flag) {
return function (constructor: any) {
// * 这里是工厂模式,可以支持选择变量,可以删除,直接使用内部的
constructor.prototype.getName = () => {
console.log("dell");
};
};
} else {
return function (constructor: any) {};
}
}

@testDecorator(true)
class Test {}

const test = new Test();
(test as any).getName(); // dell

合理写法

不推断出装饰器内部的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function testDecorator<T extends new (...args: any[]) => any>(constructor: T) {
return class extends constructor {
name = "lee";
getName() {
return this.name;
}
};
}

@testDecorator
class Test {
name: string;
constructor(name: string) {
this.name = name;
}
}

const test = new Test("dell");
console.log((test as any).getName());

推断出装饰器内部的方法,写法有改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function testDecorator() {
return function <T extends new (...args: any[]) => any>(constructor: T) {
return class extends constructor {
name = "lee";
getName() {
return this.name;
}
};
};
}

const Test = testDecorator()(
class {
name: string;
constructor(name: string) {
this.name = name;
}
}
);

const test = new Test("dell");
console.log(test.getName());

方法装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 装饰器永远是个方法,方法的装饰器,里面的三个参数是规定好的
* @param target 普通方法 target 对应的是类的 prototype
* 静态方法 target 对应的是类的构造函数
* @param key 装饰方法的名字
* @param descriptor writable enumerable configurable value
*/
function getNameDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
// console.log(target, key);
// descriptor.writable = true;
descriptor.value = function() {
return 'decorator';
};
}

class Test {
name: string;
constructor(name: string) {
this.name = name;
}
@getNameDecorator
getName() {
return this.name;
}
}

const test = new Test('dell');
console.log(test.getName());

访问器的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function visitDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
// descriptor.writable = false;
}

class Test {
private _name: string;
constructor(name: string) {
this._name = name;
}
get name() {
return this._name;
}
@visitDecorator
set name(name: string) {
this._name = name;
}
}

const test = new Test('dell');
test.name = 'dell lee';
console.log(test.name);

属性的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// * 属性装饰器并没有descriptor, 但是可以返回一个descriptor进行控制

// function nameDecorator(target: any, key: string): any {
// const descriptor: PropertyDescriptor = {
// writable: false
// };
// return descriptor;
// }

// test.name = 'dell lee';

// 修改的并不是实例上的 name, 而是原型上的 name
function nameDecorator(target: any, key: string): any {
target[key] = 'lee';
}

// name 放在实例上
class Test {
@nameDecorator
name = 'Dell';
}

const test = new Test();
console.log((test as any).name); // Dell
console.log((test as any).__proto__.name); // lee

参数装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 原型,方法名,参数所在的位置
function paramDecorator(target: any, method: string, paramIndex: number) {
console.log(target, method, paramIndex);
}

class Test {
getInfo(name: string, @paramDecorator age: number) {
console.log(name, age);
}
}

const test = new Test();
test.getInfo('Dell', 30);

使用案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const userInfo: any = undefined;

function catchError(msg: string) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
const fn = descriptor.value;
descriptor.value = function () {
try {
fn();
} catch (e) {
console.log(msg);
}
};
};
}

class Test {
@catchError('userInfo.name 不存在')
getName() {
return userInfo.name;
}
@catchError('userInfo.age 不存在')
getAge() {
return userInfo.age;
}
}

const test = new Test();
test.getName();
test.getAge();

Reflect Metadata

Reflect Metadata 是 ES7 的一个提案,它主要用来在声明的时候添加和读取元数据。TypeScript 在 1.5+ 的版本已经支持它,你只需要:

  • npm i reflect-metadata --save
  • tsconfig.json 里配置 emitDecoratorMetadata 选项

metadata

API

1
2
3
4
5
6
7
function metadata(
metadataKey: any,
metadataValue: any
): {
(target: Function): void;
(target: Object, propertyKey: string | symbol): void;
};

使用

1
2
3
4
5
6
7
8
9
10
@Reflect.metadata('inClass', 'A')
class Test {
@Reflect.metadata('inMethod', 'B')
public hello(): string {
return 'hello world';
}
}

console.log(Reflect.getMetadata('inClass', Test)); // 'A'
console.log(Reflect.getMetadata('inMethod', new Test(), 'hello')); // 'B'

获取类型信息

通过使用 Reflect.getMetadata API,Prop Decorator 能获取属性类型传至 Vue,

1
2
3
4
5
6
7
8
9
10
11
12
13
function Prop(): PropertyDecorator {
return (target, key: string) => {
const type = Reflect.getMetadata('design:type', target, key); // 获取属性类型
console.log(`${key} type: ${type.name}`); // Aprop type: string
// Reflect.getMetadata("design:paramtypes", target, key) // 获取函数参数类型
// Reflect.getMetadata("design:returntype", target, key) // 获取返回值类型
};
}

class SomeClass {
@Prop()
public Aprop!: string;
}

自定义 metadataKey

除能获取类型信息外,常用于自定义 metadataKey,并在合适的时机获取它的值,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function classDecorator(): ClassDecorator {
return target => {
// 在类上定义元数据,key 为 `classMetaData`,value 为 `a`
Reflect.defineMetadata('classMetaData', 'a', target);
};
}

function methodDecorator(): MethodDecorator {
return (target, key, descriptor) => {
// 在类的原型属性 'someMethod' 上定义元数据,key 为 `methodMetaData`,value 为 `b`
Reflect.defineMetadata('methodMetaData', 'b', target, key);
};
}

@classDecorator()
class SomeClass {
@methodDecorator()
someMethod() {}
}

Reflect.getMetadata('classMetaData', SomeClass); // 'a'
Reflect.getMetadata('methodMetaData', new SomeClass(), 'someMethod'); // 'b'

Basic Types 官网

Boolean

1
let isDone: boolean = false;

Number

1
2
3
4
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

String

1
2
let color: string = "blue";
color = "red";

Array

1
2
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];

Tuple

1
2
3
4
5
6
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ["hello", 10]; // OK
// Initialize it incorrectly
x = [10, "hello"]; // Error

当访问具有已知索引的元素时,将检索正确的类型:

1
2
console.log(x[0].substring(1)); // OK
console.log(x[1].substring(1)); // Error, 'number' does not have 'substring'

访问一组已知索引之外的元素失败,并显示以下错误:

1
2
x[3] = "world"; // Error, Property '3' does not exist on type '[string, number]'.
console.log(x[5].toString()); // Error, Property '5' does not exist on type '[string, number]'.

Enum

1
2
3
enum Color {Red, Green, Blue}

let c: Color = Color.Green;// 1

默认情况下,枚举从 0 开始对其成员编号。您可以通过手动设置其成员之一的值来更改此值。
例如,我们可以从 1 而不是 0 开始上一个示例:

1
2
3
4
5
6
enum Color {
Red = 1,
Green,
Blue,
}
let c: Color = Color.Green;

甚至手动设置枚举中的所有值:

1
2
3
4
5
6
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
let c: Color = Color.Green;

枚举的一个方便功能是,您也可以在枚举中从数字值转到该值的名称。
例如,如果我们具有值 2,但不确定上面的 Color 枚举中映射到的值,则可以查找对应的名称:

1
2
3
4
5
6
7
8
enum Color {
Red = 1,
Green,
Blue,
}
let colorName: string = Color[2];

console.log(colorName); // Displays 'Green' as its value is 2 above

Any

我们可能需要描述编写应用程序时不知道的变量类型。
这些值可能来自动态内容,例如
来自用户或第三方库。
在这些情况下,我们要选择退出类型检查,并让值通过编译时检查。
为此,我们将它们标记为任何类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

//如果您知道类型的某些部分,但可能不是全部,那么any类型也很方便。
//例如,您可能有一个数组,但是该数组混合了不同的类型:
let list: any[] = [1, true, "free"];

list[1] = 100;

Void

1
2
3
function warnUser(): void {
console.log("This is my warning message");
}