我有两个班,:help function-range-example
和Database
。我有一个函数,它接受数据库类实例作为参数。如何确保该函数仅接受数据库类实例,而不接受其他任何实例。
我知道我可以使用DatabaseEnc
来检查实例是否属于checkConn函数中的数据库。但是我正在寻找一种基于打字稿的解决方案。
instance of
除了数据库以外,我不能将其他任何实例传递给/* database.ts */
class Database {
public state: string = null;
constructor(state: string) {
this.state = "some state";
}
}
export default Database;
/* database_enc.ts */
class DatabaseEnc {
public state: string = null;
constructor() {
this.state = "some other state";
}
}
export default DatabaseEnc;
/* provider.ts */
import Database from "./database";
import DatabaseEnc from "./database_enc";
function checkConn(db: Database): void {
Log.print(db);
}
// wrong, I should not be allowed to pass DatabaseEnc
// instance to the checkConn function parameter
const test = new DatabaseEnc();
checkConn(test);
// right, checkConn function should only accept Database
// class instance as a parameter
const test1 = new Database();
checkConn(test1);
// what is happening? I am allowed to pass any class's instance
// to the checkConn function.
函数。
答案 0 :(得分:1)
TypeScript在结构上是类型化的,这意味着如果两个类型具有相同的结构,则将它们视为相同。请参阅TS文档中的Type Compatibility部分。这是一个方便的行为,并且从JS的角度来看是正确的,因为这两个对象都将在运行时具有相同的属性。
话虽这么说,当这两个类分开时,您将开始遇到类型错误(例如,通过向Database
类添加新属性),因此您仍然会得到某种类型的控件以后。
我认为您不应该尝试破解这种行为并接受它,因为这是与("program to interfaces, not implementations")一起使用的好原则。您应该期望对象具有特定的能力,而不是期望某些特定的类。
interface Checkable {
checkConnection: (param: string) => boolean
}
class Database implements Checkable {
// ...
checkConnection(param: string) {
return true
}
}
// Is not Checkable.
class DatabaseEnc {
// ...
}
// Allow all objects that can be checked.
function checkConn(db: Checkable): void {
Log.print(db.check());
}
const test = new DatabaseEnc();
checkConn(test); // OK
const test1 = new Database();
checkConn(test1); // Error, since it doesn't implements the Checkable interface.