TypeScript类和接口

类和接口

类的基本使用

属性必须要有默认值 必须要初始化 否则编译报错

class Person {
    // 属性必须要有默认值 必须要初始化 否则编译报错
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

const p = new Person("why", 18)

类的继承

super可以调用父类属性的构造器,

 super(name, age)

也可以调用父类的方法

super.eating()

重写 父类有eating方法 子类不想用父类的eating方法,而自己写了一个eating方法

类的多态

多态表现:相同类型的对象,调用相同的方法,有不同的结果

多态前提:父类的引用指向子类的对象

类的成员修饰符
  • 默认情况下 属性修饰符是pubilc 即 属性在任何地方都可见

  • private 仅在同一类中可见、私有的属性或方法

    要修改或访问属性要调用方法

class Person {
    private name: string = ''

    // 封装了两个方法,通过方法来访问、修改name
    getName() {
        return this.name
    }

    setName(newName) {
        this.name = newName
    }
}

const p = new Person()
console.log(p.getName())
p.setName('why')
  • protected在类内部和子类可以被访问
只读属性

属性可以在构造器中赋值,一旦赋值就不能修改,但是如果该属性是一个对象,可以修改该对象中的属性

setter和getter

可以取代getName 和 setName方法

class Person {
    private _name: string

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

    // 访问器setter/getter
    // setter
    set name(newName) {
        this._name = newName
    }
    // getter
    get name() {
        return this._name
    }
}

const p = new Person('why')
p.name = 'coderwhy'
console.log(p.name)
静态类(类的静态属性、静态方法)

可以直接通过类来调属性、方法

抽象类
// 抽象类不能实例化
abstract class Shape {
    // 抽象类的方法可以没有函数体 这种方法又叫抽象方法
    abstract getArea();
}
class Rectangle extends Shape {
    private width: number
    private height: number

    constructor(width: number, height: number) {
        super()
        this.width = width
        this.height = height
    }
    // 抽象类的方法必须在子类中实现
    getArea() {
        return this.width * this.height
    }

}
类的类型

类也可以作为一种类型

class Person {
    name: string = '123'
    eating() {

    }
}
// 对象字面量来创建对象
const p1: Person = {
    name: 'why',
    eating() {

    }
}

接口

索引类型

// 通过interface定义索引类型
interface IndexLanguage {
    [index: number]: string
}

const frontLanguage: IndexLanguage = {
    0: 'HTML',
    1: 'CSS',
    2: 'JAVAScript',
    3: 'Vue',
}
接口的继承

也是使用extends关键字,支持多继承的

interface ISwim {
  swimming: () => void
}

interface IFly {
  flying: () => void
}


interface IAction extends ISwim, IFly {

}

const action: IAction = {
  swimming() {

  },
  flying() {

  }
}

交叉类型
interface ISwim {
  swimming: () => void
}

interface IFly {
  flying: () => void
}

type MyType1 = ISwim | IFly
type MyType2 = ISwim & IFly

const obj1: MyType1 = {
  //只需要两种类型的其中一种
  flying() {

  }
}

const obj2: MyType2 = {
  //两种类型的方法都要都有
  swimming() {

  },
  flying() {
    
  }
}
类实现接口
interface ISwim {
    swimming: () => void
}

interface IEat {
    eating: () => void
}

// 类实现接口
class Animal {

}
// 继承:只能实现单继承
// 实现:实现接口 类可以实现多个接口
class Fish extends Animal implements ISwim, IEat {
    swimming() {
        console.log('Fish swimming')
    }

    eating() {
        console.log('Fish eating')
    }
}
interface和type区别

非对象类型 函数、联合类型 推荐使用type

ts允许定义2个相同名称的接口interface,会对接口的属性做合并

而type不能重复定义相同的名称

// ts的lib库中的window类里面没有age属性
// 自己定义Window接口 会和上下文中的Window合并
interface Window {
    age: number
}
window.age 
字面量的赋值

一旦是对象的引用赋值 就会有freshness擦除操作

freshness擦除操作:擦掉在IPerson中没有的属性,如果info依然包含IPerson中所有的属性,就通过类型检测

interface IPerson {
    name: string,
    age: number,
    height: number
}
// 会报错 是因为p 的类型限制为IPerson 只能传入name,age,height这3个属性
// const p: IPerson = {
//     name: "why",
//     age: 18,
//     height: 1.88,
//     address: '广州市'
// }
// 将对象单独提出来
const info = {
    name: "why",
    age: 18,
    height: 1.88,
    address: '广州市'
}

const p: IPerson = info//就不会报错 因为这里是对象的引用赋值
TypeScript枚举类型

枚举是TypeScript特有的特性

枚举就是将一组可能出现的值,定义在一个类型中,这个类型就是枚举类型

泛型

泛型:将类型参数化。函数的参数不是写死的,而是由调用函数的以参数的形式告知

function sum2<Type>(num1: Type) {
    return num1
}
// 希望参数的类型由调用函数的以参数的形式告知
sum2<string>("20")
sum2<string[]>(["abc"])
sum2<{ name: string }>({ name: "why" })

泛型可以接收不同类型的参数

function foo<T, E, O>(arg1: T, arg2: E, arg3: O) {


}
foo<number, string, boolean>(10, '30', true)
泛型接口的使用
interface foo<T1, T2> {
    name: T1,
    age: T2
}

const p: foo<string, number> = {
    name: "why",
    age: 13
}
泛型类的使用
class Point<T>{
    x: T
    y: T
    z: T

    constructor(x: T, y: T, z: T) {
        this.x = x,
            this.y = y,
            this.z = z
    }
}
const p = new Point("huhdi", "bih", "biuhuho")//类型推导
泛型的类型约束
interface Ilength {
    length: number
}

//确保传进来的参数有length属性,就用extends集成接口,形成约束
function getLength<T extends Ilength>(arg: T) {
    return arg.length
}
getLength("abc")
getLength(['abc', 'cba'])
模块化

模块和命名空间都是作用域

模块的内部模块就是命名空间 把模块再来划分作用域,这些作用域就是命名空间

export namespace time {
    export function format(time: string) {
        return "2022-2-2"
    }

    export const name: string = "why"
}

export namespace price {
    export function format(price: number) {
        return "99.00"
    }
}
time.name
time.format("2022-3-18")
price.format(179)

类型的查找

typescript会在哪里查找我们的类型声明呢?

  • 内置类型声明;

在安装ts的时候 就有的声明文件。包含JS的内置类,如Math,Date,还有DOM API ,如Window,Document

  • 外部定义类型声明;

在使用第三方库需要的类型声明。

这些类型有2种声明方式:

  • 在本身库中有类型声明 比如axios,安装axios就有声明文件

  • 在社区中的公有库中 可以通过下面的链接查找对应的声明文件

    [TypeScript: Search for typed packages (typescriptlang.org)](https://www.typescriptlang.org/dt/search?search=lodash)

  • 自己定义类型声明

如果安装了第三方库,需要声明文件,在社区公有库中找不到,就要自己编写 .d.ts 文件(详见代码)。

// 声明模块
declare module 'lodash' {
    export function join(arr: any[]): void
}
// 声明变量
declare let whyName: string
declare let whyAge: number
declare let whyHeight: number

// 声明函数
declare function whyFoo(): void    
// 声明文件
// 把以jpg结尾的文件作为一个模块使用
declare module '*.jpg'

// 声明命名空间
declare namespace $ {
    export function ajax(setting: any): any
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值