Typescript: Compiler does not take into account truthy check and falsy alarm of possibly null.

Created on 4 Apr 2020  路  3Comments  路  Source: microsoft/TypeScript

First of all thank you for sharing awesome technology with community 鉂わ笍
TypeScript Version: 3.8.3


Search Terms:
Object is possibly null, incorrectly possibly null, truthy check, 2531 ...

Code

Simplified example

type MyType = {
  prop: any;
} | null;

function myMethod(arg: MyType) {
    return arg && (arg as MyType).prop;
}

Project real case

export interface Message {
  translationKey: string;
  values?: any[] | { [key: string]: any };
}

type MessagesTree = {
  [key: string]: Message | Message[] | MessagesTree | null;
} | null;

const castArray = (val:any) => (Array.isArray(val) ? val : [val]);

function myMethod(messages: MessagesTree = {}) {
    return castArray(messages).filter(
      (msg: Message | MessagesTree) =>
        msg && (msg.translationKey || (msg as MessagesTree).explicit));
//      ^ truthy check                               ^ Object is possibly 'null'. ts(2531)

}

Expected behavior:
it is not possible to get there null as it is after truthy check, therefore I would expct not to get error about possible null

Actual behavior:
it raises possible null error
I need to force non-null by "!" ---> (msg as MessagesTree)!.explicit to avoid error

Playground Link: https://www.typescriptlang.org/play?#code/C4TwDgpgBAsiAq5oF4oG8BQUpgE4HswAuKAQwDsQBuDAXygB8pyBXAGzZowDMXyBjYAEt85KAFsQMCMAAW+ACYAKUrgDmJOIkgBKdFmxRcMlrjGq1UAGRWoK9WQDOsBEh0A6PIRq0MfiAAeYPi4wFBC5MAQuNyk-NDSjo6katCY2MC4FI5spMKiANIQICSOmRFqNNgAbqRsLBCOAPwkFCAA2gC6jOhQ7QDWxaXl5GqdrZRQtD5+oJCwjcmpjvDGKPrYA0NQZbgV4wtJKdBMiUsQXT1nxytrPawcPvfsnH78omVQ-KRlAIK4WRAUFQSlqbCIbT0yAAfHZ-oD3EJHPDSCBQXU9E0oGCoCR2mDOjouLwBPkxJJpHJFAAmJTiRY3TQM5arCDrNC0PTpQzGYCmMTfP4A1F05mNDzcIRsKK4JQGQzYAD0iqgkul0Sg+BYYVibEcQLBDWcAFpYaR+qRmC8yOQFMxRDsWGBgqEIHb8AAjABWEEEjnlhjpjg0h3OVzFtzZUOhAYV4mD1lsQbU7ky2VyZKKQIYTGTTlDN1ZEA8gTAbCE-CEwB0RL8vmwQA

Related Issues: Did you find other bugs that looked similar? No, all I found had differences and therefore their explanations/solutions did not match my case.

Thank you! 馃檹

Working as Intended

Most helpful comment

When you assert the type, you undo any type narrowing that was done. You are saying to the compiler "trust me, forget everything you know, but the type could include null". If you don't want the compiler to think it might be null don't assert a type that could possible be null.

This works as expected:

type MyType = {
  prop: any;
} | null;

function myMethod(arg: MyType) {
    return arg && arg.prop;
}

All 3 comments

When you assert the type, you undo any type narrowing that was done. You are saying to the compiler "trust me, forget everything you know, but the type could include null". If you don't want the compiler to think it might be null don't assert a type that could possible be null.

This works as expected:

type MyType = {
  prop: any;
} | null;

function myMethod(arg: MyType) {
    return arg && arg.prop;
}

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Ok I will be using "!" in such cases.

Was this page helpful?
0 / 5 - 0 ratings