TypeScript

什么是 TypeScript

TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript的基础上添加静态类型定义构建而成。TypeScript通过 TypeScript编译器或 Babel 转译为 JavaScript代码,可运行在任何浏览器,任何操作系统。TypeScript 是 JavaScript 的超集

超集 : 如果一个集合S2中的每一个元素都在集合S1中,且集合S1中可能包含S2中没有的元素,则集合S1就是S2的一个超集,反过来,S2是S1的子集。 S1是S2的超集,若S1中一定有S2中没有的元素,则S1是S2的真超集,反过来S2是S1的真子集。 例如 :sass是 css的超集 C++是 C 语言的超集

为什么要学 TypeScript

  • JavaScript对变量的类型比较宽容,他不会要求你声明变量时指定变量的类型。所以普遍前端开发者都会缺少类型思维。没有类型的语言其实是不利于大型项目的开发的。
  • 100%兼用 JavaScript代码,无需修改平滑迁移
  • TypeScript 让我们的代码更可靠更清晰。

TypeScript 环境依赖及开发环境的构建

依赖

安装 TypeScript 之间需要安装 node 环境

有时间写一个 详细的过程配置

安装完成后测试是否安装成功
TypeScript_第1张图片

TypeScript_第2张图片

当版本号显示正常说明安装成功

安装 TypeScript

终端:
npm install typescript -g	// 安装TypeScript

tsc --version				// 查看版本号

npm init -y					// 项目初始化

tsc --init 					// 生成 tsconfig.json 文件
tsconfig.json 将 ts 转换为 js 的一个配置文件

npm install @types/node --dev-save
该依赖是在开发环境中解决模块声明文件问题

TypeScript 语法

创建 TypeScript 文件(后缀为ts)
TypeScript_第3张图片

// TypeScript 支持强类型,所以我们声明一个变量a可以给它加上类型
var a:string = "HelloWorld"  
console.log(a) 

TS 转 JS

要运行 TypeScript 需要转换为 JavaScript

  • 首先将 tsconfig.jsonoutDir 改为 js的输出路径
    TypeScript_第4张图片

  • vscode 配置任务,运行任务

点击终端 ----- 点击运行任务 ----- 选择 tsc 监视

TypeScript_第5张图片

使用 tsc 加文件名可以运行 ts 文件 然后生成 js 文件

TypeScript_第6张图片

有了 js 文件,我们就可以在终端使用node来运行它了

在这里插入图片描述

TypeScript 的数据类型

TypeScript 中的数据类型有Undefined、Number(数值类型)、string(字符串类型)、Boolean(布尔类型)、enum(枚举类型)、any(任意类型)、void(空类型)、Array(数组类型)、Tuple(元祖类型)、Null(空类型)。

TypeScript 相对于 JavaScript 增加了新的数据类型,这些数据类型只用于 TypeScript 环境下,当TypeScript 编译成 JavaScript 的时候,会去掉 TypeScript 中的新类型 转变成 JavaScript 中的数据类型。

1、Undefined 类型

当定义了一个变量,没有给这个变量进行赋值,那这个变量中有一个默认值 undefined,undefined 就是 Undefined 类型。

let a: number;
console.log(a);  //输出undefined

2、Number 类型

和JavaScript一样,TypeScript里的所有数字都是浮点数。 这些浮点数的类型是 number。

let b: number = 10; // 整数
let c: number = 2.13 // 浮点数

在 TypeScript 中存在以下几种特殊的 Number 类型数据:

  • NaN:不是数字(Not a Number)。如果一个计算结果或者函数的返回值本应该是数字,但是不是数字,在 TypeScript 中并不会报错,而是把它的结果设置成NaN;
  • nfinity:正无穷大;
  • -Infinity:负无穷大。

3、string 字符串

由单引号’'或者双引号""括起来的一串字符就是字符串。

let d: string = "lanbots";  //输出 lanbots
let e: string = 'linbots';  //输出 linbots

你还可以使用模版字符串,它可以定义多行文本内嵌表达式。 这种字符串是被``包围 ,并且以${ expr }这种形式嵌入表达式

let name: string = "lanbots";
let age: number = 23;
let sentence: string = `my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;

这与下面定义sentence的方式效果相同:

let sentence: string = "my name is " + name + ".\n" +
"I'll be " + (age + 1) + " years old next month.";

4、boolean 布尔类型

在程序中我们经常碰到这样的情况:判断条件是否成立,判断对错。这样的结果无非就是两种情况:是,否。表示这种情况的变量就是布尔类型(boolean),其数值有 true 和 false。

let a: boolean = false; // Boolean类型,编译通过
let b: boolean = 0; // Boolean类型,使用数字赋值,编译失败

5、enum 枚举

当出现以下这种情况:

  • 表示饮料杯的类型:小杯、中杯、大杯,有三种结果;
  • 表示彩虹的颜色:赤橙黄绿青蓝紫,有七种结果;
  • 表示四季:春夏秋冬,有四种结果。

这种变量的结果可能是固定的几种数据,我们使用枚举类型表示。

//表示四季这种情况 定义一个枚举类型的变量  定义枚举的关键字是enum
//一般枚举类型的变量 用大写字母表示
enum SEASON{
    SPR,//结果一般也用大写字母表示
    SUM,//结果之间用逗号隔开
    AUT,
    WIN
}
console.log(SEASON.SPR);//0

enum CUP_TYPE{
  //在ts中会给每一个可能的结果赋值一个整数 方便在计算机中存储和使用 默认是0
  SMALL_CBIG_CUP_TYPE = 1MID_CUP_TYPE,//2
  BIG_CUP_TYPE // 3
}
console.log( CUP_TYPE.MID_CUP_TYPE);


如果我们要打印出来内容,应该怎么操作呢?

enum SEASON{
    SPR="春",
    SUM="夏",
    AUT="秋",
    WIN="冬"
}
console.log(SEASON.SPR);//春

TypeScript_第7张图片

6、Any

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量:

let a: any;
a = 23;
a = "lanbots";//a可以再次赋值任意类型的值
console.log(a); //输出lanbots 

TypeScript_第8张图片

7、Void

某种程度上来说,void类型像是与any类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void:

function warnUser(): void {
    alert("This is my warning message");
}

声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined和null

let unusable: void = undefined;

8、Never

never类型表示的是那些永不存在的值的类型。 例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。

never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。 即使 any也不可以赋值给never

9、类型断言

类型断言(Type Assertion)可以用来手动指定一个值的类型

有的时候在联合类型的时候,只能访问联合类型的共有方法或者属性,但是这个时候是不够用的。这个时候就要自己手动断言成某个类型。断言不是改变某个类型,不是类型转换。这个时候能让取到你断言成的类型的方法。

类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的
function getLength(something: string | number): number {
    if (something.length) {
        return something.length;
    } else {
        return something.toString().length;
    }
}

// index.ts(2,19): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.
// index.ts(3,26): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.

上例中,获取 something.length 的时候会报错。
此时可以使用类型断言,将 something 断言成 stringfunction getLength(something: string | number): number {
    if ((<string>something).length) {
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}

类型断言有两种形式。 其一是“尖括号”语法:

let someValue: any = "this is a string";
<类型>let strLength: number = (<string>someValue).length;

另一个为as语法:

let someValue: any = "this is a string";as 类型
let strLength: number = (someValue as string).length;

两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在TypeScript里使用JSX时,只有 as语法断言是被允许的。

TypeScript 函数

函数的定义

功能相近、多次使用,根据参数呈现不同结果的独立代码块

function searchXiaoJieJie(age:number):string {  
  return '找到了'+age +'岁的小姐姐'  
}
var age:number = 18;  
var result:string=searchXiaoJieJie(age)  
console.log(result) // 找到了18岁小姐姐

注意

  • 必须使用 function这个关键字来定义一个函数
  • 函数名和变量名都是一样的(都需要遵循加类型的规则)
  • 函数的参数可有可无
  • 如果参数有多个,用都好隔开

形参(形式上的参数)实参(真实传递的参数)

  • 可选参数的函数
function searchXiaoJie Jie(age:number,status?:string):string {  
  let yy:string=''  
  yy='找到了'+age+'岁'  
  if(status!=undefined){  
    yy = yy +status   
  }
  return yy+'的小姐姐'  
}
var result:string=searchXiaoJieJie(22,'大长腿')  
console.log(result) 
  • 有默认参数的函数
function searchXiaoJieJie(age:number=18,status:string='小蛮腰'):string {  
  let yy:string=''  
  yy='找到了'+age+'岁'  
  if(status!=undefined){  
    yy = yy +status  
  }
  return yy+'的小姐姐'  
} 
var result:string=searchXiaoJieJie()  
console.log(result) //找到了18岁小蛮腰的小姐姐(不传参)

var result:string=searchXiaoJieJie(22,'大长腿') 
console.log(result) //找到了22岁大长腿的小姐姐(传参)
  • 当我们的需求是不确定的,我们可以这样写
function searchXiaoJieJie(...xuqiu:string[]):string {  
  let yy:string='找到了'  
  for(let i=0;i<xuqiu.length-1;i++) {  
    yy = yy +xuqiu[i]   
    if(i<xuqiu.length){  
      yy = yy + '、'  
    }
  }
  yy=yy+'的小姐姐'  
  return yy   
} 
var result:string=searchXiaoJieJie('22岁','大长腿','瓜子脸','小蛮腰')  
console.log(result) // 找到了22岁、大长腿、瓜子脸、的小姐姐

函数的三种定义方式

+函数声明法(常用)

function add(n1:number,n2:number):number{   
  return n1+n2   
} 
console.log(add(1,2))
  • 函数表达式法

先声明一个变量,直接把这个函数赋值给变量,那么这个变量就是函数名,通过变量名可以调用这个函数

注意:定义之后要调用,否则会报错

var add = function(n1:num ber,n 2:number):number{  
  return n1+n2  
}
console.log(add(1,3)) 
  • 箭头函数

利于回调,函数都有作用域

var add=(n1:number,n2:number):number=>{   
  return n1+n2 //this   
}
console.log(add(3,5) 

模块化

利用TypeScript的关键词module,可以达到类似于命名空间的效果,而export可以控制是否被外部访问。

TypeScript_第9张图片

  • module可以嵌套,访问时用.作分隔符,也可以用.作为分隔符来简写module的嵌套;
  • 只有带关键词export的才可以被外部访问;
  • module可以合并,但是非export的对象在其他module下,即使是同一个名称,也不能被访问,如funcA()

基本语法

// 通过class创建类
class Animal {
    // 类的属性
    name: string;
    // 类的构造器
    constructor(name: string) {
        this.name = name;
    }
    // 类的方法
    sayHello():void{
        alert("hello animal:"+this.name);
    }
}
// 实例化类
var tom = new Animal("tom");
tom.sayHello();

类的继承

// 通过class创建类
class Animal {
    // 类的属性
    name: string;

    // 类的构造器
    constructor(name: string) {
        this.name = name;
    }

    // 类的方法
    sayHello(): void {
        alert("hello animal:" + this.name);
    }
}

// 继承Animal
class Cat extends Animal {
    // 重写方法
    sayHello(): void {
        alert("hello cat:" + this.name);
    }
}

class Dog extends Animal {
    sayHello(): void {
        alert("hello dog:" + this.name);
    }
}

修饰符

class Animal {
    private name: string; // 这里把name修饰符改为private

    constructor(name: string) {
        this.name = name;
    }

    sayHello(): void {
        alert("hello animal:" + this.name);
    }
}

class Cat extends Animal {
    sayHello(): void {
        alert("hello cat:" + this.name); //这里会报错,因为无法引用父类private修饰的属性
    }
}

class Dog extends Animal {
    sayHello(): void {
        alert("hello dog:" + this.name); //这里会报错,因为无法引用父类private修饰的属性
    }
}

当把属性的修饰符改成私有时,子类继承以后便会报错。那么如何解决呢?看下一节。

Get/Set访问器

class Animal {
    private name: string;

    get name(): string { //通过get和set解决子类不能引用父类private修饰的属性的问题
        return this.name;
    }

    set name(name: string) {
        this.name = name;
    }

    constructor(name: string) {
        this.name = name;
    }

    sayHello(): void {
        alert("hello animal:" + this.name);
    }
}

class Cat extends Animal {
    sayHello(): void {
        alert("hello cat:" + this.name); 
    }
}

class Dog extends Animal {
    sayHello(): void {
        alert("hello dog:" + this.name); 
    }
}

静态属性

class Table {
    static width: Number = 100;
    static height: Number = 50
}

var width: Number = Table.width;

你可能感兴趣的:(前端积累,typescript,javascript)