'Is there way to narrow function parameters witch have same union types signature to exactly same subtypes by generic type
// this is what i what for function parameters type
type Combinable = string | number;
function isString(param: unknown): param is string {
return typeof param === "string";
}
// i expect function parameters a and b to have exactly the same subtype of Combinable like both are string or number(e.g. a: string and b: number is not i wanted),and finally the return type of this function must be the same subtype of a and b
function add<T extends Combinable>(a: T, b: T): T {
if (isString(a)) {
//and i get this following error
//1st question: how can i fix this
/* Type 'string' is not assignable to type 'T'.
'string' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Combinable'.ts(2322) */
// my 2nd question is here: why TS can not infer b must be type "string" since i narrow type of a to "string"?
//type ta = typeof a // answer is string & T === string
//type tb = typeof b // answer is T why T not string?
return a + b;
} else {
return (a as number) + (b as number); //same error
}
}
let a: Combinable = "123";
let b: Combinable = 123;
//3rd question here: i want to know that why TS can infer a and b must be the same subtype of Combinable here but it can not do this in the function body above?
add(a, b); //constraint a and b in same sub type is what i expected when function called
My Questions:
- How can i fix this
- Why TS can not infer b must be type "string" since i narrow type of a to "string"?
- Why TS can infer a and b must be the same subtype of Combinable when function called but it can not do this in the function body above?
Appreciate your comments and answers.
Solution 1:[1]
If it's just about making sure the typescript compiler does his job, you can achieve it like this:
type Combinable = string | number;
function add<T extends Combinable>(a: T, b: T): T {
return (a as number) + (b as number) as T;
}
let a: Combinable = "123";
let b: Combinable = 123;
const sumOfAB = add(a, b); // Argument of type 'number' is not assignable to parameter of type 'string'.(2345)
let c: Combinable = 123;
let d: Combinable = "123";
const sumOfCD = add(c, d); // Argument of type 'string' is not assignable to parameter of type 'number'.(2345)
let e: Combinable = 123;
let f: Combinable = 123;
const sumOfEF = add(e, f); // const sumOfEF: number
let g: Combinable = "123";
let h: Combinable = "123";
const sumOfGH = add(g, h); // const sumOfGH: string
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | W.S. |
