尚硅谷-TypeScript

尚硅谷-TypeScript,第1张

1. TypeScript简介

(1)TypeScript是什么?存在的意义是什么?

本质:是以js为基础构建的语言。
意义:在js的基础上最大的差别是引入了类型的概念。使js从动态类型的语言变为静态类型的语言。
注意:ts可以在任何支持js的平台中运行,但是ts不可以直接被js解析器执行,所以要将ts编译为js再执行。
ts优势:增添类型,支持es6,增添es不具备的新特性,丰富的配置选项,强大的开发工具。

2 TypeScript的环境搭建

(1)安装ts

npm i -g typescript

(2)编译ts
在终端

tsc 01-helloTS.ts

将ts文件转化为js

3 TypeScript的类型声明

1.变量声明

2.变量的赋值和声明同时进行的情况

3.函数中的变量声明

function sum(a:number,b:number){
    return a+b
}

console.log(sum(11,22))
//报错:类型“string”的参数不能赋给类型“number”的参数。t
console.log(sum(11,"123"))

4.函数返回值的类型

//表示函数返回值的类型是number
function add(a:number,b:number):number{
    return a+b
}
4 TypeScript中的类型
类型例子描述
number1,2,-33任意数字
string“hello”,“hi”任意字符串
booleantrue,false布尔值
字面量其本身限制变量的值就是该字面量的值
any*任意类型
unknown*类型安全的any
void空值(undefined)没有值(undefined)
never没有值不能是任何值
object{name:‘weijiamin’}任意的JS对象
array[1,2,3]任意JS数组
tuple[4,5]元素,TS新增类型,固定长度数组
enumenum(A,B)枚举类型,TS新增类型

例子
(1)字面量:

//a为字面量类型
let a:10
//报错:不能将类型“11”分配给类型“10”
a=11
let b:"mela"|"female"
b = 'mela'
b = 'female'
//报错:不能将类型“"nan"”分配给类型“"mela" | "female"”。
b = 'nan'

(2)any:任何类型

一个变量设置类型为any后,相当于对该变量关闭了TS的类型检查。
在使用TS过程中,不建议使用

//显式的any
let d:any
d=1
d='hello'
d=[1,2]
//隐式any
//在TS中如果不指定类型就会自动判断变量的类型为any
let d1
d1=1
d1="hello"

注意 any类型的数据可以赋值给其他类型的变量 并且不会报错

let a:10
a=d1//没有报错

(3)unknown

unknown:未知类型,实质是一个类型安全的any
和any的区别?unknown类型的数据不可以赋值给其他类型的变量

// unknown
let e:unknown
e=1
e="hello"
e=[1,2]

如何非要将unknown类型的变量赋值给其他类型的变量呢?

方法1

// unknown
let e:unknown
e=1
e="hello"
let e2:string
//进行类型判断 类型相同才赋值
if(typeof e === "string"){
    e2=e
}

方法2
(类型断言):可以用来告诉解析器变量的实际类型

// unknown
let e:unknown
e=1
e="hello"
let e2:string
//类型断言
e2=e as string
或者
e2=<string>e

(4)void

一般用于设置返回值的类型
可以取undefined null

//void表示为空,以函数为例,表示没有返回值
//可以取undefined null
function metod1():void{
    return undefined
}

(5)never

//never表示永远不会返回结果
function method2():never{
  throw new Error('报错了')
}

(6)object
用法1

JS中一切皆为对象

//object
let a:object
a={}
a=function (){}

用法2
指定对象的结构

这种指定的对象属性结构必须一模一样,不能多不能少

可以在属性中加上号表示可选属性:

//可选属性
let b1:{name:string,age?:number}
b1={name:'wei',age:11}
b1={name:'wei'}
要点1 设置对象结构的类型声明

可以添加指定属性以外的其他属性:

//添加其他属性
let b2:{name:string,[propName:string]:any}
b2={name:'wei',age:18,sex:"男"}
要点2 设置函数结构的类型声明

扩展 设置函数结构的类型声明
·
语法:(形参:类型,形参:类型)=>返回值类型
·
let b3:(a:number,b:number)=>number;

(7)array

要点3 设置数组结构的类型声明

方式1

//表示希望e是字符串类型的数组
let e:string[]
e=['1','2']

方式2

//表示希望e是数字类型的数组
let e2:Array<number>
e2=[1,2]

(8)tuple元组

tuple:固定长度的数组

//定义了长度为2的字符串数组
let h:[string,string]
h=['1','2']
// h=['1']//报错
// h=['1','2','3']//报错

(9)enum枚举

