TypeScript
一、语言特性
- 类型批注和编译时类型检查
- 类型推断
- 接口
- 枚举
- 泛型编程
- 名字空间
- 元组
- 类
- 模块
- lambda 函数的箭头语法
- 可选参数以及默认参数
二 、TypeScript 基础语法
- 模块
- 函数
- 变量
- 语句和表达式
- 注释-ctrl+/
2.1 第一个TypeScript
(1)使用以下 TypeScript 程序来输出 “Hello World” :
const hello : string = "Hello World!"
console.log(hello)
(2)首先通过 tsc 命令编译:
tsc Runoob.ts
(3)最后我们使用 node 命令来执行该 js 代码
$ node Runoob.js
Hello World
(4)流程如下
图片:
注意我们也可以直接在vscode里面使用run code运行,实测没问题照样可以运行。
三、TypeScript 基础类型
3.1 Any 类型
任意值是 TypeScript 针对编程时类型不明确的变量使用的一种数据类型。
变量的值会动态改变时,比如来自用户的输入,任意值类型可以让这些变量跳过编译阶段的类型检查,示例代码如下:
let x: any = 1; // 数字类型
x = '王小明'; // 字符串类型
x = false; // 布尔类型
3.2 let 和 const
let 声明的变量只在 let 命令所在的代码块内有效。
let 变量名 = 变量值;
(1) 在相同的作用域或块级作用域中,不能使用let关键字来重置var关键字声明的变量:
var x=2;//合法
let x=3;//不合法
(2)在相同的作用域或块级作用域中,不能使用let关键字来重置let关键字声明的变量:
let x=2;//合法
let x=3;//不合法
{
let x=4;//合法
let x=5;//不合法
}
(3)在相同的作用域或块级作用域中,不能使用var关键字来重置let关键字声明的变量:
let x=2;//合法
var x=3;//不合法
{
let x=4;//合法
var x=5;//不合法
}
(4)let关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的:
let x=2;//合法
{
let x=3;//合法
}
{
let x=4;//合法
}
(5)const
const var x="wxm";
x="王松";//错误,const一旦声明就不能再更改了
四、 函数
使用完整函数类型定义,可以向函数发送多个参数,每个参数使用逗号 , 分隔:
4.1 命名函数
有完整的参数和返回类型
function add(x: number, y: number): number {
return x + y;
}
4.2 匿名函数
匿名函数是一个没有函数名的函数
//匿名函数
var msg = function() {
return "hello world";
}
console.log(msg())
4.3 可选参数
在 TypeScript 函数里,如果我们定义了参数,则我们必须传入这些参数,除非将这些参数设置为可选,可选参数使用问号标识 ?替代
//可选参数,必须放在必要参数后
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
let result1 = buildName("Bob"); // 正确
let result2 = buildName("Bob", "Adams", "Sr."); // 错误,参数太多了
let result3 = buildName("Bob", "Adams"); // 正确
根据错误提示,发现本函数最多输入两个参数
4.4 默认参数
函数本身带有默认值的参数,不传入该参数的值,则使用默认参数
function calculate_discount(price: number, rate=1) {
var discount = price * rate;
console.log("计算结果: ", discount);
}
calculate_discount(1000);
calculate_discount(1000, 0.30);
4.5剩余参数
当我们不确定参数个数时,剩余参数语法允许我们将一个不确定数量的参数作为一个数组传入。
function addNumbers(...nums:number[]) {
var i;
var sum:number = 0;
for(i = 0;i<nums.length;i++) {
sum = sum + nums[i];
}
console.log("和为:",sum)
}
addNumbers(1,2,3)
addNumbers(10,10,10,10,10)
4.6 箭头函数
Lambda 函数也称之为箭头函数。语句只有一行
var foo = (x:number)=>10 + x
console.log(foo(100)) //输出结果为 110
五、类的使用
类是属性和函数的集合,是生成对象或类实例的模板。
定义类的关键字为 class,后面紧跟类名:
5.1 定义
TypeScript 类定义方式如下:
class 类名{
// 类作用域
}
5.2 创建类的数据成员
以下实例我们声明了类 Car,包含字段为 engine,构造函数在类实例化后初始化字段 engine。this 关键字表示当前类实例化的对象。注意构造函数的参数名与字段名相同,this.engine 表示类的字段。此外我们也在类中定义了一个方法 disp()。
class Car {
// 字段
engine:string;
// 构造函数
constructor(engine:string) {
this.engine = engine
}
// 方法
disp():void {
console.log("发动机为 : "+this.engine)
}
}
5.3 创建实例化对象
(1)我们使用 new 关键字来实例化类的对象
var object_name = new class_name([ arguments ])
(2)类实例化时会调用构造函数
var obj = new Car("Engine 1")
(3)访问
// 访问方法
obj.function_name()
5.4 类的属性和函数的访问权限
类中的属性和函数都有访问权限,默认为public即全局可访问,其次为protected即可在类的内部和其子类的内部可访问,最后为private,只能在该类内部可访问。
如下实例
//访问权限
class MyInfo { //class是关键字,类名默认全部大写首字母
public name: string; //public属性,可省略
private _weather: string; //私有属性,习惯以_开头进行命名
constructor(name: string, weather: string){ //构造函数,一般用于初始化
this.name = name;
this._weather = weather;
}
printInfo(): void { //其它函数
this._test();
console.log(`Hello, ${this.name}.`);
console.log(`Today is ${this._weather}.`);
}
private _test(): void {
console.log('You can not call me outside!');
}
}
let myData = new MyInfo('QiGe', 'raining'); //使用new关键字生成对象
console.log(myData._weather); //error!
myData._test(); //error
myData.printInfo();
错误如图所示,私有属性不可直接访问
当在类外部时,可以通过设置get和set操作来获取private属性,这样更安全。
5.5 静态属性
static 关键字用于定义类的数据成员为静态的,静态成员可以直接通过类名调用。
class StaticMem {
static num:number;
static disp():void {
console.log("num 值为 "+ StaticMem.num)
}
}
StaticMem.num = 12 // 初始化静态变量
StaticMem.disp() // 调用静态方法
5.6 继承
可以通过extends关键字继承其它类,从而成为其子类。子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。
class Shape {
Area:number
constructor(a:number) {
this.Area = a
}
}
class Circle extends Shape {
disp():void {
console.log("圆的面积: "+this.Area)
}
}
var obj = new Circle(223);
obj.disp();
六 、模块Module
对于大型的项目,我们需要使用模块进行管理。每个 .ts 文件就是一个模块,通过 export 来对外部模块暴露元素,通过 import 来引入模块。
6.1 模块导出使用关键字 export 关键字
格式如下:
// 文件名 : SomeInterface.ts
export interface SomeInterface {
// 代码部分
}
6.2 要在另外一个文件使用该模块就需要使用 import 关键字来导入
格式如下:
import someInterfaceRef = require("./SomeInterface");
七、TypeScript 接口
接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现,让具体的类执行具体的方法。
7.1 TypeScript 接口定义
格式:
interface interface_name { }
实例
以下实例中,我们定义了一个接口Person,接着定义了一个变量 customer,它的类型是Person。customer 实现了接口 Person 的属性和方法。
interface IPerson {
firstName:string,
lastName:string,
sayHi: ()=>string
}
var customer:IPerson = {
firstName:"Tom",
lastName:"Hanks",
sayHi: ():string =>{return "Hi there"}
}
console.log("Customer 对象 ")
console.log(customer.firstName)
console.log(customer.lastName)
console.log(customer.sayHi())
var employee:IPerson = {
firstName:"Jim",
lastName:"Blakes",
sayHi: ():string =>{return "Hello!!!"}
}
console.log("Employee 对象 ")
console.log(employee.firstName)
console.log(employee.lastName)
如图所示
八、TypeScript 联合类型
联合类型(Union Types)可以通过’|'将变量设置多种类型,赋值时可以根据设置的类型来赋值。注意:只能赋值指定的类型,如果赋值其它类型就会报错。
8.1 创建联合类型的语法格式
声明一个联合类型:
Type1|Type2|Type3
8.2 联合类型作为函数参数
var val:string|number
val = 12
console.log("数字为 "+ val)
val = "wxm"
console.log("字符串为 " + val)
8.3 联合类型数组
可以将数组声明为联合类型:
var arr:number[]|string[];
var i:number;
arr = [1,2,4]
console.log("**数字数组**")
for(i = 0;i<arr.length;i++) {
console.log(arr[i])
}
arr = ["no1","no2","no3"]
console.log("**字符串数组**")
for(i = 0;i<arr.length;i++) {
console.log(arr[i])
}