0

I have a function that returns multiple types (union type) but then I have another function later that uses the value returned from the first function but only accepts a single type. Right now typescript is giving me an error saying that there is a type mismatch because the first function could potentially return something that would not be acceptable for the second function, but in the way that I am calling it I know it will not have a conflict. How can I inform typescript that the return value of the first method will work in the second?

Example:

function returnNumberOrString (variable): string | number {
    if (variable === 'hello') return 'hello to you';
    if (variable === 123) return 456;
}

function onlyNumbers (number : number) {
    return number + 1;
}

let number = returnNumberOrString(123);

onlyNumbers(number); // This shows a warning because returnNumberOrString could possibly return a string

2 Answers 2

1

The accepted solution only hides the compiler error. You will still be able to call onlyNumbers with a string even if you use Type Assertion to tell the compiler it is a number. If you perform the check I've written below, you won't ever pass anything but a number to your onlyNumbers function. This is a safer operation if you're doing anything that requires strictly numbers (as your function name implies)

function returnNumberOrString (variable): string | number {
    if (variable === 'hello') return 'hello to you';
    if (variable === 123) return 456;
}

function onlyNumbers (number : number) {
    return number + 1;
}

// Can pass string or number, will only ever get a number in val
let val = typeof returnNumberOrString(123) === "number" ? 456 : -1; // I used -1, you can use any value to mean "error" though.

console.log(val); // 456
console.log(onlyNumbers(val)); // 457

let val2 = typeof returnNumberOrString("hello") === "number" ? 456 : -1; 

console.log(val2); // -1
console.log(onlyNumbers(val2)); // 0 
Sign up to request clarification or add additional context in comments.

Comments

0

This works for me:

let n = returnNumberOrString(123);

onlyNumbers(<number>n);

As James notes, this hides the compiler error, but doesn't prevent the wrong value from being passed in, so you need to be very confident that you can guarantee by some other means what's being passed in.

3 Comments

This hides the compiler error, but you can still call onlyNumbers with a string value. e.g. let val = returnNumberOrString("hello"); onlyNumbers(<number>val); // Prints "hello to you1"
@James Well yes, it's essentially an unsafe cast that he's asking for. The question is, "I know this is safe; the compiler can't or won't infer that it's safe; how do I hide the compiler error?" He may be wrong that it's safe; I can't say.
In my particular case it is safe but I do understand that if I was unsure of the returned variable that doing a type check is the better solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.