TypeScript入门

300 阅读5分钟

一、TypeScript 是什么

TypeScript是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。

TypeScript 与 JavaScript 的区别
TypeScriptJavaScript
JavaScript 的超集用于解决大型项目的代码复杂性一种脚本语言,用于创建动态网页。
可以在编译期间发现并纠正错误作为一种解释型语言,只能在运行时发现错误
强类型,支持静态和动态类型弱类型,没有静态类型选项
最终被编译成 JavaScript 代码,使浏览器可以理解可以直接在浏览器中使用
支持模块、泛型和接口不支持模块,泛型或接口
支持 ES3,ES4,ES5 和 ES6 等不支持编译其他 ES3,ES4,ES5 或 ES6 功能
社区的支持仍在增长,而且还不是很大大量的社区支持以及大量文档和解决问题的支持

二、TypeScript 类型

基础类型
  • 常用:boolean、number、string、array、enum、any、void、unknown

  • 不常用:tuple、null、undefine、never

    注:如果我们使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。 通过将 any 类型改变为 unknown 类型,我们已将允许所有更改的默认设置,更改为禁止任何更改

对象类型

interface 和 type 的区别:type 更强大,interface 可以进行声明合并,type 不行。

数组类型
interface IItem {
  id: number;
  name: string;
  isDad: boolean;
}
const objectArr: IItem[] = [{ id: 1, name: '俊劫', isGod: true }];
const objectArr: Array<IItem> = [{ id: 1, name: '俊劫', isGod: true }];
const numberArr: number[] = [1, 2, 3];
const arr: (number | string)[] = [1, "string", 2];

三、TypeScript 接口

定义

在面向对象语言中,接口是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类去实现。 TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

interface Person {
  name: string;
  age?: number;
}
let Semlinker: Person = {
  name: "Semlinker",
  age: 33,
};
接口继承
interface Animal{
  eat():void;
}
interface Person extends Animal{
  work():void;
}
class Web implements Person{
  public name:string;
  constructor(name:string){
    this.name = name
  }
  eat(){
    console.log(this.name+'eat')
  }
  work(){
    console.log(this.name+'work')
  }
}

函数接口

interface Person{
  (name:string,age:number):string
}
var setData:Person = function(name:string,age:number):string{
  return name+age
}
setData('张三'18)

四、TypeScript 泛型

定义

泛型是允许同一个函数接受不同类型参数的一种模板。相比于使用 any 类型(放弃类型检查),使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型。 其实就是解决类、接口、方法的复用性、以及对不确定数据类型的支持。 泛型要求传入的参数和返回的参数一致。

function getData<T>(value:T):T{ // 第一个T表示指定函数类型,最后一个表示函数返回的类型
  return value;
}
getData<number>(123)
泛型接口
interface ConfigFn{
  <T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
  return value
}
getData<string>('张三')

五、TypeScript中的函数

function getInfo(name:string,age:number=20,...result:number[],sex?:string):string{
  return `${name}----${age}----${sex}`
}
  • 可选参数必须配置到参数的最后面,代码警告,可运行
  • 剩余参数用三点运算符

六、装饰器

定义

装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以修改类的行为。其实装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。

实现
  • 类装饰器:在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数,可以用来监视、修改或替换类定义。传入一个参数。类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
  • 属性装饰器:传入2个参数:静态成员就是类的构造函数,实例成员就是类的原型对象;成员名字。
  • 方法装饰器:传入3个参数:静态成员就是类的构造函数,实例成员就是类的原型对象;成员名字;成员的属性描述符
  • 方法参数装饰器:传入3个参数:静态成员就是类的构造函数,实例成员就是类的原型对象;参数名字;参数在函数参数列表中的索引
function logClass1(params:string){
  return function(target:any){
    console.log('类装饰器1')
  }
}
function logClass2(params:string){
  return function(target:any){
    console.log('类装饰器2')
  }
}
function logAttribute(params?:string){
  return function(target:any,attrName:any){
    console.log('属性装饰器')
  }
}
function logMethod(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法装饰器')
  }
}
function logParams1(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法参数装饰器1')
  }
}
function logParams2(params?:string){
  return function(target:any,attrName:any,desc:any){
    console.log('方法参数装饰器2')
  }
}
​
@logClass1('http://www.baidu.com')
@logClass2('xxx')
class HttpClient{
  @logAttribute()
  public apiUrl:string|undefined
  constructor{
    
  }
  @logMethod()
  getData(){
    return true
  }
  setData(@logParams1() attr1:any,@logParams2() attr2:any){
    return true
  }
}
var http:any = new HttpClient();
装饰器执行顺序

属性>方法>方法参数>类 如果有多个同样的装饰器,它会先执行后面的

七、TypeScript的优缺点

优点:
  • 代码的可读性和可维护性
  • 在编译阶段就发现大部分错误,避免了很多线上bug
  • 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、重构等
缺点:
  • 有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等不是很熟悉的概念
  • 会增加一些开发成本,当然这是前期的,后期维护更简单了
  • 一些JavaScript库需要兼容,提供声明文件,像vue2,底层对ts的兼容就不是很好
  • ts编译是需要时间的,项目大了以后,开发环境启动和生产环境打包的速度就成了考验