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() 
}


相关文章
|
6月前
|
存储 JavaScript
TypeScript三
在 TypeScript 中,数组可以通过类型定义,如 `number[]` 或 `string[]`。示例展示了数字和字符串数组的声明与访问。数组解构允许将数组元素赋值给多个变量。通过 `for...in` 循环可遍历数组。多维数组如 `number[][]` 存储嵌套数组。数组方法包括:`concat()` 连接数组,`every()` 检查所有元素是否满足条件,`filter()` 过滤符合条件的元素,`forEach()` 对每个元素执行回调,`indexOf()` 查找元素位置,`join()` 将数组转为字符串,`map()` 应用函数于每个元素并返回新数组
|
6月前
|
JavaScript 前端开发 开发者
TypeScript一
JavaScript开发迅速但维护成本高,适合小型项目,因其动态类型导致编辑器提示不全。TypeScript是JS超集,增加了类型系统,提高开发效率和代码质量。安装TypeScript需先安装Node.js,然后通过npm安装tsc。案例演示创建`.ts`文件,转换成`.js`并运行。TypeScript支持多种数据类型,如any、number、string等,并有严格变量声明和函数定义规则,包括函数重载和匿名函数。
|
6月前
|
存储 JavaScript 索引
TypeScript四
## 联合类型 联合类型使用`|`分隔,表示变量可为多种类型: ```c var val: string | number; val = 12; // OK val = &quot;Runoob&quot;; // OK `
|
6月前
|
JavaScript 前端开发
TypeScript二
JavaScript Number对象包含多种方法,如`toExponential()`将数值转化为指数形式,`toFixed()`保留指定位数的小数,`toLocaleString()`按本地格式显示数字,`toPrecision()`格式化数字到指定长度,`toString()`以指定基数表示数字,而`valueOf()`返回原始数值。此外,示例中还展示了Date对象的格式化方法。对于String对象,有`constructor`返回创建对象的函数,`length`获取字符串长度,`prototype`用于扩展对象,以及一系列如`charAt()`、`indexOf()
|
6月前
|
开发框架 JavaScript 前端开发
什么是TypeScript
什么是TypeScript
34 0
|
JavaScript
【TypeScript理解】
【TypeScript理解】
|
JavaScript
TypeScript(一)
TypeScript(一)
|
JavaScript 前端开发 数据库
TypeScript 期中考试现在开始
相信这段时间来,对 TypeScript 感兴趣的小伙伴们已经把这个神器给系统的学习了一遍了吧。如果计划开始学习但是还没有开始,或者没有找到资料的同学,可以看下我在之前文章中 前端进阶指南[1] 找一下 TypeScript 部分的教程,自行学习。
|
JSON JavaScript 前端开发
Typescript知识总结(1)
Typescript知识总结(1)
Typescript知识总结(1)