Reputation: 25
type SeveralTypes = type0 | type1 | type2;
function funTypes<T extends SeveralTypes>(info: T, callback: (obj: T extends type2 ? number : string) => void) {
if (isType0(info)) {
return callback("passAstring"); // TS Warn: Argument of type '"passAstring"' is not assignable to parameter of type 'T extends boolean ? number : string'
} else if (isType1(info)) {
return callback("passAstring"); // TS Warn: Argument of type '"passAstring"' is not assignable to parameter of type 'T extends boolean ? number : string'
} else {
return callback(1001); // TS Warn: Argument of type '1001' is not assignable to parameter of type 'T extends boolean ? number : string'
}
}
funTypes(1, (d) => { }); // Typeof d --> string
funTypes("str", (d) => { }); // Typeof d --> string
funTypes(false, (d) => { }); // Typeof d --> number
When I use this function the infer type of the parameter callback are correct. However TS indicates problems when assigning parameters. Is there another way to type the callback parameters?
Upvotes: 1
Views: 140
Reputation: 250036
There are several issues here. The major one being that narrowing one variable (info
in this case) never has any impact on the type of another variable (callback
) in this case. There is also the issue that generally conditional types that still contain unresolved type parameters are generally hard for the compiler to reason about, so since T
is not known, and your function takes an argument dependent on T
, typescript will do the safe thing and not let you use as a parameter either number
or string
The usual way to get around this is to use type assertions, or my preferred approach, to use a generic public signature and a more permissive implementation signature (just be aware it is up to you to ensure the logic in your conditional type is replicated in the implementation, there is no help from the compiler here)
type SeveralTypes = type0 | type1 | type2;
function funTypes<T extends SeveralTypes>(info: T, callback: (obj: T extends type2 ? number : string) => void): void
function funTypes(info: SeveralTypes, callback: (obj: number | string) => void) {
if (isType0(info)) {
return callback("passAstring");
} else if (isType1(info)) {
return callback("passAstring");
} else {
return callback(1001);
}
}
funTypes(1, (d) => { }); // Typeof d --> string
funTypes("str", (d) => { }); // Typeof d --> string
funTypes(false, (d) => { }); // Typeof d --> number
Upvotes: 1