//定义枚举
enum Gender{
    male=0,
    female=1
}
let i:{name:string,gender:Gender}
i={
    name:'lihua',
    gender:Gender.male
}

扩展
(1)| (或)

let c:number | string

(2)& (且)

let j:{name:string}&{age:number}
j={name:'li',age:18}

(3)类型别名

type myType = string

let m:myType
type myType2 = 1|2|3|4|5
let m2:myType
let m3:myType

4 类型断言

// unknown
let e:unknown
e=1
e="hello"
let e2:string
//类型断言
e2=e as string
或者
e2=<string>e
5 TypeScript编译选项

(1)开启编译的监视模式(单个文件)

tsc app.ts -w

问题1:存在一定的时间间隔
问题2:其他文件的变化是不会被监视的

(2)使用tsc来编译所有文件

1.增加tsc的配置文件

2.终端中输入tsc–>回车

不开启监视模式


2.终端中输入tsc -w–>回车

开启监视模式

6 tsconfig.json配置选项(1)

tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译

(1)includ

用于指定哪些ts文件需要编译(默认情况下是目录下的所有ts文件都被编译)
/* 任意文件
/** 任意目录

    "include": [
        //只编译src下的任意目录的任意文件:只编译src下的所有文件
        "./src/**/*"
    ]

(2)exclude(一般情况下不需要设置)

用于指定哪些ts文件不被编译
默认值:[“node_modules”,“bower_components”,“jspm_packages”]

    "exclude": [
        //除了src/hello目录下的文件不编译,其他的文件都编译
        "./src/hello/**/*/"
    ]

(3)extends(一般不用)

定义继承的配置文件

(4)files(一般不用)

指定编译文件的列表,只在编译文件量少的时候才用到

    "files": [
        "typse.ts",
        "hello.ts",
        "binder.ts"
    ]
7 tsconfig.json配置选项(2)

compilerOptions

编译器的选项,决定了编译器如何对ts文件进行编译

  "compilerOptions": {
        //用于指定ts被编译为的ES的版本
        "target": "ES6",

        // module 指定要使用的模块化的规范
        "module": "ES6",

        //lib:用于指定项目中需要使用的库 【一般不用配置】
        // "lib": [],

        //outDir 指定编译后文件所在的目录
        "outDir":"./dist",

        // 将编译后的文件合并到一个文件中 【一般不用配置】
        // "outFile": "./dist/app.js"

        //所有严格检查的总开关 【建议为true】
        "strict": false,

        //是否对js文件进行编译 默认为fasle
        "allowJs": false,

        //是否检查js代码是否符合ts语法的规范 默认为false
        "checkJs": false,

        //是否移除注释 默认为false
        "removeComments": false,

        //不生成编译后的文件 默认为fasle
        "noEmit": false,

        //当有错误的时候不生成编译后的文件 默认为fasle
        "noEmitOnError": false,

        // 用来设置编译后的文件是否使用严格模式
        // 当有模块化代码的时候 js自动进入严格模式
        "alwaysStrict": true,

        //不允许隐式的any类型
        "noImplicitAny": true,

        //不允许不明确类型的this
        "noImplicitThis": true,

        //严格的检查空值
        "strictNullChecks": true,
    },
8 webpack打包ts文件(1)

(1)下载依赖的包

npm init
npm i webpack-cli -g
npm i webpack-cli -D
npm i -g typescript
npm i ts-loader

(2)webpack.config.js

//引入一个包
const path = require('path')

//webpack的配置信息
module.exports = {
    //入口文件
    entry:'./src/index.ts',
    //打包完成后放在哪里
    output:{
        path:path.resolve(__dirname,'dist'),
        //打包后文件名
        filename:"build.js"
    },
    //指定webpack打包时使用的模块
    module:{
        //指定要加载的规则
        rules:[
            {
                //指定规则生效的文件
                test:/\.ts$/,
                //要使用的loader
                use:'ts-loader',
                exclude:/node-modules/
            }
        ]
    }
}

(3)tsconfig.json

// tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译

{
    "compilerOptions": {
        "target": "ES2015",
        "module": "ES2015",
        "strict": true
    },
}
8 webpack打包ts文件(2)

(1) html文件生成和打包

npm i html-webpack-plugin -D

作用:自动的生成html文件并且引入相关的资源

//引入html插件
const HtmlWebpackPlugin = require('html-webpack-plugin')


plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        }),
    ]

(2)webpack-dev-server

npm i webpack-dev-server -D

修改package.json

(3)在webpack打包前先删除之前的包

npm i clean-webpack-plugin -D
//引入clean插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

plugins:[
  new CleanWebpackPlugin()
]
8 webpack打包ts文件(3)

兼容性配置 babel
(1)下载依赖的包

