typescript

安装

安装

npm install -g typescript

检测安装是否成功

tsc -V

编译

手动编译

对于 xxx.ts 文件,执行

tsc xxx.ts

输出为 xxx.js 文件,将ts文件里面的代码转成js代码
通过node.js 运行代码

node xxx.js

自动编译

1). 生成配置文件tsconfig.json
    tsc --init
2). 修改tsconfig.json配置
    "outDir": "./js",    ts文件编译后的js文件会在./js目录下
    "strict": false,     非严格模式 
3). 启动监视任务: 
    终端 -> 运行任务 -> 监视tsconfig.json

webpack打包

下载依赖package.json

{
    "name": "ha",        // 自命名
    "version": "0.1.0",
    "description": "",
    "main": "index.js",
    "scripts": { 
        // 配置打包命令
        "dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
        "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@types/jquery": "^3.5.4",     // 下载jquery的声明文件
        "clean-webpack-plugin": "^3.0.0",
        "cross-env": "^7.0.2",
        "html-webpack-plugin": "^4.5.0",
        "ts-loader": "^8.0.11",
        "typescript": "^4.0.5",
        "webpack": "^4.41.5",
        "webpack-cli": "^3.3.10",
        "webpack-dev-server": "^3.10.2",
        "jquery": "^3.6.0"  // 安装jquery
    }
}

入口JS: src/main.ts

document.write('Hello Webpack TS!')

index页面: public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>webpack & TS</title>
</head>
<body>
  
</body>
</html>

build/webpack.config.js

const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')

const isProd = process.env.NODE_ENV === 'production' // 是否生产环境

function resolve (dir) {
    return path.resolve(__dirname, '..', dir)
}

module.exports = {
    mode: isProd ? 'production' : 'development',
    entry: {
        app: './src/main.ts'
    },

    output: {
        path: resolve('dist'),
        filename: '[name].[contenthash:8].js'
    },

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                include: [resolve('src')]
            }
        ]
    },

    plugins: [
        new CleanWebpackPlugin({
        }),

        new HtmlWebpackPlugin({
            template: './public/index.html'
        })
    ],

    resolve: {
        extensions: ['.ts', '.tsx', '.js']
    },

    devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map',

    devServer: {
        host: 'localhost', // 主机名
        stats: 'errors-only', // 打包日志输出输出错误信息
        port: 8089,
        open: true
    },
}

运行与打包

与配置的命令有关

"scripts": { 
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}

npm run dev
npm run build

类型注解

function greeter (person: string) {
  return 'Hello, ' + person
}

let user = 'Yee'

console.log(greeter(user))

约束变量person的类型为string,编译时即使存在错误,也会生成相应的js文件

基础类型

基本语法: let 变量名:数据类型 = 值

boolean

let boo1:boolean = true;
let boo2 = false;
console.log(boo1,'--',boo2) // true "--" false

number

let num1: number = 10      // 十进制
let num2: number = 0b1010  // 二进制
let num3: number = 0o12    // 八进制
let num4: number = 0xa     // 十六进制
console.log(num1,'-',num2,'-',num3,'-',num4) // 10 "-" 10 "-" 10 "-" 10

string

let name:string = 'tom'
console.log(`My name is ${name}, I am ${num1} years old!`) // My name is tom, I am 10 years old!

undefined null

undefined null 可以被赋值给任意类型,算是其他类型的子类型(非严格模式)

let un1: undefined = undefined
let nu1: null = null
num1 = null
console.log(un1,'-',nu1) // undefined "-" null
console.log(`num1=${num1}`) // num1=null

数组 array

语法:

  • let 变量名: 数据类型[] = [值...]
  • let 变量名: Array<数据类型> = [值...]

值的类型必须是定义的数据类型,否则会报错

let arr1: number[] = [1,2,3]
let arr2: Array<number> = [4,5,6]
console.log(arr1,'---',arr2) // (3) [1, 2, 3] "---" (3) [4, 5, 6]

