程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

Vue3开发极简入门(2):TypeScript定义对象类型

balukai 2025-05-14 11:58:35 文章精选 4 ℃

TypeScript官方的定义:

TypeScript是具有类型语法的JavaScript。是一种基于JavaScript的强类型编程语言。

以下的说法来源于我早年间看的JavaScript(以下简称JS)之父Brendan Eich的一些访谈,但是年深日久的,我也年纪大了,记忆很可能模糊,甚至错误,不保真,也提供不了来源,所以大家就当看个乐儿,不看也行。

JS的诞生,其实蛮仓促的,好像10来天就把JS设计出来了,而且是个很杂糅的语言。从名字也能看出来——JavaScript,就是在傍Java、蹭热度,有点“雷碧”、“康帅傅”、“金庸新”的意思。Brendan也承认,很多地方设计的不严谨。说实话,在很长一段时间,JS都被视为一个“玩意儿”,不算是一个严肃的编程语言。

但是呢,牛人就是牛人,JS虽然简约但不简单,随性但不随便,大家用起来很爽,因此在网页客户端这一块,基本上就干掉了其他解决方案,例如Java的Applet(能知道这玩意儿的肯定得40~50岁了)、微软的ActiveX、Adobe的Flash等。

正是因为设计的不谨慎,使得很灵活,写起来很爽,才有了著名的Atwood 定律:

任何能够用JavaScript实现的应用,最终都必将用JavaScript实现。

但是也有问题,尤其是面对大型、多人协作开发的应用系统时,太灵活了就不是一件好事,最典型的就是对象数据。

比如JS:

const user={id:1,name:"leo"};
console.log('用户姓名:',user.nmea);
console.log('用户年龄:',user.age);

以上代码没有问题,顶多输出NaN,这种情况IDE是不会有什么错误提示的,也不会有自动补全,因为JS是允许访问不存在的数据的,user.nmea就是合法的。

这对于团队协作,开发一个大型应用系统来说,指不定就埋下了很难检查出的雷。

TypeScript(以下简称TS)就能解决这个问题(TS的好处不止如此,但是本文仅就强类型这一方面讲述)。

定义一个类,Java是这么做的:

//定义类
public class UserInfo implements Serializable {
    @Serial
    private static final long serialVersionUID = -1;
    private String userId;
    private String name;
    private int age;
    //省略 构造函数、get/set方法
}
// new一个
UserInfo userInfo=new UserInfo()
//省略set

泛型这么写:

@Data
public class Result<T> implements Serializable {
    @Serial
    private static final long serialVersionUID = -1;
    private int code;
    private String msg;
    private T data;


    public Result(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }


    public static <T> Result<T> success(T data) {
        return new Result<T>(0, "success", data);
    }


    public static <T> Result<T> noAuth(){
        return new Result<T>(-1, "Token校验不通过", null);
    }
}

TS里面这么做。创建src/params/index.ts:

//接口
export interface DeptParam {
    deptId: string
    deptName: string
    deptDesc?: string//可选
}

export interface UserParam {
    userId: string
    userName: string
    userAge?: number
    dept: DeptParam
}

export interface UserResult {
    userId: string
    name: string
    age: number
}

export interface ResultDto<T> {
    code: number
    msg: string
    data: T
}
//自定义类型 定义列表 写法1
export type UserList = Array<UserParam>
//写法2
//export type UserList = UserParam[]
  
export type Car = {
    vehicleNo: string
    vin: string
    vehicleAge?: number
}

export type Phone = { imei: string } | null

export type Pair<Car, Phone> = [Car, Phone]

// 类
export class ResponseDto<T> {
    private code: number
    private msg: string
    private data: T
    constructor(code: number, msg: string, data: T) {
        this.code = code
        this.msg = msg
        this.data = data
    }

    static success<T>(data: T): ResponseDto<T> {
        return new ResponseDto<T>(0, "success", data)
    }

    get getCode(): number {
        return this.code
    }
    set setCode(code: number) {
        this.code = code
    }

    get getMsg(): string {
        return this.msg
    }

    set setMsg(msg: string) {
        this.msg = msg
    }

    get getData(): T {
        return this.data
    }

    set setData(data: T) {
        this.data = data
    }
}

export class Res<T> {
    private _code = 0
    get code(): number {
        return this._code
    }

    set code(code: number) {
        this._code = code
    }
}

在vue组件中使用:

<script lang='ts' setup name='TsDemo'>
import { ResponseDto, type ResultDto, type Car, type Phone, type DeptParam, type Pair, type UserList, type UserParam } from '@/params';
import { reactive, ref } from 'vue';
//声明一个列表
let deptList: Array<DeptParam> = [
    { deptId: "1", deptName: "总经办",deptDesc:"很重要" },
    { deptId: "2", deptName: "研发部" }
]
//声明一个对象
let user1: UserParam = { userId: "1", userName: "张三", userAge: 31, dept: deptList[0] }
let user2: UserParam = { userId: "2", userName: "李四", userAge: 30, dept: deptList[1] }


//声明一个列表
let userList: UserList = [user1, user2]
//声明一个响应式列表
let userListRea = reactive<UserList>(userList)
//声明一个响应式对象
let userRea = reactive<UserParam>({ userId: "3", userName: "王五", dept: deptList[1] })

let car: Car = { vehicleNo: "京ABC2", vin: "1111" }

let pair: Pair<Car, Phone> = [car, null]

let result: ResultDto<Car> = {
    code: 0,
    msg: "success",
    data: car
}

let respDto:ResponseDto<Car>=ResponseDto.success(car)
</script>

总结:

  • interface、type、class的区别和使用场景,大家可以搜搜,或者问问AI,本文就不水了。
  • class,搞Java的一看就知道怎么回事,几乎一模一样。
  • 如果像代码那样,get/set方法,仅仅是单纯地存取值,没有额外的逻辑,在JS中是很少用的,一般都是public字段,然后res.code这么存、取就行。
  • 如果只有get,没有set,此字段为只读。
  • 导入的如果是interface、type,导入前面要加type。class则不用。
  • ref、reactive的具体应用后文会讲。

如果要写一个用于接收服务端返回响应数据的通用类,一般是interface和class配合,写法如下:

export interface IResponse<T> {
    code: number
    msg: string
    data: T | null
}

export class ResponseClass<T> {
    code: number
    msg: string
    data: T | null

    constructor(response: IResponse<T>) {
        this.code = response.code
        this.msg = response.msg
        this.data = response.data
    }

    success(): boolean {
        return this.code === 0
    }

    fail(): boolean {
        return !this.success
    }
    //按需写一些其他处理逻辑
}
最近发表
标签列表