🎖️typeScrpt中如何从类派生接口?

简介: 在面向对象编程(OOP)中,通常我们会定义接口,并在不同的类中实现这些接口。但在 TypeScript 中,我们也可以进行反向操作,即从一个类中派生一个接口,而无需实际定义这个接口

嗨,大家好!这里是道长王jj~ 🎩🧙‍♂️

在面向对象编程(OOP)中,通常我们会定义接口,并在不同的类中实现这些接口。但在 TypeScript 中,我们也可以进行反向操作,即从一个类中派生一个接口,而无需实际定义这个接口。这种做法在多种场景下非常有用,比如为 JavaScript 类创建类型安全的模拟。这能确保模拟类实现了原始类的所有方法,而无需额外定义独立的接口。

提取实例类型

首先,我们需要从类中提取实例类型。默认情况下,当你在 TypeScript 中检索类的类型时,你会获得类的构造函数类型,而不是该类实例的类型。为了获得实例类型,我们可以定义一个实用型:

type ExtractInstanceType<T> = T extends new (...args: any[]) => infer R ? R : T extends {
    prototype: infer P } ? P : any;

这里的 ExtractInstanceType<T> 首先尝试从类的构造函数中推断实例类型。如果构造函数不可公开访问,它会从类的原型属性中推断实例类型。这与 TypeScript 内置的 InstanceType<T> 工具类型的主要区别在于,后者只适用于公开的构造函数。

考虑以下带有私有构造函数的类:

class SomeClass {
   
  private constructor() {
   }
  someMethod() {
   }
}

//> OK: 类型为 SomeClass
type SomeClassInstance = ExtractInstanceType<typeof SomeClass>; 

//> Error: 类型 'typeof SomeClass' 无法满足约束 'abstract new (...args: any) => any'。
type SomeClassInstanceError = InstanceType<typeof SomeClass>

从实例类型中提取方法

一旦我们有了实例类型,我们可以提取出它的方法。为此,我们可以定义另外两个实用型:

type ExtractMethodNames<T> = {
    [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never }[keyof T];
type ExtractMethods<T> = Pick<T, ExtractMethodNames<T>>;

ExtractMethodNames<T> 是一个映射类型,它遍历 T 的所有属性,并检查每个属性是否对应于一个方法。如果是方法,则保留该属性的键;否则,将该键分配为 never 类型。

ExtractMethods<T> 利用 Pick 工具类型从 T 中仅选择那些属于方法的属性。

现在,让我们使用这些实用型从 SomeClassInstance 中提取方法:

type SomeClassMethods = ExtractMethods<SomeClassInstance>;

在这个示例中,SomeClassMethods 是仅包含 SomeClass 实例方法的类型。

使用提取的方法实现类

最后,我们来看看如何定义一个实现了 SomeClassMethods 类型的新类。通过确保类的类型为 SomeClassMethods,我们可以确保该类具有与 SomeClass 实例相同的方法。

//> OK: 类实现了 SomeClass 中的方法
class SomeClassMock implements SomeClassMethods {
   
  someMethod() {
   }
}

//> Error: 类 'SomeClassMockError' 不正确地实现了接口 'SomeClassMethods'。
//> 类型 'SomeClassMockError' 中缺少属性 'someMethod',但在类型 'SomeClassMethods' 中是必需的
class SomeClassMockError implements SomeClassMethods {
   
  anotherMethod() {
   }
}

在这段代码中,SomeClassMock 是一个实现了 SomeClassMethods 类型的新类。这确保了 SomeClassMock 包含了 someMethod 函数。如果 SomeClassMock 不包含 someMethod 函数,或者 SomeClassMock 中的 someMethod 函数与 SomeClassMethods 中的函数不匹配,TypeScript 将引发编译错误。🛠️


🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?当你处于这个阶段时,你发现什么对你帮助最大?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨

目录
相关文章
|
程序员 C++
28.【C++ 继承与派生 (详解)】(一)
28.【C++ 继承与派生 (详解)】
89 0
|
C++
28.【C++ 继承与派生 (详解)】(二)
28.【C++ 继承与派生 (详解)】
77 0
|
8月前
|
安全 Java 编译器
C++:继承与派生
C++:继承与派生
|
8月前
|
C++
【C++】——继承和派生
【C++】——继承和派生
|
8月前
|
程序员 C++
48继承与派生
48继承与派生
54 0
|
数据安全/隐私保护 C++
C++ 类的继承与派生
C++ 类的继承与派生
95 0
C++中的继承和派生
C++ 中的继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承类似,例如儿子继承父亲的财产。 继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。 在C++中,派生(Derive)和继承是一个概念,只是站的角度不同。继承是儿子接收父亲的产业,派生是父亲把产业传承给儿子。 被继承的类称为父类或基类,继承的类称为子类或派生类。“子类”和“父类”通常放在一起称呼,“基类”和“派生类”通常放在一起称呼。 派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。
继承和派生
🐰继承和派生的概念 🐰派生类的声明 🐰派生类的构成 🌸1.从基类接受成员 🌸2.调整从基类接受的成员 🌸3.增加新成员 🐰派生类中基类成员的访问属性 🌸公用继承: 🌸私有继承: 🌸受保护的继承: 🐰总结
C++学习——继承与派生
C++学习——继承与派生
150 0
C++学习——继承与派生

热门文章

最新文章