TypeScript 如何做构造函数类型

你写过《贪吃蛇》小游戏吧?里面的“蛇”是由一节节身体组成的,每一节都有自己的位置、颜色这些属性。要是用普通的 JavaScript 写,你可能会写一个函数来生成蛇的身体,每次调用这个函数就返回一个新的身体对象。但如果不小心写错了参数,比如把位置写成了字符串,游戏可能就会出bug。

要是换用 TypeScript 呢?它能帮你提前“揪出”这类错误——这就需要用到构造函数类型了。简单说,构造函数类型就是“规定了要生成什么样的对象模板”,就像你给《贪吃蛇》的蛇身体定了个“必须带数字位置、布尔值状态”的规矩,下次生成身体时,不符合规矩的代码就会报错。

TypeScript 如何做构造函数类型

先搞懂:构造函数类型不是“函数类型”

很多人刚接触时会混淆:函数类型是普通函数的样子,而构造函数类型是“用来生成对象的函数”的样子。举个生活化的例子:你开了一家面包店,做牛角面包的“配方”就是构造函数类型——这个配方规定了“必须用面粉、黄油、酵母”,最后要做出“带酥皮、有奶味”的牛角包。要是配方里漏了酵母,或者要做个“水果面包”,就不符合这个配方的要求。

用 TypeScript 代码来看:普通函数类型是 () => string,而构造函数类型是用 new 开头的,比如 new (name: string) => { name: string; isFresh: boolean }。意思是:这个构造函数得接收一个字符串参数 name,用 new 调用后,返回的对象必须有 name(字符串)和 isFresh(布尔值)两个属性。

怎么用构造函数类型?两步就上手

第一步:定义一个“模板”(构造函数类型)

先把你要生成的对象的要求写清楚,就像先写好面包店的牛角面包配方。比如我们要做“学生”对象,要求是:有 name(姓名,字符串)、age(年龄,数字),还有 study(学习,函数)方法。

对应的 TypeScript 代码就是:

`typescript

// 这就是学生的构造函数类型模板

type StudentConstructor = new (name: string, age: number) => {

name: string;

age: number;

study: () => void;

};

`

这里 StudentConstructor 就是我们定的“生成学生的规矩”,它规定了构造函数的参数和返回对象的样子。

第二步:用这个“模板”生成实例

接下来,你可以写一个真正的构造函数,它必须符合这个模板的要求。比如我们写一个 createStudent 函数,用它生成学生:

`typescript

// 符合StudentConstructor的构造函数

const createStudent: StudentConstructor = function(name, age) {

return {

name: name,

age: age,

study: () => console.log(${name}在认真学TypeScript)

};

};

// 用new调用,生成学生实例

const myStudent = new createStudent("小明", 12);

console.log(myStudent.name); // 输出:小明

myStudent.study(); // 输出:小明在认真学TypeScript

`

要是你写错了——比如参数少写一个,或者返回对象少了 study 方法——TypeScript 会直接报错,比如“类型 '{ name: string; age: number; }' 缺少属性 'study'”,帮你提前找到问题。

再进阶:用构造函数类型做更灵活的事

要是你想让生成的对象能兼容不同类型,比如不仅能生成学生,还能生成老师,可以用“泛型”让模板更灵活。还是用面包店的例子:牛角面包和吐司面包的配方,都可以用“面包”这个泛型模板来定义。

比如我们做一个“可学习的人”的构造函数类型,支持学生、老师:

`typescript

// 泛型构造函数类型,T是要生成的对象类型

type PersonConstructor<T> = new (name: string, age: number) => T;

// 学生类型

interface Student {

name: string;

age: number;

grade: number; // 学生多了年级属性

study: () => void;

}

// 老师类型

interface Teacher {

name: string;

age: number;

subject: string; // 老师多了科目属性

teach: () => void;

}

// 生成学生的构造函数,符合PersonConstructor<Student>

const createStudent: PersonConstructor<Student> = function(name, age) {

return { name, age, grade: 5, study: () => console.log(${name}学五年级) };

};

// 生成老师的构造函数,符合PersonConstructor<Teacher>

const createTeacher: PersonConstructor<Teacher> = function(name, age) {

return { name, age, subject: "数学", teach: () => console.log(${name}教数学) };

};

`

这样,同一个 PersonConstructor 模板,就能生成不同类型的对象,代码复用性更高,还不会出错。

简单说,TypeScript 的构造函数类型就是给“生成对象的函数”定规矩,就像你给玩具车定“必须有轮子、能跑”的规则,最后造出来的车就不会是缺轮子的次品,写代码也更省心。

上一篇 C / C++ 编程语言的核心应用场景与入门学习要点科普