I recently found a bit of typescript code in a bigger angular project, that had a Bitwise-OR/Pipe-Symbol within its object declaration. Like this:
dataSource: FileSource | null;
In my understanding it is an object of the type FileSource that is also nullable.
dataSource = null; // Works
dataSource = new FileSource... // Works
dataSource = 32; // Error
I also found out that you can declare an object with a whole set of Datatypes like this:
myVariable: number | string | null;
Now to my actual question: I can as well declare an object with a question mark as a symbol for nullable. Is there any difference between these two declarations?
myVariable: FileSource | null;
mySecondVariable?: FileSource;
If there is no difference between these two, would you consider it a bad practice, as it is not common in other languages and no valid javascript code?
BTW: In Javascript this:
myVariable: Number | null;
myVariable = "Hello World";
would be fine.
My focus is the nullability of an object and how these declarations differ
Is there any difference between these two declarations?
Yes, particularly with strict null checks. A property with a union type (the |
symbol) is required to be present with a value that matches one of the types.
An optional property (declared with ?
) is just that: Optional. The object isn't required to have it at all. Although that said, at the moment (at least), TypeScript treats prop?: X
exactly like prop: X | undefined
; see this issue helpfully pointed out by jcatz.
Without strict null checks, this is fine:
type A = {
dataSource: Date | null
};
type B = {
dataSource?: Date
};
const a: A = { dataSource: null }; // Works
const b: B = { dataSource: null }; // Also works
With strict null checks, the second is wrong:
type A = {
dataSource: Date | null
};
type B = {
dataSource?: Date
};
const a: A = { dataSource: null }; // Works
const b: B = { dataSource: null }; // Error: Type 'null' is not assignable to type 'Date | undefined'.
Live Example in the Playground
Similarly, assigning undefined
would be fine without strict null checks, but with them, it's an error in the union type case:
type A = {
dataSource: Date | null
};
type B = {
dataSource?: Date
};
const a: A = { dataSource: undefined }; // Error: Type 'undefined' is not assignable to type 'Date | null'.
const b: B = { dataSource: undefined }; // Works