TypeScript
是JavaScript
的一个超集,支持ECMAScript 6
标准(ES6
教程)。TypeScript
由微软开发的自由和开源的编程语言。TypeScript
设计目标是开发大型应用,它可以编译成纯JavaScript
,编译出来的 JavaScript
可以运行在任何浏览器上。TypeScript
本身并非什么高深的技术,凡是有JavaScript
基础的同学都可以轻松掌握TypeScript
是一种给 JavaScript
添加特性的语言扩展。增加的功能包括:
Mixin
Await
ECMA 2015
反向移植而来:
lambda
函数的箭头语法TypeScript
和JavaScript
的区别TypeScript
是 JavaScript
的超集,扩展了JavaScript
的语法,因此现有的JavaScript
代码可与TypeScript
一起工作无需任何修改,TypeScript
通过类型注解提供编译时的静态类型检查。TypeScript
可处理已有的JavaScript
代码,并只对其中的TypeScript
代码进行编译。Bug
时间。JS
缺失的功能。Vue 3
源码使用TS重写,释放出重要信号: TS
是趋势。Angular
默认支持TS
; React
与TS
美配合,是很多大型项目的首选TypeScript
的安装有两种主要的方式来获取TypeScript
工具:
注意:由于Vscode
的终端默认使用powershell
,默认禁止输入脚本(指令)
powershell
,终端执行set-ExecutionPolicy RemoteSigned
;输入y
通常我们使用.ts
作为TypeScript
代码文件的扩展名
目录结构:
在index.html
中
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
head>
<body>body>
<script src="./index.js">script>
html>
在index.ts
中
console.log("Hello TypeScript!");
使用方式:
打开终端,通过tsc fileName
编译转化为js
文件(注意你的当前目录所在)
这个时候你就会发现文件目录多出来一个index.js
文件
打开index.html
,控制台打印结果。或者也可以在终端node
执行index.js
文件
创建文件夹typescript
在终端初始化项目npm init -y
这个时候typescript
文件夹下会多出一个package.json
文件
终端局部安装npm install typescript
package.json文件夹里面会多出一个"typescript": "^4.7.2"
,这个就表示安装的typescript
版本是4.7.2
的
目录结构
在index.ts
中
console.log("Hello TypeScript!");
自动编译TypeScript
安装npm i ts-node-dev --save-dev
packages.json
中添加脚本
{
"name": "typescript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "ts-node-dev --respawn --transpile-only index.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"typescript": "^4.7.2"
}
}
在终端中使用npm start
启动
这样我们就不需要在修改index.ts
的同时还有一直在控制台输入node index.ts
,当你修改index.ts
保存后它就会自动执行。
类型 | 例子 | 描述 |
---|---|---|
number | 1,-33,2.5 | 任意数字 |
string | ‘hi’,“hi”,hi | 任意字符串 |
boolean | true、false | 布尔值 true 或 false |
字面量 | 其本身 | 限制变量的值就是该字面量的值 |
any | * | 任意类型 |
unknown | * | 类型安全的 any |
void | 空值(undefined) | 没有值(或 undefined) |
never | 没有值 | 不能是任何值 |
object | {name:“孙悟空”} | 任意的 JS 对象 |
array | [1,2,3] | 任意 JS 数组 |
tuple | [4,5] | 元组,TS 新增类型,固定长度数组 |
enum | enum{A,B} | 枚举,TS 中新增类型 |
number
:双精度64
位浮点值。它可以用来表示整数和分数
// 十进制
let a: number = 10; // 这里限制了a的数据类型为number
console.log(a); // 10
// 八进制
let b: number = 0o744;
console.log(b); //484
// 二进制
let c: number = 0b1010;
console.log(c); // 1010
// 十六进制
let d: number = 0xf00d;
console.log(d); // 61453
boolean
let a: boolean = false;
let b: boolean = true;
let c = true;
console.log(a, b, c);
string
let a: string = "hello";
setTimeout(() => {
a = "world";
console.log(a);
}, 2000);
console.log(a);
字面量:也可以使用字面量去指定变量的类型,通过字面量可以确定变量的取值范围
// 字面量类型 限制取值范围
// 传的参数的取值只能是 "red" | "green" | "yellow" | "blue" 不能是别的
const a = (b: "red" | "green" | "yellow" | "blue") => {
console.log(b); // red
};
a("red");
const foo = (n: 10 | 20 | 30 | "red") => {
console.log(n); // 10
};
foo(10);
any
// 任意类型
let a: any = "aaa";
a = 10;
a = false;
console.log(a); // false
unknown
// 不知道是什么类型
let a: unknown = "a";
a = 10;
console.log(a); // 10
tuple
// tuple 元组 类似js中的数组,它是元素可以是任意类型的
let x: [number, string];
x = [10, "hello"];
array
// array 数组
let arr: Array<any> = [1, 2, 3, "hello", true];
let arr1: Array<number> = [1, 2, 3];
let arr2: Array<Object> = [{ name: "Linux", age: 28 }];
console.log(arr); // [1, 2, 3, "hello", true]
console.log(arr1); // [1, 2, 3]
console.log(arr2); // [{ name: "Linux", age: 28 }]
enum
枚举
// 通常情况下我们使用枚举类型定义一类常量
enum Color {
red = "red",
blue = "blue",
}
console.log(Color.red); // red
console.log(Color.blue); // blue
// 枚举类可以作为变量的数据类型
let a: Color = Color.red;
// a = '' 警告
console.log(a); // red
类型断言(类型转换)
有些情况下,变量的类型对于我们来说是很明确,但是TS
编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,断言有两种形式
第一种
let a: unknown = "hello ts";
let lg: number = (a as string).length;
console.log(lg); // 8
第二种
let a: unknown = "hello ts";
let lgx: number = (<string>a).length;
console.log(lgx); // 8
函数定义
// 普通定义函数方式
function foo() {
console.log("foo"); // foo
}
foo();
// 声明式
const bar = function () {
console.log("bar"); // bar
};
bar();
函数返回值
我们会希望函数将执行的结果返回到调用它的地方,通过使用return
语句就可以实现。
在使用return
语句时,函数会停止执行,并返回指定的值。
注意:返回值的类型需要与函数定义的返回类型(return_type
)一致
// function function_name(): return_type {
// // 语句
// return value;
// }
function foo(): boolean {
return true;
}
console.log(foo()); // true
function bar(): Object {
return {
name: "foo",
age: 42,
};
}
console.log(bar()); // { name: 'foo', age: 42 }
// 没有返回值
function bo(): void {}
bo();
带参数函数
在调用函数时,您可以向其传递值,这些值被称为参数。
这些参数可以在函数中使用。
您可以向函数发送多个参数,每个参数使用逗号 , 分隔
function bar(a: number, b: string) {
console.log(a, b); // 10 hello
}
bar(10, "hello");
可选参数
在TypeScript
函数里,如果我们定义了参数,则我们必须传入这些参数,除非将这些参数设置为可选,可选参数使用问号标识 ?
可选参数必须跟在必需参数后面。 如果上例我们想让b
是可选的,a
必选,那么就要调整它们的位置,把b
放在后面。如果都是可选参数就没关系。
// 可选参数 ?
// 可选参数需要放在固定参数的后面
function foo(a: number, b?: string) {
console.log(a, b); // 10 undefined
}
foo(10);
默认参数
可以设置参数的默认值,这样在调用函数的时候,如果不传入该参数的值,则使用默认参数
// 参数的默认值
// 参数有了默认值,就可以不传,不传就以默认值为准
// 传了以实际值为准
function test(a: number, b: number = 10) {
console.log(a, b); // 10 10 // 10 20
}
test(10);
test(10, 20);
剩余参数
有一种情况,我们不知道要向函数传入多少个参数,这时候我们就可以使用剩余参数来定义。
剩余参数语法允许我们将一个不确定数量的参数作为一个数组传入。
// 剩余参数
function boo(a: number, ...args: any[]) {
console.log(a, ...args); // 10 [ 20, 30, 40 ]
}
boo(10, [20, 30, 40]);
匿名函数(函数表达式)
const msg = function () {
return "Hello";
};
console.log(msg()); // Hello
匿名函数自调用
(function () {
console.log("hello");
})();
Lambda
函数(箭头函数)
const a = (a: number, c: boolean = false, b?: string): number => {
console.log(a, b, c); // 10 "hello" true
return 10;
};
a(10, true, "hello");
联合类型(Union Types
)可以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值。
注意:只能赋值指定的类型,如果赋值其它类型就会报错。
语法:Type1|Type2|Type3
let a: number | string;
a = 10;
a = "hello";
console.log(a); // hello
联合类型数组
// 可以放入number类型和string类型的元素
let b: Array<number | string> = [];
b = [10, "hello", 20];
console.log(b);
// 只能同时放入number类型或者string类型
let c: number[] | string[];
c = [10, 20];
console.log(c); // [10, 20]
c = ["hello", "ts"];
console.log(c); // [ 'hello', 'ts' ]
const foo = (a: number | string): void => {
console.log(a); // 10 // hello
};
foo(10);
foo("hello");
TypeScript
是面向对象的JavaScript
类描述了所创建的对象共同的属性和方法。
TypeScript
支持面向对象的所有特性,比如 类、接口等
定义类的关键字为class
,后面紧跟类名,类可以包含以下几个模块(类的数据成员):
创建实例化对象
我们定义出来的类是可以作为类型去使用的
// 创建类
class Car {
// 字段[属性、成员变量]
brand: string;
timestamp: Date;
// 构造函数
// constructor 初始化参数
constructor(brand: string, timestamp: Date) {
this.brand = brand;
this.timestamp = timestamp;
}
// 方法(普通函数)
disp(): void {
console.log(`品牌:${this.brand}`);
}
// 箭头函数
sayHi = (name: string): string => {
console.log(name); // hello
return name;
};
}
// 创建对象的方式一
const car = new Car("法拉利", new Date());
console.log(car.brand, car.timestamp); // 法拉利 2022-05-26T10:36:54.145Z
car.disp(); // 品牌:法拉利
car.sayHi("hello");
// 创建对象的方式二
const baoma: Car = {
brand: "宝马",
timestamp: new Date(),
// 重写方法
disp() {},
sayHi(): string {
return "";
},
};
baoma.disp();
const foo = (car: Car) => {
console.log(car);
// Car {
// sayHi: [Function (anonymous)],
// brand: '法拉利',
// timestamp: 2022-05-28T02:08:48.847Z
// }
};
foo(new Car("法拉利", new Date()));
static
关键字
static
关键字用于定义类的数据成员(属性和方法)为静态的,静态成员可以直接通过类名调用
// 被 static 修饰的方法和属性 叫做静态方法和静态属性
// 静态方法和属性 在使用的时候需要被类直接调用 不需要实例化(不需要创建对象)
class Person {
static title = 10;
static sayHi() {
console.log("Hello"); // Hello
}
}
console.log(Person.title); // 10
// 可以赋值
console.log((Person.title = 20)); // 20
Person.sayHi();
instanceof
运算符
instanceof
运算符用于判断对象是否是指定的类型,如果是返回true
,否则返回false
访问控制修饰符
TypeScript
中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。TypeScript
支持3
种不同的访问权限
public
(默认) : 公有,可以在任何地方被访问。(写或不写都是public
)protected
: 受保护,可以被其自身以及其子类和父类访问。private
: 私有,只能被其定义所在的类访问TypeScript
支持继承类,即我们可以在创建类的时候继承一个已存在的类,这个已存在的类称为父类,继承它的类称为子类。
类继承使用关键字extends
,子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。
TypeScript
一次只能继承一个类,不支持继承多个类,但TypeScript
支持多重继承(Student
继承 Person
,Children
继承 Student
)。
继承类的方法重写
类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写。
其中super
关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHi = (): void => {
console.log(`${this.name}:我今年 ${this.age}`);
};
}
class Student extends Person {
constructor(name: string, age: number) {
super(name, age);
}
}
class Children extends Student {
constructor(name: string, age: number) {
super(name, age);
}
// 方法也可以被重写
sayHi = (): void => {
console.log("hi");
};
}
abstract
修饰的类,就是抽象类,抽象类又叫基类(父类)abstract
修饰的方法叫做抽象方法,被abstract
修饰的属性叫做抽象属性,抽象类在被被继承时,抽象方法和抽象属性必须重写abstract
修饰的方法和属性,在继承时必须重写,分别叫做抽象类和抽象方法abstract class Animal {
abstract name: string;
// 抽象方法不能有方法体
abstract speak(): void;
abstract say: () => void;
}
class Dog extends Animal {
// 抽象类在被被继承时,抽象方法和抽象属性必须重写
name: string;
constructor(name: string) {
super();
this.name = name;
}
speak(): void {
console.log(`${this.name}:汪汪汪`);
}
say = () => void {};
}
const dog = new Dog("泰迪");
console.log(dog);
dog.speak();
接口定义使用interface
关键字
接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性
需要注意接口不能转换为 JavaScript
。 它只是TypeScript
的一部分。
interface IPerson {
firstName: string;
lastName: string;
sayHi: () => void;
}
const customer: IPerson = {
firstName: "Tom",
lastName: "Hanks",
sayHi: (): string => {
return "Hi there";
},
};
interface IA {
a: string;
}
// 类实现接口 同时实现多个接口
class Student implements IPerson, IA {
firstName: string;
lastName: string;
a: string;
constructor(firstName: string, lastName: string, a: string) {
this.firstName = firstName;
this.lastName = lastName;
this.a = a;
}
sayHi = (): void => {
console.log(`${this.firstName}${this.lastName}`);
};
}
const stu = new Student("王", "五", "好");
stu.sayHi();
接口的实现使用implements
关键字
同一个类可以实现多个接口
抽象类也可以实现接口
接口不能实现接口,但可以使用extends
扩展
interface IPerson {
firstName: string;
lastName: string;
}
// 接口可以被扩展
interface IB extends IPerson {
age: number;
}
class Student implements IB {
age: number;
firstName: string;
lastName: string;
}