元祖 tuple

定义数组的时候限定数据的位置、类型与个数

let arr3: [string, number, boolean] = ['haha',10,true]
console.log(arr3) // (3) ["haha", 10, true]

枚举

枚举里面的每个数据都可以称为元素,每个元素都有自己的编号,默认从0开始,依次递增,也可以自定义,元素可以是中文(不推荐)

enum Color{
    red = 10,
    绿 = 9,
    blue,
    orange
}
let color: Color = Color.blue
console.log(color,'-',Color.绿,'--',Color.red) // 10 "-" 9 "--" 10
console.log(Color) // {9: "绿", 10: "blue", 11: "orange", red: 10, 绿: 9, blue: 10, orange: 11}

any

不确定具体类型时使用,也可用于数组中(any[] 或者 Array<any>)

let any1: any = 1
any1 = 'haha'
console.log(any1) // haha

// let any2: any[] = [100,'jjadsasdfghj',true]
let any2: Array<any> = [100,'jjadsasdfghj',true]
console.log(any2[1].split('')) 
// console.log(any2[0].split(''))
// 编译时不会报错,但在浏览器中会报错Uncaught TypeError: any2[0].split is not a function

void

函数声明的时候,在小括号的后面使用:void,表示该函数没有返回值

function show(): void {
    // return            // undefined
    // return undefined  // undefined
    return null          // null
    // return 1          // error
}
console.log(show())

let vo1: void = undefined
let vo2: void = null
console.log(vo1,'----',vo2) // undefined "----" null

object

// object:定义一个函数,参数与返回值都是object类型
function getObj(x: object): object {
    console.log(x)
    return {
        name: 'ni',
        age: 10
    }
    // return null或者undefined也可以
}
console.log(getObj({name: 'haha', age: 26}))  // {name: "haha", age: 26}   {name: "ni", age: 10}
console.log(getObj({}))                       // {}   {name: "ni", age: 10}
console.log(getObj(new String(123)))          // String {"123"}   {name: "ni", age: 10}
console.log(getObj(String))                   // ƒ String() { [native code] }   {name: "ni", age: 10}

联合类型 Union Types

取值可以为多种类型中的一种 |

// x 取值只能为数字 或 字符串,其他类型会报错
let x: number | string = 100
x = 'uuu'
// x = true // Type 'boolean' is not assignable to type 'string | number'.

类型断言 Type Assertion

手动指定一个值的类型

语法:

  • <类型>值

  • 值 as 类型 tsx 中只能用这种方式

function getLength(x: number | string) {
    // 如果是string类型,直接返回x.length比较简单,但number没有length属性,直接用会报错,所以要用到类型断言
    return (<string>x).length ? (x as string).length : x.toString().length
}
console.log(getLength('hahagdssdfgh'),'---',getLength(12345)) // 12 "---" 5

类型推断

当没有明确指定类型的时候推测出一个类型

  • 定义变量时赋值了, 推断为对应的类型

    let b9 = 123  // number
    // b9 = 'abc' // error 不能将类型“string”分配给类型“number”
    console.log(b9)
    
  • 定义变量时没有赋值, 推断为any类型

    let b10  // 变量 "b10" 隐式具有 "any" 类型,但可以从用法中推断出更好的类型
    b10 = 123
    b10 = 'abc'
    console.log(b10)
    

接口

相当于一个约束,interface中定义的属性必须传,不传会报错,编译成js文件后执行会显示为undefined
如果多传一个属性不会报错

interface Person {
  firstName: string,
  lastName: string
}
function person(person: Person) {
  console.log(person.firstName,'--',person.lastName)
}
let user = {
  firstName: 'haha',
  lastName: 'ben'
}
person(user)

基础

接口是对象的状态(属性)和行为(方法)的抽象(描述)

