2

I have the following code:

private extractInitials(fullname: string): string {
    const initials = fullname
        .replace(/[^a-zA-Z- ]/g, '')
        .match(/\b\w/g)
        .join('')
        .toUpperCase();
    return initials.substring(0, 2);
}

I'm getting an error enter image description here

[ts] Object is possibly 'null'. [2531]

So I tried if fullname { const initials .... return ... } else return '';

Turns out typescript was complaining about this guy

fullname.replace(/[^a-zA-Z- ]/g, '')

Which makes sense because this might end up being an empty string

So I did

const t = fullname.replace(/[^a-zA-Z- ]/g, '')
if(t) { /* do the rest */ } else return ''

and it still gave me the object is possibly null error. I know it's not. How do I fix?

Max
  • 965
  • 1
  • 10
  • 28
Asool
  • 13,031
  • 7
  • 35
  • 49
  • 2
    It's the *match* that might be null, hence that's where the underlining is. – jonrsharpe Dec 11 '18 at 17:22
  • 2
    *"Which makes sense because this might end up being an empty string"* No, that doesn't make sense. `""` is not `null`. They're quite different things. – T.J. Crowder Dec 11 '18 at 17:24
  • You can use a non-null assertion on the match result if you're confident the source string will be non-empty: `.match(/\b\w/g)!` -- if the text is empty you will get `null` from that and `.join()` will throw an error. – Aaron Beall Dec 11 '18 at 20:00

3 Answers3

11

The issue is that match can return null. If you want a blank string as as result, just use the || trick¹ to do || [] on the result of match:

private extractInitials(fullname: string): string {
    const initials =
        (fullname
        .replace(/[^a-zA-Z- ]/g, '')
        .match(/\b\w/g)
        || []
        )
        .join('')
        .toUpperCase();
    return initials.substring(0, 2);
}

If you want to return null in that case instead, you can use the && trick¹ to return the null if the match result is null, otherwise continuing on with your join etc.:

private extractInitials(fullname: string): string {
    const parts = fullname
        .replace(/[^a-zA-Z- ]/g, '')
        .match(/\b\w/g);
    return parts && parts.join('').toUpperCase().substring(0, 2);
}

¹ The || trick is that || evaluates its left-hand operand and, if it's truthy², takes that value as its result; otherwise it evaluates its right-hand operand and takes that value as its result. The && trick is similar, just the other way around: It evaluates its left-hand operand, and if it's falsy³, takes that value as its result; otherwise, it evaluates its right-hand operand and takes that value as its result.

² falsy - null, undefined, "", 0, NaN, or (of course) false

³ truthy - not falsy

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
4

I run into a similar issue, in my case, all I did was to add the following rule to the tsconfig.json

"strictNullChecks": false
"noImplicitAny": false,

That should do the work

Alberto S.
  • 1,805
  • 23
  • 39
0

One possible solution to remove the null check error could be to use Optional Chaining.

const extractInitials = (fullname: string): string  => {
    const initials = fullname.replace(/[^a-zA-Z- ]/g, '').match(/\b\w/g)?.join('').toUpperCase();
    return initials?.substring(0, 2) || '';
}

This will return an empty string if the result of regex match is null, otherwise will return the expected output. You can try running it with different values in the TS playground here.

This has been explained in another answer here as well.

vpuri
  • 39
  • 1
  • 10