Typescript: Wrong "possibly 'undefined'" assertion

Created on 10 Jan 2019  路  6Comments  路  Source: microsoft/TypeScript


TypeScript Version:
3.2.2


Search Terms:
Cannot invoke an object which is possibly 'undefined'.
Object is possibly 'undefined'.

Code:

type ElementRef = (element: HTMLElement | null) => void;

type ThumbProps = React.HTMLProps<HTMLDivElement> & {
  elementRef?: ElementRef;
}

type ComponentProps = React.HTMLProps<HTMLDivElement> & {
  thumbYProps?: ThumbProps;
}

class Component extends React.Component<ComponentProps>{
  public thumbYElementRef  = (ref: HTMLElement | null) => {
    this.thumbYEl = ref;
    typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref);
  };
}

Expected behavior:
Compillation without errror.
Due to previous check typeof this.props.thumbYProps!.elementRef === 'function' it can't be undefined.

Actual behavior:
Cannot invoke an object which is possibly 'undefined'.
Problem solves if add non-null assertion, but it is unnecessary here!

// this one will compile fine
  public thumbYElementRef  = (ref: HTMLElement | null) => {
    this.thumbYEl = ref;
    typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef!(ref);
  };

Playground Link:

Related Issues:

Bug

Most helpful comment

@xobotyi aaaaaaand now it's fixed 馃槈

All 6 comments

This is probably because of the _other_ assertion you have in there causing TS to think the types are unrelated (hypothesis: it synthesizes one asserted-non-null type for this.props.thumbYProps!, refines that one instance of it, and then it synthesizes another one when you assert it again on the right side so the new instance is missing the refinement).

@Kovensky looks like you're right.

public thumbYElementRef = (ref: HTMLElement | null) => {
    this.thumbYEl    = ref;
    const thumbProps = this.props.thumbYProps!;
    typeof thumbProps.elementRef === 'function' && thumbProps.elementRef(ref);
};

Has no errors.

But I'm still thinking that proper behavior is to have no errors in given example.

Dont know about implementation possibility and sadly has no time to read tsc sources.
If you're right about assertion synthesis, issue solvation will require significant changes, cause it supposes identicall equality of variables assertions with same accessor string within one expression statement.

You would be correct. An assertion prevents us from tracking refinements to the asserted reference right now (it's kinda a known limitation). As @xobotyi points out, you can usually work around that by storing the asserted value in a temporary and reusing it.

One bad thing about that workaround - useless variable in generated code.

@xobotyi aaaaaaand now it's fixed 馃槈

@weswigham a-we-some!
Thank you very much.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MartynasZilinskas picture MartynasZilinskas  路  3Comments

uber5001 picture uber5001  路  3Comments

zhuravlikjb picture zhuravlikjb  路  3Comments

blendsdk picture blendsdk  路  3Comments

jbondc picture jbondc  路  3Comments