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

Support inferred string-modified union types #17512

Closed
RonPenton opened this issue Jul 29, 2017 · 4 comments
Closed

Support inferred string-modified union types #17512

RonPenton opened this issue Jul 29, 2017 · 4 comments
Labels
Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined Suggestion An idea for TypeScript Too Complex An issue which adding support for may be too complex for the value it adds

Comments

@RonPenton
Copy link

I ran into an interesting situation that I wanted to run by the community to see if there's a way to add a new feature into TypeScript to support. I'll grant that it's an edge-case, but it seems like something that could be kind of neat.

Here's the code:

Code

// From Library 1
type status = "success" | "error" | "warning" | "info";

// From Library 2
type statusColor = "success" | "success-dark" | "error" | "error-dark" | "warning" | "warning-dark" | "info" | "info-dark";

// My library
function getColorFromStatus(status: status): statusColor {

    // ideal case: doesn't work:
    return status + "-dark";    // Error TS2322	Type 'string' is not assignable to type 'statusColor'

    // compromise: compiles but not type-safe. Changes to "status" type won't be caught.
    return status + "-dark" as statusColor;

    // safe case: works but extra code + runtime penalty:
    switch (status) {
        case "success": return "success-dark";
        case "error": return "error-dark";
        case "warning": return "warning-dark";
        case "info": return "info-dark";
    }
}

I think it would be neat if the expression:

status + "-dark"

could be automatically inferred to be of type:

"success-dark" | "error-dark" | "warning-dark" | "info-dark";

It's probably a lot more complex than it seems. And there's probably a heck of a lot of issues dealing with what happens with other string operations or if a runtime function like .toUpperCase() is called on the string, and what happens if any item in the union isn't a string, etc, etc. But still.

Any thoughts?

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Jul 30, 2017

I believe this is roughly the same idea as proposed in #16746 (comment)

I think it is a great idea, but might be highly complex.

I would say it is not an edge case because, if generalized somewhat, it could allow for something like (syntax is just something I made up)

interface Outer {
  details: Inner
}
interface Inner {
  name: string;
}

type Delimiter = ".";

type DeepKey<T, OKey extends keyof T, IKey extends keyof T[OKey]> = OKey + Delimiter + IKey;

function pick<T, OKey extends keyof T, IKey extends keyof T[OKey]>(o: T, key: DeepKey<T, OKey, IKey>) {
  const [outer, inner] = key.split(".");
  return o[outer][inner];
}

declare const o: Outer;

const name = pick(o, "details" + "." + "name");

@gcnew
Copy link
Contributor

gcnew commented Jul 30, 2017

Another related issue #12940.

@DanielRosenwasser
Copy link
Member

As well as #12754

@DanielRosenwasser DanielRosenwasser added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Aug 2, 2017
@DanielRosenwasser DanielRosenwasser added the Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined label Sep 18, 2017
@RyanCavanaugh RyanCavanaugh added Too Complex An issue which adding support for may be too complex for the value it adds and removed In Discussion Not yet reached consensus labels Oct 10, 2017
@RyanCavanaugh
Copy link
Member

We'd either have to invent a completely new kind of type (a deferred-expansion union), which would be a ton of work, or risk people accidently creating combinatorially explosive literal types. This doesn't seem to come up often enough to warrant either scenario.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined Suggestion An idea for TypeScript Too Complex An issue which adding support for may be too complex for the value it adds
Projects
None yet
Development

No branches or pull requests

5 participants