typescript修炼指南(二)

简介: typescript修炼指南(二)

大纲

本章主要讲解一些ts的常规用法,涉及以下内容:

  • interface: 接口
  • class : 类
  • function: 函数
  • T :  泛型

之前因本人业务繁忙(太菜了 被拉去改bug了┭┮﹏┭┮), 所以拖更了,后边会陆续补上, 还在踩坑的小伙伴,希望本文能给你们一些帮助 QAQ


接口

基本使用

定义: 用来集中约束数据类型,用关键词interface来定义一个接口

interface People {
        num:number,
        country: string,
    }
复制代码


使用接口:

// 这样就会报错: 因为约定的时候没有name属性
 const getPeople = (people: People) => people.name 
复制代码


  • 定义可选属性
interface User {
        name: string,
        age: number,
        sex?: string  // ? 表示可选的
    }
复制代码


  • 定义只读属性
interface User {
        name: string,
        age: number,
        readonly weight: string, // readonly表示只读
  }
复制代码


  • 定义函数属性
interface User {
        name: string,
        age: number,
        get: (sex: string)  => string  // 定义参数类型和返回值类型
 }
 // 或者直接使用函数接口
interface Func {
    (sex: string) : string  // 注意这里的符号
}
interface User {
    name: string,
    age: number,
    get: Func,  // 使用接口
}
复制代码


注意点

有时候我们会遇到这样的情况,当调用函数的时候,传入的参数类型有可能是可选类型,举个例子


  • 定义接口
interface User1 {
        name?: string, 
}
复制代码


  • 定义函数
const getUser = (user: User1): { result: string} => {
        return {result: user.name }
 }
复制代码


这时候会报类型错误, 因为返回值也可能是个void类型, 那如何避免?返回的时候也是可选即可

const getUser = (user: User1): { result?: string} => {
        return {result: user.name }
 }
复制代码


另外, 当我们调用的时候传入的是额外的属性比如传入age属性, 则需要as断言

const username = getUser({age: 20} as User1)
复制代码


或者,我们可以在接口定义的时候传入一个自定义属性约束

interface User1 {
        name?: string, 
        [propName: string]: any,// 属性名字符串类型, 这种条件下值可以是任意类型了
  }
复制代码


通过上边约束, 我们就可以实现这样的一个数据类型约束,键key是变化的, key自增变化

const UserP = {
    name: 'lili',
    age: 20,
    userClass: {
        1: 'class1',
        2: 'class2',
       // .....
    }
}
复制代码


  • 定义约束
interface mark {
        [name: number]: string 
}
interface User2 {
    name: string, 
    age: number,
    userClass: mark
}
复制代码


接口继承

直接贴代码,比较简单, 也可以多继承的

interface inter1 {
    name: string
}
interface inter2 {
    (age: number) : number
}
interface inter3 {
    get: (name: string) => string
}
interface interAll extends inter1 {
    add: (age: number) => number
}
// 多继承
interface interAll extends inter1, inter2, inter3 {
    add: (age: number) => number
}
复制代码


类class

抽象类

抽象类中只用于定义,定义的抽象方法,不会实现具体的方法,且不能实例化,只能作为基类,关键词:abstract

abstract class Test {
    add(): void { console.log('add') }
    // 抽象方法不需要实现具体的方法
    abstract remove(): string 
}
// 直接实例化会导致错误
// const test = new Test()
复制代码


继承抽象类

class Test1 extends Test {
    // 这里如果不实现remove方法就会报错, 因为是抽象方法
    remove() {
        return 'remove'
    }
}
复制代码


ts中的类关键词
  • public: 公共修饰词 默认都是public 外部可以访问到的
  • protected: 外部无法访问 内部和子类都可以访问
  • private: 私有修饰符 只有内部可以访问
// class中的 关键词
class Test2 {
    // 公共修饰词 默认都是public 外部可以访问到的
    public add() {
        console.log('add')
    }
    //  外部无法访问 内部和子类都可以访问
    protected remove() {
        console.log('remove')
    }
    // 私有修饰符 只有内部可以访问
    private result() {
        console.log('result')
        this.remove() // 可以访问
    } 
}
class Test3 extends Test2 {
    change() {
        this.add() 
        this.remove()
        // 报错  子类无法访问
        //this.result()
    }
}
const test2 = new Test2()
test2.add()
//test2.remove() // 报错
//test2.result() // 报错
复制代码


作为初始化接口
class Test4 {
    public name: string = 'lili'
    public age: number = 20
    public get(): string { return name }
}
const test4 = new Test4()
console.log(test4.get())
// test.name = 1 // 报类型错误  因为name是string类型
复制代码


函数

  • 可选参数
const f1 = (a: string = 'f1', b? : number): void => console.log(a,b?b:'')
复制代码


  • 剩余参数 ...rest
const f2 = (a: string, ...rest: string[]): void => { }
复制代码


  • 函数的重载
// 调用批次
function reloadFunc (name: string): { code: number }
function reloadFunc (name: string, age: number): { code: number } 
// 函数实现
function reloadFunc (name: string, age?: number, sex?: string): { code: number } {
    if(name) {
        return { code: 0 }
    }else if(age) {
        return { code: 1 }
    }else {
        return { code: 2 }
    }
}
reloadFunc('lili')
reloadFunc('lili', 20)
//  reloadFunc('lili', 30, '男')  这一行会报一个错误: 期望是2个参数
复制代码


