typescriptnullablestrictstrictnullchecks

Can I disable distinguishing between null and undefined in TypeScript strict null-checking mode?


I'm currently converting a large TypeScript codebase to strict null-checks. The codebase has many types with optional members:

interface MyInterface {
  member1?: number;
  member2?: string;
}

Furthermore, it uses a type Nullable<T> = T | null, and has many return null statements.

Now I'm facing many compiler errors which basically state that T | null cannot be converted to T | undefined, or vice versa, like in this example:

interface MyInterface {
  member1?: number;
  member2?: string;
}

const myFunction = () => {
  return null;
}

const item: MyInterface = {};
item.member1 = myFunction();      // <== can't assign null to undefined

I love strict null-checking in TypeScript, but I have no use for the distinction between null and undefined. I can appreciate that there are some use cases where it makes sense to distinguish between null and undefined, but in this project, it really does not play an important part. These functions that return null just return nothing - it does not matter whether it is null or undefined. Same goes for the optional members - they are either set to a value, or they are not.

I also prefer to not convert the member1?: number; to member1: Nullable<number>;, and to leave the return null as they are

Can I disable the distinction between undefined and null, at least in TypeScript?


Solution

  • I'd better to wrote a comment, but since I want to show you some code example I leave it as answer.

    If I were you, I would add some wrapper for all your interfaces with optional (weak) properties.

    Here is an example of such wrapper:

    
    type MapNullable<T> = {
        [P in keyof T]: undefined extends T[P] ? (T[P] | null) : T[P]
    }
    
    interface MyInterface {
      member1?: number;
      member2?: string;
    }
    
    const myFunction = () => {
      return null;
    }
    
    const item: MapNullable<MyInterface> = {};
    item.member1 = myFunction(); // member1?: number | null | undefined
    

    MapNullable iterates through all properties. If property is optional, it just extend this property with one more type - null, if property is not optional it leaves it as is.

    I understand it is not the best solution, but at least it can help you with migration. Once, you migrate, you can make your types more robust and get rid of MapNullable interface.

    MapNullable is not the best name for type, but still better than Foo or Bar

    I agree with @jcalz, I can't imagine other way to handle undefined|null in other way

    UPDATE

    It looks like your code works without error in TS playground. Please see here

    I have disabled strictNullChecks. There is no error.

    You should explicitly set return type of your function.

    const myFunction = ():null => {
      return null;
    }
    

    TS version: 4.0.2