Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken narrowing of types intersecting with unique symbols #24846

Closed
leemhenson opened this issue Jun 10, 2018 · 3 comments
Closed

Broken narrowing of types intersecting with unique symbols #24846

leemhenson opened this issue Jun 10, 2018 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@leemhenson
Copy link

TypeScript Version: 3.0.0-dev.20180609 & 2.9.1

Search Terms:
Narrowing unique symbol union

Code

declare const phantom: unique symbol;
type Phantom = typeof phantom;
type PhantomString = string & Phantom;

const fn = (arg?: PhantomString) => arg;
const fn2 = (arg: Array<PhantomString | null>) => arg;

Expected behavior:

fn and fn2 should be reported as:

const fn: (arg?: PhantomString) => PhantomString | undefined;
const fn2: (arg: Array<PhantomString | null>) => Array<PhantomString | null>;

Actual behavior:

fn and fn2 are reported as:

const fn: (arg?: undefined) => undefined;
const fn2: (arg: null[]) => null[];

Playground Link:

https://www.typescriptlang.org/play/#src=declare%20const%20phantom%3A%20unique%20symbol%3B%0D%0Atype%20Phantom%20%3D%20typeof%20phantom%3B%0D%0Atype%20PhantomString%20%3D%20string%20%26%20Phantom%3B%0D%0A%0D%0Aconst%20fn%20%3D%20(arg%3F%3A%20PhantomString)%20%3D%3E%20arg%3B%0D%0A%0D%0Aconst%20fn2%20%3D%20(arg%3A%20Array%3CPhantomString%20%7C%20null%3E)%20%3D%3E%20arg%3B

Appears to be partially related to strictNullChecks

@jack-williams
Copy link
Collaborator

Related #23672 ?

@mhegazy
Copy link
Contributor

mhegazy commented Jun 11, 2018

The compiler reduces empty intersection types to never when used in a union. an empty intersection type is one whose constituents are all unit types. so 1 & 2 "a" & false or "s" & unique symbol.

so PhantomString | null is just null. see #18438 for more details.

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jun 11, 2018
@leemhenson
Copy link
Author

Ah ok, I see. Using type PhantomString = string & { "phantom-string": any }; seems to work. I can see there are a few issues suggesting true nominal typing support so I'll add my 👍 to those.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants