Skip to content

Cannot return unique symbol #32242

Closed
Closed

Description

@AnyhowStep

TypeScript Version: 3.5.1

Search Terms:

function, return type, unique symbol

Code

const a = Symbol();
const b = Symbol();

function identity<T> (t : T) : T {
  return t;
}

/**
 * Mouseover `identity(a)`,
 * Tooltip shows,
 * 
 * ```
 * function identity<typeof a>(t: typeof a): typeof a
 * ```
 */
/**
 * Expected : typeof a
 * 
 * Actual   : symbol
 */
const actual = identity(a);
/**
 * Error
 * 
 * Type 'symbol' is not assignable to type 'unique symbol'.
 */
const expectA : typeof a = actual;

/////////////////////////////////////////////////

function giveTypeOfA () : typeof a {
  return a;
}

/**
 * Expected : typeof a
 * 
 * Actual   : symbol
 */
const actual2 = giveTypeOfA();
/**
 * Error
 * 
 * Type 'symbol' is not assignable to type 'unique symbol'.
 */
const expectA2 : typeof a = actual2;

Expected behavior:

actual and actual2 should be typeof a

Actual behavior:

actual and actual2 are symbol

Playground Link: Playground

Related Issues:

The very last comment of #24506 asks a question about intended behaviour but it goes unanswered.

Activity

  1. AnyhowStep commented on Jul 3, 2019

    @AnyhowStep
    ContributorAuthor

    The current workaround is,

    const a = Symbol();
    
    function giveTypeOfA () : { workaround : typeof a } {
      return { workaround : a };
    }
    
    /**
     * Expected : { workaround : typeof a }
     * 
     * Actual   : { workaround : typeof a }
     */
    const actual2 = giveTypeOfA();
    /**
     * Assignment OK!
     */
    const expectA2 : typeof a = actual2.workaround;

    Playground


    Returning a tuple with one element also works,

    const a = Symbol();
    
    function giveTypeOfA () : [typeof a] {
      return [a];
    }
    
    /**
     * Expected : [typeof a]
     * 
     * Actual   : [typeof a]
     */
    const actual2 = giveTypeOfA();
    /**
     * Assignment OK!
     */
    const expectA2 : typeof a = actual2[0];

    Playground


    However, this does not work,

    const a = Symbol();
    
    function giveTypeOfA () : [typeof a] {
      return [a];
    }
    
    /**
     * Expected : typeof a
     * 
     * Actual   : symbol
     */
    const actual2 = giveTypeOfA()[0];
    /**
     * Assignment Not allowed
     */
    const expectA2 : typeof a = actual2;

    Playground


    So, it seems like I have to "box" the unique symbol until I actually need it.

  2. RyanCavanaugh commented on Jul 26, 2019

    @RyanCavanaugh
    Member

    The uniqueness of a symbol goes away through widening.

  3. AnyhowStep commented on Jul 26, 2019

    @AnyhowStep
    ContributorAuthor

    Why would it widen for foo () : typeof a but not foo() : [typeof a]?

  4. typescript-bot commented on Jul 28, 2019

    @typescript-bot
    Contributor

    This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  5. artalar commented on Aug 15, 2019

    @artalar

    Sorry, but Im really "Cannot return unique symbol":

    function getSymbol() {
      const uniqueSymbol: unique symbol = Symbol()
      return uniqueSymbol
    }
    
    var a = getSymbol()
    // no error??
    var b: typeof a = getSymbol()
  6. coreh commented on Feb 20, 2020

    @coreh

    I know this ticket is closed and marked as "Working as Intended", but IMO the current behavior makes it a bit harder than necessary to create custom Unit types that are guaranteed to not clash with string/number literals and "survive" being passed through generic function calls without getting widened to just symbol.

    I'm using AnyhowStep's tuple "boxing" workaround for now (thanks for pointing that out!) but I would like to ask if y'all could reconsider, and change the unique symbol widening behavior to be the same as the one used for string/number literals.

    I'm not sure if doing so could have additional implications to the type system... (Maybe something breaks because of it?) In that case, perhaps we could maybe opt out of the widening behavior via the unique type modifier?

    function identity<T> (t : T) : unique T {
      return t;
    }
  7. RyanCavanaugh commented on Feb 20, 2020

    @RyanCavanaugh
    Member

    It's confusing to allow this because it's unclear if : unique T means "Returns the same unique symbol each time" or "Returns a new unique symbol each time".

  8. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions