GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Can't evaluate equality of symbols made by Symbol.for · Issue #35909 · microsoft/TypeScript

Can't evaluate equality of symbols made by Symbol.for #35909

New issue
Copy link
New issue
Copy link
Open
#64451
Open
Can't evaluate equality of symbols made by Symbol.for#35909
#64451
Copy link
Labels
Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript

Description

@falsandtru
falsandtru (falsandtru)
opened on Dec 29, 2019
Issue body actions

This is also an obstacle of branded types and ghost types. I think resolving this problem is easy because these types are just a new literal type similar to string literal types.

TypeScript Version: 3.7.x-dev.20191228

Search Terms:

Code

const a = Symbol.for('');
const b = Symbol.for('');
const c: typeof b = Symbol.for(''); // error
a === b; // error

Expected behavior:
no error
Actual behavior:
Type 'typeof b' is not assignable to type 'typeof a'.
This condition will always return 'false' since the types 'typeof a' and 'typeof b' have no overlap.
Playground Link: https://www.typescriptlang.org/play/index.html?ts=3.8.0-dev.20191228&ssl=1&ssc=1&pln=4&pc=18#code/MYewdgzgLgBAhjAvDAygTwLYCMQBsB0AZiAE4AUA5BQJQDcAUKJLFkqpjgceVXY+NBjAAXDChoADgFMQhGK2TpseIqUo1aMAPRaYUkiVL0EiU-M069B0kA

Related Issues: #35200

Reacted by ExE Boss, Cobertos, Semesse, SancheZz, Michał Niedziółka, Stefan Thomas, Benjamin Laird, Sʜɪᴍᴜʀᴀ Yū, Clément Maisonhaute and lionel-rowe

Activity

  1. falsandtru commented on Dec 29, 2019

    @falsandtru
    falsandtru (falsandtru)
    on Dec 29, 2019
    ContributorAuthor
    More actions

    Example

    // npm package A@v1
    namespace A1 {
        // Structural hidden field across versions and packages.
        const tag = Symbol.for('TagName');
        export class A<T> {
            constructor(arg: T) { }
            [tag]: T;
        }
    }
    // npm package A@v2
    namespace A2 {
        // Structural hidden field across versions and packages.
        const tag = Symbol.for('TagName');
        export class A<T> {
            constructor(arg: T) { }
            [tag]: T;
        }
        export declare function f(a: A<'a'>): void;
    }
    // npm package B
    namespace B {
        A2.f(new A1.A('a')); // Should work.
    }
    // npm package A
    namespace A {
        // Structural hidden field across versions and packages.
        const tag = Symbol.for('TagName');
        export class A<T> {
            constructor(arg: T) { }
            [tag]: T;
        }
    }
    // npm package B
    namespace B {
        // Structural hidden field across versions and packages.
        const tag = Symbol.for('TagName');
        export class B<T> {
            constructor(arg: T) { }
            [tag]: T;
        }
    }
    // npm package C
    namespace C {
        declare function f(a: A.A<'a'>): void;
        f(new B.B('a')); // Should work.
    }
  2. Ryan Cavanaugh (RyanCavanaugh)
    added
    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this feature
    SuggestionAn idea for TypeScriptAn idea for TypeScript
    on Jan 14, 2020
  3. ExE-Boss commented on Feb 14, 2020

    @ExE-Boss
    ExE Boss (ExE-Boss)
    on Feb 14, 2020
    Contributor
    More actions

    Like we have unique symbol, we should probably support:

    const foo: global symbol "<name>";

    This would allow declaring Node’s built-in symbols as:

    declare module "util" {
    	namespace inspect {
    		// https://github.com/nodejs/node/issues/20821
    		const custom: global symbol "nodejs.util.inspect.custom";
    	}
    
    	namespace promisify {
    		// https://github.com/nodejs/node/issues/31647
    		const custom: global symbol "nodejs.util.promisify.custom";
    	}
    }
    Reacted by Kenta Moriuchi and Semesse
  4. typeofweb commented on Mar 17, 2020

    @typeofweb
    Michał Miszczyszyn (typeofweb)
    on Mar 17, 2020
    More actions

    It's a bug I just stumbled upon and it was really surprising.

  5. ExE-Boss commented on Mar 19, 2020

    @ExE-Boss
    ExE Boss (ExE-Boss)
    on Mar 19, 2020
    Contributor
    More actions

    It’s the intended behaviour for unique symbol types, which global symbols actually aren’t, but they’re currently using the same code path.

  6. typeofweb commented on Mar 19, 2020

    @typeofweb
    Michał Miszczyszyn (typeofweb)
    on Mar 19, 2020
    More actions

    Sounds like it's not expected, more like an unforeseen side effect of adding unique symbols.

  7. kurtharriger commented on Apr 14, 2020

    @kurtharriger
    Kurt Harriger (kurtharriger)
    on Apr 14, 2020
    More actions

    I was looking at code for library and noticed usage of Symbol and Symbol.for I was curious what the difference was and found this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for

    I then attempted to try it in typescript and erroneously get the error that the conditional will alwasy be false even when the value is actually true.

    https://www.typescriptlang.org/play/?ssl=3&ssc=25&pln=1&pc=1#code/MYewdgzgLgBARjAvDAygTwLZxAGwHQBmIATgBQDkcAhseQJQDcAUKJLHAExKqbb5FlKNes1YRcAUzw4QAc1LwkiZJxiMmQA

    image

  8. cowboyd commented on Jan 13, 2022

    @cowboyd
    Charles Lowell (cowboyd)
    on Jan 13, 2022
    More actions

    Is the problem that there is no concept of a "symbol literal" in TypeScript?

    It would be really nice to have a literal syntax for symbols which would type just like any other primitive literal like 'string', 5, or true.

    Syntax is arbitrary, but using@ as a placeholder.

    const something = @something; //=> Symbol.for("something")
    const somethingElse = @"something.else"; //=> Symbol.for("something.else")
    
    const object: { [something]: string } = { @something: 'hello' };

    Seems like this would ease a lot of pain in matching types that use well known symbols as keys. But even in the absence of a literal syntax, what would it take for TS to treat Symbol.for() expressions as literals?

    Reacted by Simon Chan and ExE Boss
  9. nicolo-ribaudo commented on Jan 13, 2022

    @nicolo-ribaudo
    Nicolò Ribaudo (nicolo-ribaudo)
    on Jan 13, 2022
    Contributor
    More actions

    Charles Lowell (@cowboyd) That would risk big conflicts with decorators, but a while ago I was thinking about the symbol "foo" syntax:

    declare function Symbol.for<T extends string>(name: T): symbol T;
    declare function Symbol.keyFor<T extends string>(sym: symbol T): T;
    declare function Symbol.keyFor(sym: symbol): string | undefined;
    
    let a = Symbol.for("foo"); // type is `symbol "foo"`
    let b: symbol "foo" = Symbol.for("bar"); // error
    let c = Symbol.for("baz" as string); // symbol string
    let d: symbol = Symbol.for("foo"); // ok, symbol T is a subtype of symbol
    let d: symbol "foo" = Symbol(); // error
    
    let descA: "foo" = Symbol.keyFor(a); // ok
    let descB: "bar" = Symbol.keyFor(a); // err, "foo" is not assignable to "bar"

    EDIT: I just noticed that this was already suggested at #35909 (comment) 😬

    Reacted by Simon Chan and Clément Maisonhaute
  10. cowboyd commented on Jan 14, 2022

    @cowboyd
    Charles Lowell (cowboyd)
    on Jan 14, 2022
    More actions

    Nicolò Ribaudo (@nicolo-ribaudo) you're definitely right, and the @ was just the first thing that popped into my head. And in fact, there isn't any need for a new literal syntax, just a new type that accurately represents the return value of Symbol.for().

    I like your suggestions. Also need to consider the difference between Symbol() and Symbol.for(). Maybe something like:

    let a = Symbol("foo") // type is `unique symbol "foo"`
    let b = Symbol.for("foo") // type is `symbol for "foo"`

    Anyhow, as you noted ExE Boss (@ExE-Boss) already suggested this.... wonder why this thread petered out? Is there something that we can do?

  11. pjeby commented on Jun 19, 2022

    @pjeby
    PJ Eby (pjeby)
    on Jun 19, 2022
    More actions

    Throwing in a use case here: I've got a library that exports a symbol for purposes of interop, that other code can declare methods with that symbol, without needing to depend on the library that defines the symbol. But then, in a project that uses both of those libraries, Typescript can't tell that module 2 implements the interface specified by module 1, even though it uses the same Symbol.for().

    As it stands, the only way to get this kind of interop is with strings, not symbols, as there's no "global symbol" or "symbol for" syntax in Typescript. Using typeof can't work here because that would force the common dependency, and a shared type definitions file, since merely equivalent types are not sufficient for "unique symbol" to match.

    Reacted by ExE Boss, Fosty Fost, SancheZz, Stefan Thomas, Benjamin Laird, Joshua Sosso (Deprecated) and Yonggang Luo
  12. Sʜɪᴍᴜʀᴀ Yū (yuhr)
    marked Indexed symbol types #60944 as a duplicate of this issue on Jan 11, 2025
  13. yuhr commented on Jan 11, 2025

    @yuhr
    Sʜɪᴍᴜʀᴀ Yū (yuhr)
    on Jan 11, 2025
    More actions

    Excerpting from #60944, as I believe it's worth mentioning here:

    1. What do you want to use this for?

    Making multiple versions of the same library compatible.

    Sometimes a library generates objects with a private property at a unique symbol key and use it as some kind of marker to statically or dynamically determine if an object is really generated or already processed with the library, while allowing users to define arbitrary properties on it as much as possible.

    But what if a user has to end up depending on multiple versions of the library somehow? To address this, the library should accept objects from other versions of the same library, so the library might want to start using non-unique symbols for the purpose. This does work at runtime but not at compile time due to the absence of indexed symbol types.

    Using a string key instead of a non-unique symbol key invades the string key space of such an object at runtime, and could conflict with an index signature at compile time.

    Reacted by ExE Boss and Grigorii Ivanov
  14. lygstate commented on Jun 4, 2026

    @lygstate
    Yonggang Luo (lygstate)
    on Jun 4, 2026
    More actions

    It's a bug, can it fixed? As Symbol.for("literal") basically act like "literal" with symbol attribute

  15. Yonggang Luo (lygstate)
    added 10 commits that reference this issue on Jun 5, 2026

    Use globalThis.lvgljsBridge to overcome issue:

    507e6f4

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    951bd1b

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    a297770

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    d34b581

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    c8ab205

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    c5fac6b

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    7ddee96

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    f8bbecd

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    74caa0b

    fix(react): use globalThis.lvgljsBridge for typed native bridge access

    2a78127
  16. michaelfig commented on Oct 19, 2026

    @michaelfig
    Michael FIG (michaelfig)
    on Oct 19, 2026
    More actions

    I'd encourage people following this issue to take a look at #64451. I'm addressing review comments on it if you'd like to make any, and I'm hoping that it will eventually be merged as a comprehensive solution for these problems.

    Reacted by snarbles2
  17. Richiban commented on Oct 27, 2026

    @Richiban
    Richard Gibson (Richiban)
    on Oct 27, 2026
    More actions

    I have also keenly felt the absence of this. In languages like Erlang (with atoms) and Ruby (with symbols) and now Python (with sentinels) we have the ability to pass / return arbitrary sentinel values that can be matched against.

    The problem is that Typescript doesn't have any representation of the type of Symbol.for('mySymbol'); it treats all symbols as unique symbols, which they are not.

    The best thing would be for Typescript to have a type symbol<"mySymbol"> or symbol "mySymbol" or similar, so you can use it in a function signature, say:

    function f(): symbol "mySymbol" {
        return Symbol.for("mySymbol")
    }
    Reacted by Charles Lowell
  18. cowboyd commented on Oct 28, 2026

    @cowboyd
    Charles Lowell (cowboyd)
    on Oct 28, 2026
    More actions

    Oh captain symbol, my captain symbol!

    (i.e. I concur)

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

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.