只读,可选属性
  • readonly 只读 — 作为变量使用的话用 const,若作为属性则使用 readonly

  • ? 可选 — 可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

interface Person {
    readonly id: number
    name: string
    age: number
    sex?: string     
}
const person: Person = { // 定义属性必须与接口一致,不能多属性少属性
    id: 1,
    name: 'haha',
    age: 18,
    // sex: '女',  可选属性
}
// person.id = 10   无法分配到 "id" ,因为它是只读属性
console.log(person)

函数类型

为了使用接口表示函数类型,我们需要给接口定义一个调用签名

它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。

// 定义的接口,用作searchF函数的类型使用
interface searchFunc {
    // 调用签名: 括号内是要传的参数,boolean便是返回值类型
    (a: string, b: string): boolean
}
// 定义函数,该类型就是上面定义的接口
const searchF: searchFunc = function (a: string, b: string): boolean {
    // 在字符串a中查找b这个字符串,search会返回b在a中所处位置,没有则返回 -1
    return a.search(b)> -1
}
console.log(searchF('hhhhaaa','h'))

类类型

使用接口来实现类的类型

类可以实现一个接口,也可以实现多个接口。接口中的内容都要真正地实现

类实现一个接口
// 定义一个接口
interface IFly {
    fly() // 该方法中没有任何的实现
}
// 定义一个类,该类型是上面定义的接口(IFly接口约束了Person1类)
class Person1 implements IFly {
    // 实现接口中的方法
    fly() {
        console.log('fly1')
    }
}
const person1 = new Person1() // 实例化对象
person1.fly() // fly1
类实现多个接口
interface ISwim {
    swim()
}
// 定义一个类,其类型是IFly和ISwim(当前这个类可以实现多个接口,一个类也可以同时被多个接口约束)
class Person2 implements IFly,ISwim {
    fly() {
        console.log('fly2')
    }
    swim() {
        console.log('swim2')
    }
}
const person2 = new Person2()
person2.fly()  // fly2 
person2.swim() // swim2
接口继承

接口与接口之间叫继承(使用extends关键字),类和接口之间叫实现(使用implements)

// 定义一个接口,继承其他的多个接口
interface IflyAndSwim extends IFly,ISwim {}

// 定义一个类,直接实现IflyAndSwim这个接口
class Person3 implements IflyAndSwim {
    fly() {
        console.log('fly3')
    }
    swim() {
        console.log('swim3')
    }
}
const person3 = new Person3()
person3.fly()  // fly3 
person3.swim() // swim3

类:相当于模板,通过模板可以实例化对象

基本示例

interface IPerson {
  firstName: string,
  lastName: string
}
function showPerson(person: IPerson) {
  console.log(person.firstName + '--' + person.lastName)
}
class CPerson {
  // 公共字段(属性)
  firstName: string
  lastName: string
  fullName: string
  // 构造器函数
  constructor (firstName: string, lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.fullName = firstName + '_' + lastName;
  }
}
// 通过类来实例化对象,不直接定义一个对象
let user = new CPerson('haha', 'aaa')
showPerson(user) // haha--aaa

TypeScript 里的类只是一个语法糖,本质上还是 JavaScript 函数的实现。
编译成的js代码:

function showPerson(person) {
    console.log(person.firstName + '--' + person.lastName);
}
var CPerson = /** @class */ (function () {
    function CPerson(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.fullName = firstName + '_' + lastName;
    }
    return CPerson;
}());
var user = new CPerson('haha', 'aaa');
showPerson(user);

同一文件夹下定义的变量名不要重复,即使 ts 文件中用的是 let,但编译成 js 是 var – 全局变量,会报错。每次的 ts 文件写成立即执行函数可以用相同变量名

