Skip to content

No way to return an unique symbol from a derived class #31242

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

Closed
dko-slapdash opened this issue May 3, 2019 · 2 comments
Closed

No way to return an unique symbol from a derived class #31242

dko-slapdash opened this issue May 3, 2019 · 2 comments
Labels
Bug A bug in TypeScript

Comments

@dko-slapdash
Copy link

TypeScript Version:
3.4.0-dev.201xxxxx

Search Terms:
Type 'symbol' is not assignable to type 'unique symbol'

Code

const SPECIAL: unique symbol = Symbol("sym");

abstract class Base {
  abstract fff(): typeof SPECIAL | number;
}

class Derive1 extends Base {
  fff() {
    return 10;
  }
}

class Derive2 extends Base {
  fff() {
    // Error: Type 'symbol' is not assignable to type 'number | unique symbol'
    return SPECIAL;
  }
}

Expected behavior:
It works.

Actual behavior:
Type 'symbol' is not assignable to type 'number | unique symbol'

Playground Link:
playground link

Related Issues:
#24506 - but it's closed due to houcekeeping, and the code there is more complicated (probably a different usecase?),

Motivation:
I want to express the notion of some "special" values returned from a method. Like in most of the cases the method returns some value, but sometimes it returns SPECIAL constant (there can be multiple) to signal about something. Looks like there is no way to do it currently in TS using symbols (if SPECIAL is a constant string, it's doable, but still I need to cast it to as const every time I return it).

@weswigham weswigham added the Bug A bug in TypeScript label May 3, 2019
@weswigham
Copy link
Member

This is sorta a bug, sorta a design limitation. Methods don't actually inherit their unannotated signature from their base type right now, so fff in Derive2 is actually a method with no context - so the SPECIAL unique symbol type is widened to symbol to make the signature per our literal type rules. However this is then compared against the base which expects the literal unique symbol. If the literal context were projected from the base, this would not happen, so that's why this is maybe a bug, since that's expected to many people, however currently contextual types not applying to subclass methods is the designed behavior, which is why this could also be read as "by design".

In any case, as a workaround, just annotate the return type on fff explicitly (: typeof SPECIAL) and it should work out.

@dko-slapdash
Copy link
Author

dko-slapdash commented May 6, 2019

Thanks Wesley! So as a work-around conclusion: this works -

const SPECIAL: unique symbol = Symbol("sym");

abstract class Base {
  abstract fff(): typeof SPECIAL | number;
}

class Derive2 extends Base {
  fff(): typeof SPECIAL { // <-- works
    return SPECIAL;
  }
}

and looks like it's the only way, because even using as doesn't help:

class Derive2 extends Base {
  fff() {
    return SPECIAL as typeof SPECIAL; // <-- doesn't work
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants