Difference between Union Types with Null and Nullable Object declaration in Typescript

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

Live Example in the Playground


There is a big difference. The ? modifier is actually equivalent to | undefined.

These are entirely equivalent:

myVariable: FileSource | undefined;
mySecondVariable?: FileSource;