// 面向对象
class Person {
    // 定义属性
    name: string
    age: number
    gender: string
    // 定义构造函数:将来实例化对象时,可以直接对属性的值进行初始化
    constructor (name: string='haha', age: number=17, gender: string='女') {
        // 更新对象中的属性数据
        this.name = name
        this.age = age
        this.gender = gender
    }
    // 定义实例方法
    show(str: string) {
        console.log(`I am ${this.name}, ${this.age} years old, ${this.gender}`,str)
    }
}
// 通过类实例化对象,可以直接进行初始化操作
let person = new Person('aa',20,'男')  // new Person()传参时:I am aa, 20 years old, 男 and you?
person.show('and you?');               // new Person()不传参时:I am haha, 17 years old, 女 and you?

继承extends

类和类之间有继承关系时,使用extends关键字

子类( 派生类 )调用父类( 基类 — 超类 )中的构造函数与实例方法时,使用super关键字

子类可以重写父类的方法

// 类Huang(子类 --- 派生类)继承自Person类(基类 --- 超类)
class Huang extends Person {
    constructor (name: string, age: number, gender: string) {
        // 调用基类中的构造函数,使用super
        super(name, age, gender)
    }
    show1() {
        // 调用父类中的方法
        super.show('你好!')
    }
}
let huang = new Huang('小明',24,'男')
huang.show1() // I am 小明, 24 years old, 男 你好!

多态

父类型引用指向子类型的实例 ==> 多态
如果子类型没有扩展的方法(除了父类中的方法,没有额外的实例方法), 可以让子类型引用指向父类型的实例
如果子类型有扩展的方法, 不能让子类型引用指向父类型的实例

父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为

class Animal {
    name: string
    constructor (name: string) {
        this.name = name
    }
    run(distance: number = 0) {
        console.log(`${this.name} run ${distance}`)
    }
}
class Dog extends Animal {
    constructor (name: string) {
        super(name)
    }
    // 重写父类中的实例方法
    run(distance: number = 5) {
        console.log(`${this.name} run ${distance}`)
    }
}
class Pig extends Animal {
    constructor (name: string) {
        super(name)
    }
    run(distance: number = 10) {
        console.log(`${this.name} run ${distance}`)
    }
}
const ani: Animal = new Animal('动物')
ani.run() // 动物 run 0米
const dog: Dog = new Dog('汪汪')
dog.run() // 汪汪 run 5米
const pig: Pig = new Pig('哼哼')
pig.run() // 哼哼 run 10米

// 父级类型创建子类的对象
const dog1: Animal = new Dog('柴犬')
dog1.run() // 柴犬 run 5米
const pig1: Animal = new Pig('两头乌')
pig1.run() // 两头乌 run 10米

function showAnimal (ani: Animal) {
    ani.run() // 参数需要是Animal类型的,但是传的子类改写了Animal的run方法
}
showAnimal(dog1) // 柴犬 run 5米
showAnimal(pig1) // 两头乌 run 10米

修饰符public private protected readonly

修饰符:描述类中成员(属性、构造函数、方法)的可访问性

  • public默认 — 公共的,任何位置都可以访问类中的成员

  • private — 私有的,外部与子类均无法访问

  • protected — 受保护的,外部无法访问,子类中可以访问

对构造函数中的参数用 public private protected 修饰,相当于类中自动添加属性成员

  • readonly 只读属性必须在声明时或构造函数里被初始化。

类中的属性成员用readonly修饰后,该属性成员在外部不可随意修改,在构造函数中可以修改

构造函数中的参数用readonly进行修饰(也叫 参数属性),constructor (readonly name: string)创建和初始化属性成员readonly name: string

class Animal {
    public name: string
    // private name: string
    // protected name: string
    constructor (name: string) {
        this.name = name
    } 
}
class Dog extends Animal {
    constructor (name: string) {
        super(name)
    }
    showParent() {
        console.log(this.name) // 子类中访问属性
    }
}
const dog: Dog = new Dog('汪汪')

// 外部访问属性
console.log(dog.name) // public: 汪汪  private:属性“name”为私有属性,只能在类“Animal”中访问。 protected: 属性“name”受保护,只能在类“Animal”及其子类中访问
dog.showParent()  // public: 汪汪  private:属性“name”为私有属性,只能在类“Animal”中访问。 protected: 汪汪

存取器

存取器:可以有效地控制对象中成员的访问,通过getterssetters来进行操作

class GSPerson {
    firstName: string
    lastName: string
    constructor(firstName: string, lastName: string) {
        this.firstName = firstName
        this.lastName = lastName
    }
    // 读取器:读取数据
    get fullName() {
        console.log('get...')
        return this.firstName + '-' + this.lastName
    }
    // 设置器:修改数据
    set fullName(val) {
        console.log('set...')
        let temp = val.split('-')
        this.firstName = temp[0]
        this.lastName = temp[1]
    }
}
const gs = new GSPerson('东方','不败')
console.log(gs.fullName)    // get... 东方-不败
gs.fullName = '诸葛-孔明'    // set... 
console.log(gs.fullName)    // get... 诸葛-孔明

静态成员static

静态成员:这些属性存在于类本身上面而不是类的实例上

静态属性, 是类对象的属性
非静态属性, 是类的实例对象的属性

在类中通过static修饰的属性或者方法(静态属性与静态方法)

静态成员使用:类名.

class staPerson {
    // 不能用name属性: 静态属性“name”与构造函数“staPerson”的内置属性函数“name”冲突
    static age: number = 10
    // “static”修饰符不能出现在构造函数声明中
    // static constructor(age1: number) {
    //   // this是实例对象,age是静态属性,不能通过实例对象直接调用静态属性
    //   // this.age = age1 // 属性“age”不是类型为“staPerson”的静态成员
    // }
    static sayHi() {
        console.log('hello')
    }
}
// const sta = new staPerson()
// 通过实例对象调用的属性(实例属性)
// console.log(sta.age) // 报错:属性“age”不是类型为“staPerson”的静态成员。 编译后显示:undefined
// 通过实例对象调用的方法(实例方法)
// sta.sayHi()

// 通过 类名.静态属性 的方法来访问该成员数据
console.log(staPerson.age) // 10
// 通过 类名.静态属性 的方法来设置该成员数据
staPerson.age = 20
console.log(staPerson.age) // 20
// 通过 类名.静态属性 的方法来调用内部静态方法
staPerson.sayHi() // hello

抽象类abstract

抽象类:包含抽象方法(抽象方法一般没有任何的具体内容的实现),也可以包含实例方法

抽象类不能被实例化,为了让子类进行实例化及实现内部的抽象方法

抽象类最终都是为子类服务的

abstract class cAnimal {
    abstract name: string = '大灰狼' // 抽象属性
    // 抽象方法
    abstract eat() // 方法“eat”不能具有实现,因为它标记为抽象。
    // 实例方法
    run() {
        console.log('跑呀')
    }
}
// const dogg: cAnimal = new cAnimal() // 无法创建抽象类的实例
// 定义子类(派生类)
class Dogg extends cAnimal {
    name: string = '狗狗'
    // 如果不写eat方法报错:非抽象类“dogg”不会实现继承自“cAnimal”类的抽象成员“eat”。
    // 重新写基类中的抽象方法,相当于子类中的实例方法
    eat() {
        console.log('吃骨头')
    }
}
const dogg: Dogg = new Dogg()
dogg.eat() // 吃骨头
// 调用抽象类中的实例方法
dogg.run() // 跑呀
console.log(dogg.name) // 狗狗

函数

函数:封装了一些重复使用的代码,在需要的时候直接调用即可

基本示例

// 函数声明 --- 命名函数
function add(x: string, y: string): string {
    return x + y
}
console.log(add('11','44')) // 1144

// 函数表达式 --- 匿名函数
// ?可选参数,x默认参数为10,如果不传入则采用默认值
let a = function (x: number = 10, y?: number): number {
    return x + y
}
console.log(a(11,44)) // 55

