Skip to content

Allow to pass "unique symbol" as a type parameter (e.g. Opaque<string, unique symbol>). #55691

@olalonde

Description

@olalonde

✅ Viability Checklist

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ Suggestion

I have been trying to write a type helper to facilitate the creation of nominal types (aka branded/tagged/opaque types), but I'm a bit stuck by the fact I can't pass unique symbol as a type parameter.

The following doesn't work:

type Opaque<T, TBrand> = T & {
  readonly __brand: TBrand;
}

type UserId = Opaque<string, unique symbol>;
// error: 'unique symbol' types are not allowed here.
type GroupId = Opaque<string, unique symbol>;
// error: 'unique symbol' types are not allowed here.

function printUserId(userId: UserId) {
  console.log(userId)
}

printUserId("abc" as UserId);
printUserId("def" as GroupId);

And if I just get rid of the TBrand parameter, it considers both UserId and GroupId to be compatible.

type Opaque<T, TBrand> = T & {
  readonly __brand: TBrand;
}

type UserId = Opaque<string>;
type GroupId = Opaque<string>;
// error: 'unique symbol' types are not allowed here.

function printUserId(userId: UserId) {
  console.log(userId)
}

printUserId("abc" as UserId);
printUserId("def" as GroupId); // works ... :(

📃 Motivating Example

See suggestion.

💻 Use Cases

  1. What do you want to use this for?

Creating nominal types

  1. What shortcomings exist with current approaches?

Have to memorize how to do it, more code to type.

  1. What workarounds are you using in the meantime?

To do the nominal type without using a type helper.

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