Fork me on GitHub

TypeScript类型和安装编译

Typescript

TypeScript 是 JavaScript 的类型的超集,它可以编译成 JavaScript。TypeScript是一门静态语言,新增了静态类型、类、模块、接口和类型注解,规避了一些类型上的低级错误,更适合应用于开发大型应用。

全局安装 TypeScript

1
npm install -g typescript

TypeScript 类型

基础类型

原始类型:

string, number, boolean(非严格模式下,这三种都可以存放null或undefined), null, undefined,

void(空值,一般用来标记没有返回值的函数返回类型,只能存放null或undefined)

symbol

boolean

1
let isDone: boolean = false;

number

1
2
let num: number = 6;
let hexLiteral: number = 0xf00d;

string

1
let myName: string = 'Tom';

数组

1
2
3
4
5
6
//定义数组的两种方式
//方式一
let list: number[] = [1, 2, 3];

//方式二,使用数组泛型
let newlist: Array<number> = [1, 2, 3];

元组

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

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
const tup : [string, number] = ['aaa', 1]

枚举(enum)

表示固定的几个取值。

1
2
3
4
5
6
7
8
9
10
11
12
13
enum Color { Red, Green, Blue }
let c: Color = Color.Green;

//枚举类型的本质是数值类型, 所以赋值数值不会报错。
let c1: Color
c1 = 1

// ts中枚举类型的取值,默认从0开始,从上到下依次递增
enum TestNum {
First = 3,
Second
}
console.log(TestNum.First, TestNum.Second) // 3, 4

和object的区别:

  • 枚举可以通过枚举的名称,获取枚举的值,也可以通过枚举的值获取枚举的名称。object只能通过key获取value;
  • 不指定初始值,枚举值会默认从0开始递增

任意值(Any)

任意值(Any)用来表示允许赋值为任意类型。

在任意值上访问任何属性都是允许的,也允许调用任何方法,可以认为声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值。

1
2
3
4
5
6
let anyThing: any = 'hello';

console.log(anyThing.myName);
console.log(anyThing.myName.firstName);

anyThing.setName('Jerry');

变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型。

空值(Void)

1
2
3
function alertName(): void {
alert('My name is Tom');
}

在 TypeScript 中,可以用 void 表示没有任何返回值的函数。声明一个 void 类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null。

Null 和 Undefined

与 void 的区别是,undefined 和 null 是所有类型的子类型。

1
2
let u: undefined;
let num: number = u;

Never

never类型表示的是那些永不存在的值的类型。

never是任何类型的子类型,可以赋值给任何类型。但是没有类型可以赋值给never。

可以用于总是抛出异常或者永远不会有返回值的函数表达式。

Object

object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。

1
2
3
4
5
6
7
8
9
declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

Object类型可以存放对象,数组,函数。

1
2
3
4
5
6
7
// 限制对象: 1. 类似字面量
const obj : { name: string } = { name: 'person1' }
// 限制对象: 2. 接口
interface PersonModel {
name: string
}
const obj2 : PersonModel = { name: 'person2' }

BigInt

表示最大的数

Symbol

表示全局唯一的引用(标识)

unknown

unknown 表示未知的类型。unknown和any都可以赋值给任意类型的, any 会绕过类型检查,而如果把unknown类型的值赋值给别的类型会报错。

1
2
3
4
5
6
// unknown与其他类型组合或交叉最后都是其他类型
type t = number & unknown //t是number类型

// unknown和任何类型组成的联合类型都是unknown(除了和any)
type t1 = unknown | any // t1 是 any类型
type t2 = unknown | number // t2 是unknown类型

类型推论

如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。

1
2
3
let myFavoriteNumber = 'seven';
//等价于
let myFavoriteNumber: string = 'seven';

如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查:

1
2
3
let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

类型声明

如果一个成员在定义时没有声明类型,可以在使用之前做类型声明(兼容第三方非ts编写的js模块)

1
declare function cameCase(word: string) : string

接口

接口的作用就是为一些类型命名和代码定义契约,进行类型检查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface LabelledValue {
label: string;
color?: number; //可选
readonly width: number; //只读
}
interface LabelledValue {
addProp?: string //接口可以扩充,但如果两个接口中同时声明了同名的非函数成员且它们的类型不同,则编译器会报错
}
//简单用法
function printLabel(config: LabelledValue) {
console.log(config.label);
}

function createLabel(config: LabelledValue): {label: string; color: string; width: number} {
let newLabel = {label: '', color: "white", width: 10};
if (config.color) {
newLabel.color = config.color;
}
return newLabel;
}
let mySquare = createLabel({label: 'aaa', color: "black", width: 10});

TypeScript具有ReadonlyArray类型,它与Array相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改:

1
2
3
4
5
6
7
8
9
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!

//可以用类型断言重写
a = ro as number[];

开始

创建项目

新建一个文件夹learn_ts,在文件夹中新建src

1
2
cd learn_ts
mkdir src

初始化文件夹:

1
2
npm init
tsc --init

目录下自动生成了一个package.json文件和tsconfig.json文件。

tsconfig.json是TypeScript 的配置文件,其中包含了初始化的一些配置,之后我们也可以自定义一些配置。

初体验

在src文件夹下新建一个index.ts文件:

1
2
3
4
5
6
function sayHello(person: string) {
return 'Hello, ' + person;
}

let user = 'Tom';
console.log(sayHello(user));

编译ts文件:

1
tsc index.ts

编译之后会在文件夹中生成一个同名的js文件。

TypeScript 只会进行静态检查,如果发现有错误,编译的时候就会报错。

TypeScript 编译的时候即使报错了,还是会生成编译结果。(如果要在报错的时候终止 js 文件的生成,可以在 tsconfig.json 中配置 noEmitOnError 即可)

参考

https://www.tslang.cn/docs/handbook/basic-types.html

-------------完结撒花 -------------