函数完整表达式

// b ---> 变量名 ---> 函数b
// (x: number, y: number) => number 当前函数的类型
// function(x: number, y: number): number {return x + y} 相当于符合上面函数类型的值
let b:(x: number, y: number) => number = function(x: number, y: number): number {
    return x + y
}
console.log(b(11,44)) // 55

剩余参数

剩余参数:放在参数声明的最后

// ...args: string[]  剩余的参数放在了一个字符串的数组中
function show(x: string, ...args: string[]) {
    console.log(x)    // a
    console.log(args) // (4) ['b', 'v', 'f', 'jkgfdsa']
}
show('a','b','v','f','jkgfdsa')

函数重载

函数重载:函数名字相同,函数参数及个数不同

// 需求:字符串类型的拼接,数字类型相加
function addMix(x: string, y: string): string
function addMix(x: number, y: number): number

function addMix(x: string | number, y: string | number): string | number {
    // x y类型必须一直才能进行接下来的操作
    if(typeof x === 'string' && typeof y === 'string') {
        return x + y
    } else if(typeof x === 'number' && typeof y === 'number') {
        return x + y
    } 
}
console.log(addMix('hah','a')) // haha
console.log(addMix(13,5))      // 18
// console.log(addMix('hah',13))  // undefined 没有重载时会显示为“undefined”,声明重载后“没有与此调用匹配的重载”
// console.log(addMix(4,'a'))     // undefined

泛型

泛型:在定义函数、接口、类的时候不能预先确定要使用的数据类型,在使用函数、接口、类的时候才能确定数据类型

基本示例

需求:根据指定的数量 count 和数据 value , 创建一个包含 count 个 value 的数组

非泛型:

function getArr(x: any, y: number): any[] {
    const arr: any[] = []
    for(let i = 0; i < y; i++) {
        arr.push(x)
    }
    return arr
}
const a = getArr(10.8751,4)
const b = getArr('ab',4)
// 非泛型的时候没有智能提示
console.log(a,a[0].toFixed(2))   // [10.8751, 10.8751, 10.8751, 10.8751] '10.88'
console.log(b,b[0].split('')) // ['ab', 'ab', 'ab', 'ab']   (2) ['a', 'b']

泛型:类型表示为 <类型别称>

function getArr1<T>(x: T, y: number): T[] {
    const arr: T[] = []
    for(let i = 0; i < y; i++) {
        arr.push(x)
    }
    return arr
}
const a1 = getArr1<number>(8.9876543,4)
const b1 = getArr1<string>('abcdss',4)
// 非泛型的时候没有智能提示
console.log(a1,a1[0].toFixed(2))   // [8.9876543, 8.9876543, 8.9876543, 8.9876543] '8.99'
console.log(b1,b1[0].split('')) // ['abcdss', 'abcdss', 'abcdss', 'abcdss']   ['a', 'b', 'c', 'd', 's', 's']

多个泛型参数的函数

 function getDouble<K,V>(x: K, y: V): [K, V] {
     return [x, y]
 }
const d = getDouble<string, number>('dfgh',18.098765)
console.log(d[0].split(''),'---',d[1].toFixed(2)) // ['d', 'f', 'g', 'h'] '---' '18.10'

泛型接口

泛型接口:在定义接口时, 为接口中的属性或方法定义泛型类型;在使用接口时, 再指定具体的泛型类型

需求:定义一个类,用来存储用户的相关信息(id,名字,年龄)

通过一个类的实例对象调用add方法可以添加多个用户信息对象,调用gerUserId方法获取指定id的用户信息

