Can I write a type guard asserting something about one or multiple sub-objects of an argument? In pseudo-code, it might look like this:
class C {
a: number?;
b: string?;
function assertInitialized() : (this.a is number) and (this.b is string) {
return this.a !== null && this.b !== null;
}
}
Background: I'd commonly use a single function to check invariants of my classes; for example, assume I have a class with some nullable fields, which get asynchronously initialized.
class DbClient {
dbUrl: string;
dbName: string;
dbConnection: DBConnection?;
…
}
This class goes through a complex asynchronous initialization process, after which dbConnection
becomes non-null. Users of the class must not call certain methods until dbConnection is initialized, so I have a function assertReady
:
assertReady() {
if (this.dbConnection === null) {
throw "Connection not yet established!";
}
}
This function assertReady
is called at the beginning of each function that requires the DbClient
to be fully initialized, but I still have to write non-null assertions:
fetchRecord(k: string) {
assertReady();
return this.dbConnection!.makeRequest(/* some request based on k */);
}
Can I give assertReady
a signature that makes the !
unnecessary? I don't want to pass this.dbConnection
to assertReady
, because that function is typically more complex.
The only trick I'm aware of is to create an interface with the same fields as the current class, but with non-nullable types (without the ?
). Then I can make a type guard that says that this is InitializedDbClient
. Unfortunately that requires duplicating a large part of the class definition. Is there a better way?