泛型

基本使用

泛型最大的作用在于灵活,对于代码复用有很大的用处,说白了,类型由调用者决定,从而实现的一种约束 定义: (T代表一种数据类型)

function testT<T>(name: T): T {
    return name
}
// 调用, 传入的是string类型 返回的约束也是该类型
testT('lili') 
复制代码


同时支持多个类型的传入:

function testT1<T, F>(name: T, age: F): [T, F] {
    return [name, age]
}
复制代码


如果传入的是数组类型,需要返回数组的某个属性,比如length属性

function testT2<T, F>(arr: Array<T>): number {
    return arr.length  // 如果没指明数组会报不存在length属性错误 加上Array即可
}
复制代码


在接口中的应用
interface testT3<T> {
    name: T
}
// 使用它
const test_t: testT3<number> = { name: 0 }
复制代码


泛型类
class TestT4<T> {
    private name: T[] = [] 
    public test(age: T): T {
        return age
    }
}
复制代码


调用就可以这样

const test_t1 = new TestT4<number>()
test_t1.test(10)
复制代码


泛型继承

也叫做泛型的约束,约束泛型只能在某个类型范围内,使用关键词extends

// extends 继承某个类型
class TestT5<T extends Args> {
    private name: T[] = [] 
    public test(age: T): T {
        return age
    }
}
const test_t2 = new TestT5<number>() // 这里就必须是这两种类型了
复制代码


泛型对象索引

比如我们传入一个对象类型,这种情况下编译器是懵逼的 不知道obj有没有key(默认是{})属性且还不知道key的类型

function testT6<T>(obj: T, key: number) {
     return obj[key]       
}
复制代码


改造一下,让它继承对象的类型,在用属性继承(keyof)这个类型,可能难理解, 直接看代码

function testT6<T extends object, U extends keyof T>(obj: T, key: U) {
    return obj[key]
 }
复制代码


泛型继承接口

泛型并不支持多继承,也就是说T extends A,B,C 这样是行不通的, 但是我们可以先用接口实现多继承,然后在继承这个接口, 也就是说 interface A extends B,C,D   然后 T extends A

interface testFunc extends A,B,C{
    name: string,
    age: number,
}
function testT7<T extends testFunc>(obj: T) {
    return obj
}
复制代码


泛型构造函数约束

如果传入的参数是一个构造函数比如:

function testT8<T>(func: T) {
     return new func() // 这样会报错, 因为不知道是构造类型
}
复制代码


改造一下: ( new( ) )

function testT8<T>(func: {new(): T}): T {
    return new func() 
}


相关文章
|
14天前
|
JavaScript 前端开发 安全
TypeScript五
TypeScript是面向对象的JavaScript超集,支持类、接口等OOP特性。类通过`class`定义,包括字段、构造函数和方法。例如,`Car`类有`engine`字段、构造函数和`disp`方法。类间可实现继承,如`Circle`继承`Shape`。TypeScript不支持多重继承,但允许多重继承链。`static`关键字定义静态成员,`instanceof`检查对象类型,访问控制修饰符(public, protected, private)管理访问权限。类能实现接口,如`AgriLoan`实现`ILoan`。 TypeScript对象是类型实例,
|
14天前
|
存储 JavaScript
TypeScript三
在 TypeScript 中,数组可以通过类型定义,如 `number[]` 或 `string[]`。示例展示了数字和字符串数组的声明与访问。数组解构允许将数组元素赋值给多个变量。通过 `for...in` 循环可遍历数组。多维数组如 `number[][]` 存储嵌套数组。数组方法包括:`concat()` 连接数组,`every()` 检查所有元素是否满足条件,`filter()` 过滤符合条件的元素,`forEach()` 对每个元素执行回调,`indexOf()` 查找元素位置,`join()` 将数组转为字符串,`map()` 应用函数于每个元素并返回新数组
|
14天前
|
JavaScript 前端开发 开发者
TypeScript一
JavaScript开发迅速但维护成本高,适合小型项目,因其动态类型导致编辑器提示不全。TypeScript是JS超集,增加了类型系统,提高开发效率和代码质量。安装TypeScript需先安装Node.js,然后通过npm安装tsc。案例演示创建`.ts`文件,转换成`.js`并运行。TypeScript支持多种数据类型,如any、number、string等,并有严格变量声明和函数定义规则,包括函数重载和匿名函数。
|
23天前
|
开发框架 JavaScript 前端开发
什么是TypeScript
什么是TypeScript
11 0
|
3月前
|
JavaScript 前端开发 Java
TypeScript
TypeScript是JavaScript的一个超集,简称ts,ts是能够完全兼容js的ts是一门静态类型的语言,js是动态类型的语言
31 0
|
JavaScript 前端开发
初识 TypeScript 二。
初识 TypeScript 二。
初识 TypeScript 二。
|
JavaScript
初识 TypeScript 一。
初识 TypeScript 一。
初识 TypeScript 一。
|
JavaScript 前端开发 开发工具
TypeScript初识
TypeScript初识
122 0
|
JavaScript 前端开发 编译器
【TypeScript】一文带你了解什么是TypeScript
【TypeScript】一文带你了解什么是TypeScript
【TypeScript】一文带你了解什么是TypeScript