// 定义一个类,用来存储用户的相关信息(id,名字,年龄)
class User{
    id?: number
    name: string
    age: number
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}
// 定义一个类,增加add  gerUserId方法
// 如果不是User类型而是其他类型每次重复代码不好,所以定义个“泛型接口”
interface IBaseCRUD<T> {
    data: Array<T>
    add: (t: T) => T
    gerUserId:(id: number) => T
}
class UserCRUD implements IBaseCRUD<User>{
    // data保存多个User类型的用户信息
    data: Array<User> = []
    add(user: User):User {
        user.id = Date.now() + Math.random()
        this.data.push(user) // 用户信息添加到data数组中
        return user
    }
    gerUserId(id: number): User {
        return this.data.find(item => item.id === id)
    }
}
const u1 = new UserCRUD()
// 调用添加数据的方法
u1.add(new User('哈',19))
u1.add(new User('a',12))
u1.add(new User('qw',16))
u1.add(new User('zxc',34))
u1.add(new User('gh',23))
console.log(u1.data) // 打印出总共6条数据

// 根据id查询数据信息
const { id } = u1.add(new User('zxcv',12))
console.log(u1.gerUserId(id)) // User {name: 'zxcv', age: 12, id: 1631879418881.0364}

泛型类

泛型类:在定义类时, 为类中的属性或方法定义泛型类型;在创建类的实例时, 再指定特定的泛型类型

class GenericNumber<T> {
    default: T
    add: (x: T, y: T) => T
}
const g1: GenericNumber<number> = new GenericNumber<number>()
// 设置默认属性值
g1.default = 12
// 定义add方法
g1.add = function (x, y) {
    return x + y
}
console.log(g1.add(13,8)) // 21

const g2: GenericNumber<string> = new GenericNumber<string>()
// 设置默认属性值
g2.default = 'hgfd'
// 定义add方法
g2.add = function (x, y) {
    return x + y
}
console.log(g2.add(g2.default,'kjh')) // hgfdkjh

泛型约束

泛型约束: 如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性

需要定义一个接口,用来约束将来的类型中必须有length属性

interface ILength {
    length: number
}
function getLength<T extends ILength>(x: T): number {
    return x.length
}
console.log(getLength<string>('kjhgfdswertyui')) // 14

声明文件

当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能

声明语句: declare var jQuery: (selector: string) => any

声明文件:把声明语句单独放到一个文件内,命名xxx.d.ts,不用引入,ts自动解析

npm下载声明文件:npm install @types/jquery --save-dev

下载的声明文件JQuery.d.tsnode_modules/@types/jquery

// 引入第三方的库jQuery
import jQuery from 'jquery'
// 声明语句
// declare var jQuery: (selector: string) => any

// 使用jQuery
jQuery('选择器')

内置对象

内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准。

ECMAScript 的内置对象

  • Boolean
  • Number
  • String
  • Date
  • RegExp
  • Error
let b: Boolean = new Boolean(1)            // Boolean {true}
let n: Number = new Number(true)           // Number {1}
let s: String = new String('abc')          // String {'abc'}
let d: Date = new Date()                   // Sat Sep 18 2021 16:07:05 GMT+0800 (中国标准时间)
let r: RegExp = /^1/                       // /^1/
let e: Error = new Error('error message')  // Error: error message
// b = true // b是单纯的boolean值,不是对象
console.log(new Number(false),new Number(1),new Number(2))    // Number {0}   Number {1}   Number {2}
console.log(new Number(true) === new Number(1),new Number(0)) // false   Number {0}
console.log(new Number(true) == new Number(1)) // false
// let bb: boolean = new Boolean(2)  
// 不能将类型“Boolean”分配给类型“boolean”。“boolean”是基元,但“Boolean”是包装器对象。如可能首选使用“boolean”。

BOM 和 DOM 的内置对象

  • Window

  • Document

  • HTMLElement

  • DocumentFragment

  • Event

  • NodeList

const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
  console.dir(event.target) // console.dir()可以显示一个对象所有的属性和方法。
})
const fragment: DocumentFragment = document.createDocumentFragment()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值