Why flow type casting not working for string literal as expected

Viewed 46

For the below example why type casting is not working in Flowtypes? What should be an ideal way of doing it?

type typeA = {
  name: 'ben' | 'ken',
};
type typeB = {
  name: string,
};
const objA: typeA = { name: 'ben' };
const objB: typeB = objA;

It gives error

Cannot assign `objA` to `objB` because in property `name`: Either  string [1] is incompatible with  string literal `ben` [2]. Or  string [1] is incompatible with  string literal `ken` [3].

However, for typescript, it is fine.

1 Answers

This is actually a TypeScript flaw IMO and Flow does it right. Let's see why:

type A = {
  name: 'ben' | 'ken';
}

type B = {
  name: string;
}

const a: A = { name: 'ben' }
const b: B = a;

b.name = 'jen';

console.log({ a });
// this logs { a: { name: 'jen' } } <- see how a.name has an invalid value!

In JS when you write b = a means that b is an "alias" for a and in fact they're the same object.

So if you make changes to b then those changes also reflect on a, so if you're permitted to "lean" the name type definition from a given list of strings to a general string, you can go and change a.name with "illegal" or better unwanted values!

Related