0

I'm running into an issue where I have an interface that describes some dynamic data where the values of each property can be one of many types, but I can't assign a variable that is one of those types.

Here's my interface:

interface MyDict {
  [key: string]: string | number;
}

Here's some data of that type:

const data: MyDict = {
  hello: 'world',
  test: 123,
};

However when I try to pull values from data and assign it to a variable typed string or number, it fails.

const example: string = data.hello;
/* ->
  Type 'string | number' is not assignable to type 'string'.
    Type 'number' is not assignable to type 'string'. ts(2322)
*/

data.hello is allowed to be either a string or a number, in this case it is a string, but when I try to assign it to variable example that can only be a string it unexpectedly fails. I'm under the impression that I can think of | as "or", but perhaps I'm wrong. Is there something I'm missing about union types? I'd really appreciate some pointers! :)

EDIT: I was able to get it to work by casting data.hello to a string, like so:

const example: string = data.hello as string;

Is this the right solution here, or is there a better practice for this use case?

2
  • Yes, you've stumbled upon the right solution. You know that the variable is a string, but the compiler only sees that its string | number. Compilers aren't magic, they're just very clever at certain things, and this level of flow analysis is not one of them. Commented Jul 11, 2019 at 21:41
  • Gotcha! Thanks for the info :) Commented Jul 11, 2019 at 21:58

2 Answers 2

2

The correct way to deal with this is to type check within your code. For instance:

if (typeof data.hello === 'string') {
  const whatever: string = data.hello;
}

The compiler views data.hello as two possible types, so if you want to declare a variable with a single type, you have to exclude the other possibility first.

Sign up to request clarification or add additional context in comments.

2 Comments

Gotcha! Thanks for the info. How does this differ from casting the variable (whatever in your example)?
Casting would make compiler warnings go away, but it doesn't actually ensure the correct type at the time of execution. In other words, it doesn't prevent errors when trying to run unsupported operations against the variable.
0

I think this will be better:

const example: keyof MyDict = data.test;

1 Comment

I don't think this will fit my use-case, as the variable example must strictly be a string.

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.