8000 Type narrowing doesn't work for class using generic Readonly<Props> · Issue #22137 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content
Type narrowing doesn't work for class using generic Readonly<Props> #22137
Closed
@ms-markda

Description

@ms-markda

TypeScript Version: "2.8.0-dev.20180221"
Not in "2.7.0-rc"

Search Terms: type narrowing class generics function method call props readonly

Code

// Loose function or method. Same result.
declare function bar(thing: string): void;

interface Base {
    thing?: string;
}
class Example<Props extends Base> {
    props: Readonly<Props>;
    mutableProps: Props;
    base: Readonly<Base>;

    foo() {
        if (this.props.thing) {
            this.props.thing.toString(); // No error
            bar(this.props.thing); // Error!
        }
        if (this.mutableProps.thing) {
            bar(this.mutableProps.thing); // No error
        }
        if (this.base.thing) {
            bar(this.base.thing); // No error
        }
    }
}

Expected behavior:

No error.

Actual behavior:

TypeScript error, but only with that combination of generics, Readonly, a class, and calling a function. Remove any one of those factors and it works as expected. Some examples of that are also shown above.

Argument of type 'P["thing"]' is not assignable to parameter of type 'string'.
  Type 'string | undefined' is not assignable to type 'string'.
    Type 'undefined' is not assignable to type 'string'.

Playground Link:

Note: Turn on StrictNullChecks.

https://www.typescriptlang.org/play/#src=%0D%0A%2F%2F%20Loose%20function%20or%20method.%20Same%20result.%0D%0Adeclare%20function%20bar(thing%3A%20string)%3A%20void%3B%0D%0A%0D%0Ainterface%20Base%20%7B%0D%0A%20%20%20%20thing%3F%3A%20string%3B%0D%0A%7D%0D%0Aclass%20Example%3CProps%20extends%20Base%3E%20%7B%0D%0A%20%20%20%20props%3A%20Readonly%3CProps%3E%3B%0D%0A%20%20%20%20mutableProps%3A%20Props%3B%0D%0A%20%20%20%20base%3A%20Readonly%3CBase%3E%3B%0D%0A%0D%0A%20%20%20%20foo()%20%7B%0D%0A%20%20%20%20%20%20%20%20if%20(this.props.thing)%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.props.thing.toString()%3B%20%2F%2F%20No%20error%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20bar(this.props.thing)%3B%20%2F%2F%20Error!%0D%0A%20%20%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%20%20%20%20if%20(this.mutableProps.thing)%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20bar(this.mutableProps.thing)%3B%20%2F%2F%20No%20error%0D%0A%20%20%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%20%20%20%20if%20(this.base.thing)%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20bar(this.base.thing)%3B%20%2F%2F%20No%20error%0D%0A%20%20%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A

Related Issues:

None that I am aware of. This showed up when updating TypeScript, so it is probably a recent regression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    InvestigatingIs in active investigationSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0