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

Opaque string types #6921

Closed
DeadMG opened this issue Feb 5, 2016 · 6 comments
Closed

Opaque string types #6921

DeadMG opened this issue Feb 5, 2016 · 6 comments
Labels
Duplicate An existing issue was already created Suggestion An idea for TypeScript

Comments

@DeadMG
Copy link

DeadMG commented Feb 5, 2016

I've got an opaque string type. We basically use this type for things that are strings under the hood, but shouldn't be interchanged with actual free text strings- for example GUIDs. We also use the nominal type checking hack with the private void property to nominally type check them.

We have a problem, though, which is that the compiler won't permit them as dictionary keys.

Can we permit a type annotation or something to say that the type is really a string or integer under the hood and should be permitted as a dictionary key?

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Feb 5, 2016
@RyanCavanaugh
Copy link
Member

Duplicate of #5599

@DeadMG
Copy link
Author

DeadMG commented Feb 5, 2016

The opaque type is not an intersection type, since we do not want to permit assigning a Guid to a string, which the intersection type does permit. And we also do not want to permit the vast majority of string members to be callable on a Guid.

@RyanCavanaugh RyanCavanaugh removed the Duplicate An existing issue was already created label Feb 5, 2016
@RyanCavanaugh
Copy link
Member

Maybe you can post some code?

@RyanCavanaugh RyanCavanaugh reopened this Feb 5, 2016
@DeadMG
Copy link
Author

DeadMG commented Feb 5, 2016

It currently looks like this:

// Construct Guids using Guid.fromString()
abstract class Guid {
    private nominal: void;

    // Expose method from actual runtime String class.
    abstract toString(): string;

    static fromString(value: string): Guid {
        return <any>value;
    }

    static toString(value: Guid): string {
        return <any>value;
    }

    static emptyGuid(): Guid {
        return Guid.fromString("00000000-0000-0000-0000-000000000000");
    }

    static isNullOrEmpty(value: Guid) {
        return _.str.isBlank(Guid.toString(value)) || value === Guid.emptyGuid();
    }
}

Guid.fromString is an evil method that we use for tests but shouldn't really. The return types from our web services specify Guids to match guid types on the server; they're actually serialized as strings. Our client really shouldn't be doing any interesting processing on Guids at all- just passing them around.

So basically, the nature of Guids as actually strings at runtime is completely hidden from the user, as both outgoing and incoming DTOs define them as Guids, and we want the strongest of checking between Guids and strings- they are completely not interchangable in any way.

But it would also improve the typing of our code if we could use them as dictionary keys, like we can on the server.

@mhegazy
Copy link
Contributor

mhegazy commented Feb 19, 2016

I would refer to this as "tagged" types. basically a sub type of string, that is only assignable from values of the same type, but otherwise behaves like a string. Tagged types are just a form of nominal typings. there is a long discussion about this in, #4895 and you can see how in the TS compiler code bases we use a similar approach in https://github.com/Microsoft/TypeScript/blob/master/src/compiler/types.ts#L8.
I think this issue is better handled by #202

@mhegazy mhegazy closed this as completed Feb 19, 2016
@mhegazy mhegazy added Suggestion An idea for TypeScript Duplicate An existing issue was already created labels Feb 19, 2016
@DeadMG
Copy link
Author

DeadMG commented Feb 19, 2016

Like I explained to the other guy, they're not the same as we do not permit assignments the other way either, or any members. In fact, in the type system, Guid and string are completely and utterly unrelated.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants