Skip to content

Destructing an optional prop of a Readonly generic with a default, the type is narrowed incorrectly #22823

@agubler

Description

@agubler

TypeScript Version: 2.7.2 & 2.8.0-insiders.20180320

Search Terms:

Description

For a generic (that is being mapped with Readonly<>), it's properties are being narrowed to the value that is assigned as a default during destructuring with strictNullChecks set to true. I have seen this for boolean and enum types.

Code

interface Props {
	foo?: boolean;
}

class Foo<P extends Props = Props> {
	props: Readonly<P> = {} as P;

	myFunc() {
		const { foo = false } = this.props;
                
                // errors because the type of `foo` is narrowed to `false` and cannot be 
                // compared to `true`
		if (foo === true) {}
	}
}

Removing Readonly from the type of props "fixes" the error, so it seems like it is related to mapped types.

Expected behavior:

foo is narrowed to the defaulted value false but should keep the type boolean.

Actual behavior:

foo should default to false but keep the base type of boolean.

Playground Link (use strictNullCheck): https://www.typescriptlang.org/play/index.html#src=interface%20Props%20%7B%0D%0A%09foo%3F%3A%20boolean%3B%0D%0A%7D%0D%0A%0D%0Aclass%20Foo%3CP%20extends%20Props%20%3D%20Props%3E%20%7B%0D%0A%20%20%20%20props%3A%20Readonly%3CP%3E%20%3D%20%7B%7D%20as%20P%3B%0D%0A%0D%0A%09myFunc()%20%7B%0D%0A%09%09const%20%7B%20foo%20%3D%20false%20%7D%20%3D%20this.props%3B%0D%0A%09%09if%20(foo%20%3D%3D%3D%20true)%20%7B%7D%0D%0A%09%7D%0D%0A%7D

Related Issues:

#17005

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions