工厂函数类型定义:代表任意一个类的构造函数 的函数类型
泛型工厂函数定义:一个可以创建任意类对象的通用泛型函数
泛型工厂函数应用场景:
使用场景1:在一些不方便或者没有办法直接 new 类名来创建对象(如装饰器)
使用场景2:在一些项目测试或者调试中简化代码使用。
class Son {
public cname: string = "名字";
public sex = "未知";
static count: number;
//鼠标放construct上会就显示:constructor Son(cname: string, sex: string): Son
constructor(cname: string, sex: string) {
this.cname = cname;
this.sex = sex;
}
eat(): void {}
}
//Son这个类名变量,有双重性质 1.类构造函数对象变量 2.创建类对象的一个类型【new 后面出现的就是】
type promiseFuncType = (resolve: string, reject: string) => any; // 这个是函数类型
type ConstructorType = new (...arg: any) => any; //这是工厂函数类型
// 工厂函数类型 [代表任意一个 类构造函数对象变量 的函数类型]
// 这个new 不是创建的意思,而是表示后面的类型是一个 类构造函数对象变量的类型【类构造函数的类型】
工厂函数
//function Factory(Constructor: { new (...arg: any): any }) {
// 上面是interface类型,下面是type类型,一个意思。记得interface需把=>改成:
function Factory(Constructor: ConstructorType) {
console.log(Constructor.name + "被工厂函数创建对象");
return new Constructor("小A", "男"); //值暂时写死,后面再写工厂函数如何传参
}
// 使用工厂函数来new创建对象
let obj = Factory(Son); //obj是any类型,所以不能点操作
console.log("obj:", obj); //obj: Son { cname: '小A', sex: '男' }
泛型工厂函数
function Factory2<T>(Constructor: { new (...arg: any): T }): T {
console.log(Constructor.name + "被泛型工厂创建对象");
return new Constructor("小B", "男");
}
let obj2 = Factory2<Son>(Son); //obj2是Son类型,自然可以点操作
console.log("obj2:", obj2);
交叉类型
//定义:将多个类型合并【多个类型属性和方法的并集】成的类型就是交叉类型。
type objtype1 = { username: string, age: number }
type objtype2 = { custname: string, phone: number, age: number }
type objtype3 = { address: string }
let first: objtype1 = { username: "wangwu", age: 23 }
let second: objtype2 = { custname: "lisi", phone: 111, age: 23 }
// 定义:将多个类型合并【多个类型属性和方法的并集】成的类型就是交叉类型。
let jiaochatype: objtype1 & objtype2 & objtype3 = {
username: "wangwu", age: 23, custname: "lisi", phone: 111, address: "shanghai"
}
let uniontype: objtype1 | objtype2 = {
username: "wangwu", age: 23, custname: "lisi", phone: 111
}
泛型函数重载+ 交叉类型+ 类型断言
interface Button {
btntype: string;
text: string;
}
interface Link {
alt: string;
href: string;
}
interface Href {
linktype: string;
target: Openlocation;
}
enum Openlocation {
self = 0,
_blank,
parent,
}
let button: Button = {
btntype: "normal",
text: "跳转",
};
let link: Link = {
alt: "goto",
href: "xx.com",
};
let href: Href = {
linktype: "xx网",
target: Openlocation._blank,
};
type union<T = any> = Extract<T, object>;
function cross<T, U>(objOne: union<T>, objTwo: union<U>): T & U;
function cross<T, U>(objOne: union<T>, objTwo: union<U>): T & U;
function cross<T, U, V>(
objOne: union<T>,
objTwo: union<U>,
objThree: union<V>
): T & U & V;
function cross<T, U, V>(
objOne: union<T>,
objTwo: union<U>,
objThree?: union<V>
) {
let obj = {};
let combine = obj as T & U;
Object.keys(objOne).forEach((key) => {
combine[key] = objOne[key];
});
Object.keys(objTwo).forEach((key) => {
if (!combine.hasOwnProperty(key)) {
combine[key] = objTwo[key];
}
});
if (objThree) {
//如果有第三个对象传递进来实现交叉
//let obj = {}
//let combine2 = obj as T & U & V
//let combine2=combine as T & U & V
let combine2 = combine as typeof combine & V;
Object.keys(objThree).forEach((key) => {
if (!combine2.hasOwnProperty(key)) {
combine2[key] = objThree[key];
}
});
return combine2; // 三个对象交叉结果
}
return combine; // 两个对象交叉结果
}
let combine = cross(button, link);
console.log(combine);
let combine2 = cross(button, link, href);
console.log(combine2);
export {};
泛型工厂函数+传参
class TestClass {
// 准备类
public name: string;
public classno: number;
constructor(name: string, classno: number) {
this.name = name;
this.classno = classno;
}
eat() {
console.log("姓名为: " + this.name + ",班级:" + this.classno);
}
}
//TestClass这个类名变量,有双重性质 1.类构造函数对象变量 2.创建类对象的一个类型【new 后面出现的就是】
//new TestClass(); //这个实例化,TestClass类名不是构造函数的代名词,而是一个类型
//type Constructor<T> = new (...args: any[]) => T; //这个函数类型,有new是构造函数类型
//想获取TestClass类中构造函数的参数及类型,方法如下:
type CstParams<T> = T extends new (...args: infer P) => any ? P : never;
type funType = new (name: string, classno: number) => any;
let test: CstParams<funType>; //test: [name: string, classno: number]
type funType1 = typeof TestClass;
let test1: CstParams<funType1>; //test1: [name: string, classno: number]
//上面2个例子结果都是一样,得到元组,说明testClass是类构造函数代名词
上面的方式加上泛型约束
type TypCstParams2<T extends new (...args: any[]) => any> = T extends new (
...args: infer P
) => any
? P
: never;
type TypConstructor<T> = new (...args: any[]) => T; //通用泛型构造函数约束
//------------------------------------------------------
//这句不能提出来:CP extends new (...args: any[]) => any
function createInstance<T, CP extends new (...args: any[]) => any>(
constructor: TypConstructor<T>,
...args: TypCstParams2<CP>
) {
return new constructor(...args);
}
createInstance<TestClass, typeof TestClass>(TestClass, "wangwu", 105).eat();
网友评论