简体   繁体   中英

Could typescript narrow union type in generic type?

it's possible to compile code with this intent:

type Tick = Date | number;

type Unary<T, R> = (_: T) => R;

function formatter<T extends Tick>(tick: T): Unary<T, string> {
    if (tick instanceof Date) {
        return (date: Date) => date.toUTCString();
    }
    return (int: number) => int.toFixed();
}

playground link

My idea is that if T is Date , tick is Date and return type is Unary<Date, string> , but Typescript tries it to unify with Unary<T, string> . It is because T extends Tick is broader than just Tick union? If so, can I limit this generic?

Don't think you can narrow the type of a parameter that is of a generic type. Any type gard will still preserve the type parameter in there as the compiler assumes a type parameter can be any derived type, so it can't eliminate what it does not know for certain.

Also what you are trying to do is narrow all type parameter occurrences (ie the occurrence in the return type) based on the check on the parameter which is definitely not possible. Type guards work on the specific variable not on the type as a whole.

One option is to use a separate implementation signature:

type Tick = Date | number;

type Unary<T, R> = (_: T) => R;

function formatter<T extends Tick>(tick: T): Unary<T, string> 
function formatter(tick: Tick): Unary<Date, string> | Unary<number, string> {
    if (tick instanceof Date) {
        return (date: Date) => date.toUTCString();
    }
    return (int: number) => int.toFixed();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM