wojky
wojky

Reputation: 78

Why TS throwing an error when using conditional types?

I am trying to use conditional typing with Typescript but tsc throwing an error.

interface Player {
    name: string;
    position: string;
    leg: string;
}

interface Coach {
    name: string;
    licence: string;
}

type Role = 'coach' | 'player';


function getPerson<T extends Role>(role: T): T extends 'coach' ? Coach : Player {
    if (role === 'coach') {
        return {} as Coach; // Type 'Coach' is not assignable to type 'T extends "coach" ? Coach : Player'
    } else {
        return {} as Player; // Type 'Player' is not assignable to type 'T extends "coach" ? Coach : Player'
    }
}

const person = getPerson('coach'); // const person: Coach
const person2 = getPerson('player'); // const person2: Player

Could someone explain to me why it does not work? And how I should refactor my code to get proper types?

Upvotes: 1

Views: 59

Answers (1)

Conditional types does not work in this way in TS.

Let's take a look on next example:


interface Coach {
    name: string;
    licence: string;
}

type Role = 'coach' | 'player';


function getPerson<T extends string>(role: Role): T extends 'coach' ? Coach : Player {
    if (role === 'coach') {
        const x = role;
        return {} as T extends 'coach' ? Coach : Player; // no error
    } else {
        return {} as T extends 'coach' ? Coach : Player; // no error
    }
}

const person = getPerson('coach'); // const person: Coach
const person2 = getPerson('player'); // const person2: Player

Above example does not helpful at all, but it show you how TS treats your Return type.

You should use overloading

interface Player {
    name: string;
    position: string;
    leg: string;
}

interface Coach {
    name: string;
    licence: string;
}

type Role = 'coach' | 'player';

function getPerson<T extends 'player'>(role: T): Player
function getPerson<T extends 'coach'>(role: T): Coach
function getPerson<T extends Role>(role: T) {
    if (role === 'coach') {
        const x = role;
        return {} as Coach;
    } else {
        return {} as Player
    }
}

const person = getPerson('coach'); // const person: Coach
const person2 = getPerson('player'); // const person2: Player

Upvotes: 1

Related Questions