I am looking for a way to tell Typescript that the property I'm trying to access is not null/undefined
.
I'm aware of
?
optional chain operator!
non-null assertion operator
Here is what I'm trying to do
type UpsertRequestType = {
per_page?: number;
page_window?: number;
};
type SettingsCollectionType = {
_id: string;
per_page: number;
page_window: number;
};
class Settings {
constructor(private readonly settingsRepository: Mongo.Collection<SettingsCollectionType>) {}
private get settings() {
return this.settingsRepository.findOne({}) || null;
}
upsert(payload: Optional<UpsertRequestType>): void;
upsert(payload: Required<UpsertRequestType>): void;
upsert(payload: unknown): void {
if (this.settings) return this.update(<Optional<UpsertRequestType>>payload);
return this.insert(<Required<UpsertRequestType>>payload);
}
private update(payload: Optional<UpsertRequestType>): void {
this.settingsRepository.update({ _id: this.settings!._id }, { $set: payload });
}
private insert(payload: Required<UpsertRequestType>): void {
this.settingsRepository.insert(payload);
}
}
As you can see I am using this.settings!._id
with !
symbol to clarify that _id
is there for sure. However, is there another way that TS can infer this behavior automatically?
It is pretty obvious that when I check if(this.settings)
it is not definitely null/undefined
CodePudding user response:
In this case the this.settings!._id
is inside the update
method, and the method is called inside the if
statement, but TypeScript cannot be sure that you will never call update
outside of it, thus it considers that this.settings
might be undefined
.
I don't think that you have an easy way of avoiding the !
syntax, so I would probably just keep it as it is now.
CodePudding user response:
As you wrote it, you are specifying that this.settings
exists, what you want to actually do is:
this.settings!._id!
so you specify that both settings
and _id
are not null
(or undefined
).
The exclamation mark operator is always put after the property you want to assert is not null, for a very specific reason:
let temp?: number = null
/*code happens here*/
if(temp! < 3)
// ...
In this case you couldn't really do something like: this!.temp
CodePudding user response:
In your particular case, the settings()
getter could be null. You should specify the return value of the get function to be non-nullish so you won't need to use the !
operator.