2

I would expect an error from the following code, but for typescript is perfectly ok, can you tell me why?

export interface Type1 {
    command: number;
}

export interface Type2 {
    children: string;
}

export type UnionType = Type1 | Type2;

export const unionType: UnionType = {
    command: 34234,
    children: [{ foo: 'qwerty' }, { asdf: 'zxcv' }],
};

Here is the link.

user2010955
  • 3,871
  • 7
  • 34
  • 53

2 Answers2

1

Typescript currently does not have a concept of exact types (there is exception for object literals, I'll explain in the end). In other words, every object of some interface can have extra properties (which don't exist in the interface).

Hence this object:

{
    command: 34234,
    children: [{ foo: 'qwerty' }, { asdf: 'zxcv' }],
}

satisfies Type1 interface because it has all of its properties (command) property but it also satisfies Type2 interface because it has all of its properties (children) as well.

A note on object literals: typescript does implement a concept of exact type only for object literals:

export const unionType: Type1 = {
    command: 34234,
    children: [{ foo: 'qwerty' }, { asdf: 'zxcv' }], // oops, not allowed here
};

export const unionType: Type2 = {
    command: 34234, // oops, not allowed here
    children: [{ foo: 'qwerty' }, { asdf: 'zxcv' }],
};

Above is the code which demonstrates object literals, and below is the code without them:

const someVar = {
    command: 34234,
    children: [{ foo: 'qwerty' }, { asdf: 'zxcv' }]
};

const: Type1 = someVar // ok, because assigning not an object literal but a variable
Nurbol Alpysbayev
  • 19,522
  • 3
  • 54
  • 89
  • 1
    OK, but I used an object literal to assign a value to my unionType const, typescript should raise an error in my opinion. Notice that I'm assigning an array to the children property, even if the type of children should be a string!, and it's fine for typescript! – user2010955 Dec 21 '18 at 08:19
  • @user2010955 Well, it seems when you're using a union, the rule about object literal does not work. I replaced `unionType: UnionType` with `unionType: Type1` and TS started to complain as expected. What I would say is, that's how TS was made, there are other hundreds of bugs and unexpected behaviors in TS that your will discover as you learn it, but still there is probably nothing that is better overall. – Nurbol Alpysbayev Dec 21 '18 at 08:24
0

The construct export type UnionType = Type1 | Type2; means that instances of UnionType are instances of Type1 or Type2. This does not necessarilly mean they cannot be instances of both.

Dan Homola
  • 3,819
  • 1
  • 28
  • 43