Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript conditional types

Tags:

I have a case where i need to use conditional types in Typescript. I'm not 100% sure that it's possible to do this using my approach, but I believe there must be a way.

I have simplified my code in the example below.

type Friend = {
    phoneNr: number;
};

type Enemy = {
    howToAvoid: string[];
};

interface Names {
    edward: Friend;
    sam: Enemy;
}

const names: Names = {
    edward: {
        phoneNr: 1234,
    },
    sam: {
        howToAvoid: ["don't go there", "dont do that"],
    },
};

function select<T extends keyof typeof names>(arg: T): Friend | Enemy {
    return names[arg];
}

console.log(select("edward"));

In short, the function select() accepts only the 2 arguments (edwards and sam) which are the keys of names. names contains a list of people, who can either be an Enemy or a Friend. select() can either return an object of type Enemy or Friend. I know it's one of the two, but I don't know which one it is.

What I want, is to be able to know that select("edward") will always return an object of type Friend, and that select("sam") will always return an object of type Enemy. All that assuming that I know in advance who is a friend, and who is an enemy.

Can we do that?

To illustrate, (by mixing the TS and JS syntaxes) I want to do the following:

function select<T extends keyof typeof names>(arg: T): T==="edwards" ? Friend : Enemy {
    return names[arg];
}

Many thanks!

like image 367
h-Reser Avatar asked Mar 21 '19 17:03

h-Reser


1 Answers

You can look up the argument as a property in the type:

function select<T extends keyof typeof names>(arg: T): Names[T] {
like image 66
Ryan Cavanaugh Avatar answered Oct 20 '22 06:10

Ryan Cavanaugh