TypeScript精炼知识

385 阅读7分钟

变量类型固定明确,不再像以往的JS数值随意赋值,动态类型

以JS为基础,在其基础之上构建TS,是它的一个超集,动态语言=>静态语言 let a:string = "q"

Type,类型 提高可维护性

【注】TS不能被JS解析器(浏览器)直接执行,需要编译为JS,最终执行还是JS

基本类型

1. 类型声明(值限制)

  • 通过类型声明可以指定TS变量中变量(参数)的类型
  • let 变量:类型 = 值
  • let 变量 = 值 则类型由值确定 函数的参数不行,写默认值也可以fn(a = 1) a相当声明了number的类型
  • 函数参数需要声明变量类型 fn():number{ }返回值也可以限制类型

【注】TS=>JS可以编译为任意版本的JS文件,默认ES3

image-20211116154051849

2. 字面量声明类型

let a:10;//let a = 10 赋值一次就不能修改有点类似const 一般不用
let a:"A"|"B"//a只有两个取值
let a: boolean | string;//联合类型 要么布尔要么字符串
let a: number & string;//且,但是错误的,一般是多对象的交集

//any类型的变量可以赋值给任意类型的变量

3. any

let a: any//let a 一样 即声明变量不声明类型,则为any(隐式)
//a可以任意赋值,相当于关闭TS的该变量类型检查,不建议使用

4.unknown

let e: unknown //未知类型 类型安全 的any
e = 10;
e = "A";
//unknown类型的变量 无法直接赋值 给其他变量,除非 转类型
if(typeof e === "string"){
    s = e;
}
//类型断言
//变量 as 类型 | <类型>变量
s = e as string//确定其类型
s = <string>e

5. void

//undefined 空值  
function fn1  (msg = 1) : void{
};//没有返回值

6. never

//没有值 永远不会返回结果,有点类型null ,什么也没有,虚无
function fn() :never{
    throw new Error("报错");
}//调用直接报错,什么返回也没有,空值都没

7. object

//对象结构限制
let b: {name: string}//声明一个对象且内部含有 name 属性  属性写死了
let b: {name?: string,age?: number}//加上?表示该属性可选
let b: {name: string,[propName: string]: any}//只有name有要求,其他属性不做要求可有可无

//函数结构限制
let d: (a: number,b: number) => number;//该函数参数都是number,返回值也是number
d = function(n1: number,n2: number): number{
    retuen n1+n2;
}

8.array

//string[] 表示字符串数组,里面只能是字符串
let a: string[]
let a: number[]//Array<number>

9.tuple

//元组 固定长度 数组
let h:[string,string]

10.enum

//枚举
enum Gender{
    Male = 1,
    Female = 0
}
let i: {name: string,gender: Gender};
i = {
    name:"a",
    gender:Gender.Male
}
console.log(i.gemder === Gender.Male)//true

11.类型别名

type myType = string;//myType代替string
type myType = {
    name: string,
    age: number
};
type myNmuber = 1 | 2 | 3
let k: myNumber

编译选项

自动编译文件

  • tsc xxx -w
  • 每次更改ts文件都会自动编译,有点类似之前的nodemon
  • 每个文件都需要单独监视

通过创建tsconfig.json文件,对编译进行预配置,然后运行tsc,可以对所有.ts文件合并编译,且tsc -w是对所有文件监听

  1. include

    • //定义希望 被被编译文件 所在 目录
      //默认值["**/*"]  **任意目录  *任意文件
      //例子
      "include":["./src/**/*","./tests/**/*"]
      //所有src和test是目录下的文件都会被编译
      
  2. exclude

    • //排除不希望被编译的文件所在 目录
      //默认值["node_modules","bower_components","jspm_packages"]
      //例子
      "exclude":["./src/hello/**/*"]
      //hello目录下的所有文件都不会被编译
      
  3. extends

    • //定义被继承的配置文件
      //例子
      "extends":"./config/base"
      //即当前配置文件会自动包含base.json中的所有配置信息
      
  4. files

    • //指定 被编译文件 的 列表,只有需要编译的文件少时才会用到
      //例子
      "file":[
          "a1.ts",
          "b1.ts"
      ]
      //针对单个被编译文件
      
  5. compilerOptions

    • //该配置存在许多子选项配置,用来完成对编译的配置
      //target ts被编译为es的版本
      //module 指定要使用的模块化规范  commonjs ES6 ...
      //lib 指定项目中要使用的库 一般不用
      //outDir js文件的输出目录
      //outFile 代码合并为一个文件
      //allowJs 是否对js文件编译
      //checkJs 是否检查js代码是否符合ts语法规范 默认false
      //removeComments 是否移除注释
      //noEmit 不生产编译后文件 默认false
      //noEmitOnError 有错时 不生产编译后文件 比如不符合TS语法规范,直接不输出
      //strict 所有严格检查总开关
      //alwaysStrict 严格模式
      //noImplicitAny 为声明变量类型默认为any 默认false,true为不允许隐式any会提示
      //noImplicitThis 不允许隐式this
      //strictNullChecks 检查是否存在
      {
      "compilerOptions": {
              "target": "ES6",//对应版本
          	"module":"ES6",
          	"lib":["dom"]"outDir":"./dist",
          	"outFile":"./dist/app.js",// 全局作用域 中代码合并 模块合并需要module:"amd"|"system" 一般用webpack模块打包
          	"allowJs":true,//可以通过该方法转js文件的es版本 只能高转低
          }
      }
      

面向对象

一切操作都需要通过对象去完成,具体事物在程序中的抽象表示即对象

浏览器=>window

页面=>document

控制台=>console

在程序中所有的 对象 分成了两个部分 属性和方法 ,例如人有自己的名字、性别这些是数据,人可以说话、跑步这些是功能。

数据在对象中代表属性,功能在对象中代表方法。

1.类(class)

class 类名 {
    属性名:类型//类型声明
    //static 静态属性 不需要创建对象 就能访问
    //static name:string = "a"  类名.name
    //实例属性,需要 创建实例对象 才能访问
    // name:stirng = "a"   a = new 类名()a.name
    //只读属性 无法更改值  readonly name:string = "a"
    //可以结合static readonly
    constructor(参数:类型){//构造函数
        this.属性名 = 参数
    }
    方法名(){//也有static 变为类方法 可以直接调用不需要构建实例对象调用
        ...
    }
}

2.抽象类

不希望使用超类创建实例对象

abstract class 类 {
//该类不能创建对象
//专门用来继承,作为父类
    //抽象类中可以定义抽象方法
    //没有方法体,子类必须对其重写
    abstract fn():void
}

3.接口

//描述一个对象的类型
type myType = {//生成对象的属性限制
	name: string,
    age: number
}//不能重复声明 myType

/*接口 用来定义一个 类结构 包含哪些属性和方法,所有属实不能有实际值*/
//接口就是对类的一个 限制!
interface myInterface{
    name: stirng;//注意分号
    age: number;
}//可以重复使用同一接口,内容合并
interface myInterface{
    gender: string;
}
//别名用法
const obj: myInterface = {
    name: "s",
    age: 2,
    gender:"male"
}
//接口定义类,实现接口
class MyClass implements myInterface{
    name: stirng;
    age: number;
    gender: string;
    
    constructor(name:string,age:number,gender:string){
        this.name = name
        this.age = age
        this.gender = gender
    }
}
//语法糖写法
class MyClass implements myInterfence{

    constructor(public name:string,public age:number,public gender:string){

    }
}

4.属性的封装

避免实例对象的属性被任意更改,导致数据不安全

//属性修饰符
//public 修饰的属性可以在 任意位置 访问修改 默认

//private 当前类 的私有属性,继承类不能访问,只能在其内部进行修改,外部无法修改 TS独有,JS无所谓 一般加noEmitOnError:true直接无法编译
	//通过在类中添加 方法暴露私有属性 可以被外部访问
getName(){//读取属性
    return this.属性
}
setName(val:string){//可以通过该方法判断设置的数据是否符合规范,符合才设置
    this.name = val
}

//属性存取器
//TS中设置getter方法的方式
get name(){
    return tihs.name
}//实例对象.name直接调用该方法

set name(val:stirng){
    this.name = val
}//实例对象.name = "aaaa"

//protected 在继承类中和超类中被访问,在外部不能被访问

5.泛型

定义函数或者类时,若类型不明确则使用泛型

function fn<T>(a:T):T{//T为泛型,不用any
    return a
}

//直接调用
fn(10)//不指定类型,TS自动判断类型
fn<string>("aa")//指定类型,有点类似断言
//可以同时指定多个
function fn2<T,K>(a:T,b:K){
    return a
    console.log(b)
}
fn2<number,string>(10,"A")
//泛型T必须是Inter子类
interface Inter{
    age: number;
}

function fn3<T extends Inter>(a:T):number{
    return a.age
}
//类也可以指定泛型
class MyClass<T>{
    name: T
    constructor(name: T){
        this.name = name
    }
}

const m = new MyClass<string>("sss")