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

Proposal: Infer return type in conditional with const values #38026

Closed
DrTtnk opened this issue Apr 17, 2020 · 2 comments
Closed

Proposal: Infer return type in conditional with const values #38026

DrTtnk opened this issue Apr 17, 2020 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@DrTtnk
Copy link

DrTtnk commented Apr 17, 2020

Search Terms

Build time conditional flow path type inference

Suggestion

Push the static flow analysis a notch and have inferred return types for conditional expressions and statements

Use Cases

At the moment the only way to have a return type inferred from a conditional flow is to recreate the same conditional structure with a conditional type in a separate type and then cast the result when needed, this may lead to inconsistencies in the types given that the cast is forced and it bypasses some of the static TS analysis

Examples

// Extremely simple example
const res = typeof 10 == "number" ? 10 : "10"; // inferred 10|"10" but actual can only be 10

// More convoluted example
const makeObject = (num: number) => ({ number: num });

const getOption = <T extends 1|2|3|object>(input: T) => {
    if(typeof input === "object") return null;
    switch (input) {
        case 1: return "ONE";
        case 2: return makeObject(2);
        case 3: return 3;
    }
    throw new Error();
}

type InferReturnType<T extends 1 | 2 | 3 | object>
    = T extends 1 ? "ONE"
    : T extends 2 ? ReturnType<typeof makeObject>
    : T extends 3 ? 3
    : T extends object ? null
    : never

const getOptionInfer = <T extends 1|2|3|object>(input: T) : InferReturnType<T> => {
    if(typeof input === "object") return null as InferReturnType<T>;
    switch (input) {
        case 1: return "ONE"         as InferReturnType<T>;
        case 2: return makeObject(2) as InferReturnType<T>;
        case 3: return 3             as InferReturnType<T>;
    }
    throw new Error();
}

const res = getOption(2); // type of res is:  3 | "ONE" | {number: number;} | null
const resInfer = getOptionInfer(2); // type of resInfer is {number: number;}

let genericInput: 1 | 3 = /* coming from somewhere else */;
const res2 = getOption(2); // type of res2 is:  3 | "ONE" | {number: number;} | null
const resInfer2 = getOptionInfer(genericInput); // type of resInfer2 is "ONE" | {number: number;}

// Expected: to have res and res2 with the same type of resInfer and resInfer2 respectively 

Checklist

My suggestion meets these guidelines:

  • [v] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [v] This wouldn't change the runtime behavior of existing JavaScript code
  • [v] This could be implemented without emitting different JS based on the types of the expressions
  • [v] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [v] This feature would agree with the rest of TypeScript's Design Goals.
@DrTtnk DrTtnk changed the title Infer return type in conditional with const values Proposal: Infer return type in conditional with const values Apr 17, 2020
@RyanCavanaugh
Copy link
Member

See #33912

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Apr 17, 2020
@typescript-bot
Copy link
Collaborator

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants