gpt4 book ai didi

typescript - 如何使用 Type Script 中的反射获取实现某个基类的子类?

转载 作者:行者123 更新时间:2023-11-28 03:54:41 43 4
gpt4 key购买 nike

我们可以像 C# 一样在 Type Script 中使用反射来获取实现某个基类的类列表吗?

例如,假设 Snake 和 Horse 实现了基类 Animal。现在我需要获取实现 Animal 的类。类似于我们在 C# 中可以做的事情:

C# 等效代码:

var childTypes = assembly.GetTypes().Where(_ => _.IsSubclassOf(typeof(Animal)));

类型脚本类:

class Animal {
}

class Snake extends Animal {
}

class Horse extends Animal {
}

最佳答案

如果您愿意依赖一个可能很快就会发生变化的功能,因为它基于过时的规范,并且如果您愿意仅使用类而不是接口(interface),那么您可以使用装饰器。

这是一个例子:

hierarchy-tracked.ts

export default function hierarchyTracked(target: new (...args: any[]) => object) {
for (const proto of walkPrototypeChain(target)) {
if (!Object.hasOwnProperty.call(proto, 'extendedBy')) {
const extendedBy: typeof Function.extendedBy = [];
Object.defineProperty(proto, 'extendedBy', {
get: () => extendedBy
});
}
// ! is used to suppress a strictNullChecks error on optional.
// This is OK since we know it is now defined.
proto.extendedBy!.push(target);
}
}

declare global {
interface Function {
// Declared as optional because not all classes are extended.
extendedBy?: Array<new (...args: any[]) => object>;
}
}

function* walkPrototypeChain(target: new (...args: any[]) => object) {
let proto = Reflect.getPrototypeOf(target);
while (proto && proto !== Object) {
yield proto;
proto = Reflect.getPrototypeOf(proto);
}
}

animals.ts

import hierarchyTracked from './hierarachy-tracked';

export class Animal {
alive = true;
static get slayable() {return true;}
static extinct = false;
}

@hierarchyTracked export class Snake extends Animal {
isEctotherm = true;
}

@hierarchyTracked export class Cobra extends Snake {
isDeadly = true;
}

@hierarchyTracked export class Horse extends Animal {
isEndotherm = true;
}
// logs
Animal.extendedBy && Animal.extendedBy.map(Taxon => Taxon.name)
.forEach(name => {
console.log(name);
});
// Snake
// Cobra
// Horse

Snake.extendedBy && Snake.extendedBy.map(Taxon => Taxon.name)
.forEach(name => {
console.log(name);
});
// Cobra

不需要诉诸全局状态,它实际上非常整洁和明确。

这也适用于 Babel 7如果您不使用 TypeScript。 (请注意,上述关于装饰器使用的相同警告仍然适用)

当然,如果您不想依赖装饰器,那么手动编写这很简单:

import trackHierarchy from './hierarachy-tracked';

export class Animal { }

class Snake extends Animal { ... }
trackHierarchy(Snake);

export {Snake};

回到上面的示例代码,很容易实现。

它来自

var childTypes = assembly.GetTypes().Where(_ => _.IsSubclassOf(typeof(Animal)));

简单

const childClasses = Animal.extendedBy || [];

警告

如果您发现自己想要编写这样的代码,您应该退一步并确保您确实了解 JavaScript。这种模式,以及您的示例用例,通常表明有人以经典思维方式接触该语言,注意到 ES 2015 类,并开始认为它们与传统语言中的类相关。

ES 类与 C#、C++、Java 或 Scala 类非常相似。

首先也是最重要的一点:JavaScript 中的类不是类型。

JavaScript 中的类是

他们的声明形式从根本上来说只是原型(prototype)上的语法糖。您试图实现的模式表明您可能不太理解这一点。特别是,它表明您可能认为它们特别

关于typescript - 如何使用 Type Script 中的反射获取实现某个基类的子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47656605/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com