npm i @babel/core @babel/preset-env babel-loader core-js -D

(2)webpack.config.js配置

rules:[
            {
                //指定规则生效的文件
                test:/\.ts$/,
                //要使用的loader
                use:[
                    //配置babel
                    {
                        //指定加载器
                        loader:'babel-loader',
                        //设置babel
                        options:{
                            //设置预定义的环境
                            presets:[
                                [
                                    //指定环境插件
                                    "babel/preset-env",
                                    //配置信息
                                    {
                                       //要兼容的目标浏览器
                                       targets:{
                                           "chrome":"88"
                                       },
                                       //指定corejs的版本
                                       "corejs":"3",
                                       //使用corejs的方式 "usage":按需加载
                                       "useBuiltIns":"usage"
                                    }
                                ]
                            ]
                        }
                    },
                    'ts-loader',
                ],
                exclude:/node-modules/
            }
9 面向对象

什么是对象?
一切皆对象,程序中的所有 *** 作都需要对象来完成

9-1 类

类就是对象的模型

(1)类

class Person{
}

const per=new Person()

console.log(per)

(2)类的属性

名称描述例子
实例属性直接定义的属性,通过实例对象访问。可读可写name:string=‘wei’
静态属性 (类属性)无需创建实例对象,直接通过类访问。可读可写static staticAge:number
只读属性(ts特有)直接定义的属性,通过实例对象访问。只读readonly sex:string=“nv”
静态只读属性(ts特有)无需创建实例对象,直接通过类访问。只读static readonly staticAge:number
//定义属性
class Person2{
    //类的实例属性
    name:string='wei'
    age:number=18
    //类的静态属性
    static staticAge:number=5
    //只读属性
    readonly sex:string="nv"
    //静态只读属性
    static readonly staticName:Person = 'liu'
}
const per2=new Person2()
console.log(per2)
//访问类的实例属性
console.log(per2.age)
//访问类的静态属性
console.log(Person2.staticAge)

(3)类的方法

//定义方法
class Person3{
    //定义实例方法
    sayhello(){
        console.log('hello')
    }
    //定义类方法
    static sayhello(){
        console.log('static hello')
    }
}
const per3=new Person3()
per3.sayhello()
Person3.sayhello()
9-2 构造函数和this

this:表示当前的实例

class Dog{
    name: string;
    age: number;
    //构造函数:在对象创建的时候调用
    constructor(name:string,age:number){
        //this:表示当前的实例
        this.name=name;
        this.age=age;
    }
    brak(){
        console.log(this.name+'汪汪汪')
    }
}

const dog = new Dog('xiaohei',4)
console.log(dog)
dog.brak()
9-3 继承
class Personn{
    name: string;
    age: number;
    constructor(name:string,age:number){
        this.name=name
        this.age=age
    }
    sayHello(){
        console.log(this.name+'hi')
    }
}

const per11=new Personn('lihua',18)
per11.sayHello()

//继承Person类
//使用继承后子类将会具有父类的所有属性和方法
class Student extends Personn{
    score:number
    constructor(name:string,age:number,score:number){
        //在子类中写了构造函数相当于覆盖了父类的构造函数,此时就要在子类的构造函数中调用父类的构造函数
        super(name,age);
        //新增的属性
        this.score=score
    }
    //新增的方法
    showScore(){
        console.log('我的成绩是'+this.score)
    }
    showName(){
        //在类的方法中super就相当于是当前类的父类
        super.sayHello()
    }
}

const student1=new Student('lihua',18,80)
student1.showScore()
//调用父类的方法
student1.sayHello()
9-4 抽象类

abstract 声明的类为抽象类:
与其他类区别不大只是不能用于创建对象
抽象类的作用就是用于被其他类继承

abstract class Personn11{
    name: string;
    age: number;
    constructor(name:string,age:number){
        this.name=name
        this.age=age
    }
    sayHello(){
        console.log(this.name+'hi')
    }
}

抽象类可以添加抽象方法:
抽象方法没有方法体,只能定义在抽象类中,子类必须对抽象方法进行重写

abstract class Personn11{
    name: string;
    age: number;
    constructor(name:string,age:number){
        this.name=name
        this.age=age
    }
    sayHello():void{
        console.log(this.name+'hi')
    }
    abstract sayAge():void;
}
class Student11 extends Personn11{
    //重写抽象方法
    sayAge(){
        console.log(111)
    }
}
9-5 接口

接口:
1.用于定义一个类的结构应该包含哪些属性和方法,同时接口也可以当做类型声明来使用
2.接口可以重复声明,相当于在之前的类型声明基础上增加属性
3 注意: 接口中所有的属性在定义的时候都不可以有实际的值

//描述一个对象的类型
    type myType = {
        name:string,
        age:number
    }

    /*
    接口:用于定义一个类的结构应该包含哪些属性和方法
          同时接口也可以当做类型声明来使用
         
     */
    interface myInterFace{
        name:string,
        age:number,
    }
    //接口可以重复声明,相当于在之前的类型声明基础上增加属性
    interface myInterFace{
        sex:string,
        //接口中所有的属性在定义的时候都不可以有实际的值
        sayHello():void;
    }
    const obj:myInterFace={
        name:'lihua',
        age:111,
        sex:'male',
        sayHello(){
            console.log('hello')
        }
    }

定义类时可以使用类去实现一个接口

    interface myInter{
        name:string,
        sayHello():void;
    }
    class MyClass implements myInter{
        name: string;
        constructor(name){
            this.name=name
        }
        sayHello(){
            console.log('大家好')
        }

    }

接口:实际上就是定义了一个类的规范

9-6 属性的封装

属性是在对象中设置的,属性可以任意被修改,会出现安全问题

    //定义一个表示人的类
    class Person{
        name:string;
        age:number;
        constructor(name,age){
            this.name=name;
            this.age=age
        }
    }
    const pre = new Person('xiaozhang',18)
    console.log(pre)

    /*
    现在的属性是在对象中设置的,属性可以任意被修改,会出现安全问题
    */
   pre.age = 22

TS可以在属性前加上属性的修饰符
* public :公共的,共有的,可以在任意位置修改【默认值】
* private :私有的,只能在类内部进行访问,修改
* protected :受保护的属性,只能在当前类和其子类中使用

    class Person2{
         private _name:string;
         private _age:number;
        constructor(name,age){
            this._name=name;
            this._age=age
        }
    }
    const pre2 = new Person2('xiaozhang',18)
    console.log(pre)

    pre2.age = 22//报错

通过在类中添加方法:使私有属性可以在外部被访问

    class Person2{
         private _name:string;
         private _age:number;
        constructor(name,age){
            this._name=name;
            this._age=age
        }
        //定义一个方法用于获取name属性
        getName(){
            return this._name
        }
    }
    const pre2 = new Person2('xiaozhang',18)
    console.log(pre2.getName())

通过在类中添加方法:使私有属性可以在外部被修改

    class Person2{
         private _name:string;
         private _age:number;
        constructor(name,age){
            this._name=name;
            this._age=age
        }
        //定义一个方法用于修改name属性
        setName(value:string):void{
            this._name=value
        }
        //定义一个修改年龄的方法
        setAge(value:number):void{
            if(value >=0 && value<=120){
                this._age=value
            }else{
                alert('输入年龄错误')
            }
        }
    }
    const pre2 = new Person2('xiaozhang',18)
    per2.setName('lihua')
getter方法用于读取方法
setter方法用于存储方法
称为属性的【存取器】

存储器方法:TS提供更加灵活的方式用于存取属性

    class Person2{
        private _name:string;
        private _age:number;
        constructor(name,age){
            this._name=name;
            this._age=age
        }
        //存储器方法get 获取属性
        get name(){
            return this._name
        }
        //存储器方法set 设置属性
        set name(value:string){
            this._name=value
        }
    }
    const pre2 = new Person2('xiaozhang',18)
    //调用存储器方法获取name
    console.log(per2.name)
    //调用存储器方法设置name
    pre2.name='lihua'

可以直接将属性定义在构造函数中

class Person2{
  constructor(private _name:string,private _age:number){
    this._name=_name;
    this._age=_age;
  }
}
9-7 泛型

1.定义泛型

在定义函数或类的时候,如果遇到的类型不明确就可以使用泛型

function fn2<T>(a:T):T{
    return a
}

2.调用泛型

可以直接调用具有泛型的函数

fn2(10);不指定泛型 ts进行自动推断
fn2<string>('hello')指定泛型 

3.同时定义多个泛型

function fn3<T,K>(a:T,b:K):T{
    console.log(b)
    return a
}

fn3(123,456)
fn3<number,string>(123,'456')

3.在函数中使用泛型

interface Inter{
    length:number;
}
function fn4<T  extends Inter>(a:T):number{
    return a.length;
}
fn4({length:15})

4.在类中使用泛型

class MyClass<T>{
    name:T;
    constructor(name:T){
        this.name=name
    }
}
const myclass=new MyClass<string>('lihua')
10 TS开发练习

TS思想:任何东西都要写在类中

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1320815.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-11
下一篇 2022-06-11

发表评论

登录后才能评论

评论列表(0条)

保存