我想实现泛型方法,它将根据提供的接口返回具体类型。这在TypeScript中是否可行?
这是我的伪示例:
class Account {
private int id = 0;
private double balance = 0.0;
private double annualInterestRate = 0.0;
private java.util.Date dateCreated;
// set dateCreated for the time and date the account was created
Account() {
dateCreated = new java.util.Date();
}
// Set accounts id and balance equal to this objects
Account(int id, double balance){
this();
this.id = id;
this.balance = balance;
}
// Getters and Setters manipulating variables to be set to the created account
// Setters have no return value and set itself equal to the variable and getters
// grab the variables and return them.
public int getId() {
return this.id;
}
public double getBalance() {
return this.balance;
}
public double getannualInterestRate() {
return this.annualInterestRate;
}
public String getDateCreated() {
return this.dateCreated.toString();
}
public void setId(int id) {
this.id = id;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void setannualInterest(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
public double getMonthlyInterestRate() {
return (annualInterestRate / 100) / 12;
}
public double getMonthlyInterest() {
return balance * getMonthlyInterestRate();
}
// set balance of withdraw to balance - amount = balance
public void withdraw (double amount) {
if(amount < balance) {
balance -= amount;
}
}
// set balance of deposit to balance + amount = balance
public void deposit(double amount) {
balance += amount;
//Transaction.add(new Transaction('D', amount, balance, "Deposit to account"));
}
@Override
public String toString() {
return "Account holder name: " + CustomerAccount.name +
"\nAccount id: " + id +
"\nAnnual interest: " + this.getannualInterestRate() +
"\nMonthly Interest Rate: " + this.getMonthlyInterestRate() +
"\nBalance " + this.getBalance() +
"\nTransaction: ";
}
}
interface IDog {
canRun: boolean;
}
interface IBird {
canFly: boolean;
}
class Dog implements IDog {
canRun: boolean;
}
class Bird implements IBird {
canFly: boolean;
}
function createInstance<T>(): T {
const key = typeof T;
switch (key) {
case IBird:
return new Bird();
return
case IDog:
return new Dog();
default:
break;
}
}
// concrete is Dog
const concrete = createInstance<IDog>();
方法是我想要实现的原始示例,它不会编译!
我想为createInstance()
方法提供接口类型,并实现一些逻辑,这些逻辑将为提供的接口创建具体类型。
TypeScript可以吗?
答案 0 :(得分:1)
当然,您可以在TypeScript中执行工厂方法。一种方法:
interface IAnimal {
}
interface IDog extends IAnimal {
canRun: boolean;
}
interface IBird extends IAnimal {
canFly: boolean;
}
class Dog implements IDog {
canRun: boolean;
}
class Bird implements IBird {
canFly: boolean;
}
class AnimalFactory {
public static create(animalType: string): IAnimal {
switch(animalType) {
case 'dog':
return new Dog();
case 'bird':
return new Bird();
default:
throw new Error('Wrong animal type.');
}
}
}
const dog: IDog = AnimalFactory.create('dog');
const bird: IBird = AnimalFactory.create('bird');
请注意,工厂隐藏了实际的类名/实现,并通过接口进行操作。如果您愿意并使用构建器模式返回与IAnimal
界面兼容的动物,您可以更进一步,例如
case 'dog':
const dog: IDog = new DogBuilder()
.setColor('white')
.setWeight(30)
.build() // whatever, you get the idea
return dog;
答案 1 :(得分:1)
您需要使用重载:
function createInstance(key: 'dog'): Dog;
function createInstance(key: 'bird'): Bird;
function createInstance(key: 'dog' | 'bird') {
// implement
}
然后将密钥作为参数传递
const dog = createInstance('dog'); // typeof dog is Dog
答案 2 :(得分:0)
在运行时无法访问接口,但您可以使用添加类型检查 String Literal Types:
interface IDog {
canRun: boolean;
}
interface IBird {
canFly: boolean;
}
class Dog implements IDog {
canRun: boolean;
}
class Bird implements IBird {
canFly: boolean;
}
function createInstance(type: 'bird'): Bird;
function createInstance(type: 'dog'): Dog;
function createInstance(type: string): any {
switch (type) {
case 'bird':
return new Bird();
case 'dog':
return new Dog();
}
}
// concrete is Dog
const concrete = createInstance('dog');
另外我认为工厂返回类型应该是接口:
function createInstance(type: 'bird'): IBird;
function createInstance(type: 'dog'): IDog;
<强>更新强>
另一种方法是存储对类的引用:
interface IInterfaces {
dog: IDog;
bird: IBird;
}
type IFactory<T> = {
[P in keyof T]: new() => T[P];
}
let factory: IFactory<IInterfaces> = {
dog: Dog,
bird: Bird
}
let dog = new factory.dog();
答案 3 :(得分:0)
问题在于TS接口在运行时不可用,因此您不能使用JS创建接口。但!它们存在于代码中,因此您可以读取文件并使用使用文件系统的解决方案来解决此问题。
最近我发现了这个:https://github.com/google/intermock,它似乎真的很有用。我还没有尝试过,但这是我找到的唯一解决此问题的方法。
node build/src/cli/index.js --files ./example-file.ts --interfaces "Admin"
您选择接口所在的文件以及要从中创建对象的接口。
您可以在测试之前使用诸如husky之类的命令运行命令,以便在实际测试之前生成模拟