-2

https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#unions-with-common-fields

keyof (A|B) = (keyof A) & (keyof B)

SO as in example

interface Bird {
  fly(): void;
  layEggs(): void;
}
   
interface Fish {
  swim(): void;
  layEggs(): void;
}
  
declare function getSmallPet(): Fish | Bird;
  
let pet = getSmallPet();
pet.layEggs();

1 Example -GOOD

1 Example -GOOD

2 Example -GOOD

2 Example -GOOD

interface Birds {
    flys: boolean;
    layEggs: string;
}

interface Fish {
    swim: number;
    layEggs: string;
}

declare let k: Fish & Birds;

k = { flys:true, layEggs:"", swim:3}

3 Example -GOOD 3 Example -GOOD

4 Example -BROKEN 4 Example -BROKEN

All is prefect till 4th Example... It's so confusing it should be k = { layEggs: ""} ????

PROOF:

interface Bird {
    fly: number;
    layEggs: string;
}

type g1 = keyof Bird

interface Fish {
    swim: boolean;
    layEggs: string;
}

type g2 = keyof Fish


type PetALL= keyof( Bird & Fish )
// let all1: EmployeeAll = "fly" 
// let all2: EmployeeAll = "email" 
// let all3: EmployeeAll = "layEggs" 

type Pet = keyof( Bird | Fish )
// let only: Employee = "layEggs"

EDITOR USED https://www.typescriptlang.org/play (default settings)

CLARIFICATION OF THE QUESTION

Question is why allowed type in next case:


interface Birds {
    flys: boolean,
    layEggs: string
}

interface Fish {
    swim: number,
    layEggs: string,
}

declare let k: Fish | Birds;

k = {}

isn't just k = { layEggs: ""} ??

As you can see in 4 Example -BROKEN

AND WHY THIS THIS SINTAX WORKS

5 Example -FIX

5 Example -FIX

  • 1
    I suggest you to limit your question to the only example that you think is actually broken. Currently it makes no sense. Esp naming `type Employee = keyof( Bird | Fish )` – Yury Tarabanko Nov 09 '20 at 15:28
  • I'm having a very hard time understanding what your problem is. `(keyof A | B)` = `(keyof A & keyof B)` doesn't mean that an object of type `A | B` can only *have* properties common to `A` and `B`; it means that given an object of type `A | B`, the only keys you can be *certain* of are those keys. Any object of type `A | B` must have all the (required) properties of *either* `A` or `B`. That is, an `A` is a valid `A | B`, and a `B` is a valid `A | B`. – jcalz Nov 09 '20 at 15:29
  • `k = { flys:true, layEggs:"", swim:3}` is assignable to both `Birds` and `Fish`. So, it's correct. You can pass it to `function catch(x: Fish)` or `function watch(x: Birds)`. If it *only* had `laysEggs` then you couldn't pass it to neither `catch` nor `watch`. – VLAZ Nov 09 '20 at 15:29
  • Ah yes, a language used by literally millions is broken :P I suggest cutting your question down to the core issue you're having. – Dane Brouwer Nov 09 '20 at 15:29
  • 1
    @DaneBrouwer I mean, it *is*. There are fundamental problem with the TS system that make it unsound, like [bivariant function declarations](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant). This isn't one of these but there are problems with TS, and there would be - [regardless of how many people are using it](https://www.logicallyfallacious.com/logicalfallacies/Appeal-to-Popularity). There is no denying that. – VLAZ Nov 09 '20 at 15:33
  • @VLAZ I was being facetious, but those are valuable resources, thank you - I just thought it was a humorous claim. – Dane Brouwer Nov 09 '20 at 15:40
  • @VLAZ many places where TS is unsound are intentional design choices where developer productivity and idiomatic JS are valued over soundness. It's fine to disagree with or be frustrated with some of these decisions, and I think it would be amazing to have a fully sound version of the language (if only so that people can see how annoying it would be to actually use), but to equate that to the language being "broken" isn't really fair. I admit I started off feeling this way too, but at this point I consider "broken" to mean "unintentional behavior" and not "pragmatic tradeoff". – jcalz Nov 09 '20 at 15:42
  • In any case, I hope we can all agree to improve our example code by using meaningful names like `Employee` instead of nonsense like `Foo` and `Bar`. – jcalz Nov 09 '20 at 15:48
  • 1
    @jcalz "broken" is a colloquial term for "unsound". It seems like what OP was referring to here, so I was going off that. It wasn't a value judgement but a statement of a fact. I'm not really opposed to this behaviour. It *does* mean that sometimes the compiler - rejects correct code or accepts incorrect code. Still, the tremendous amount of convenience it provides all around more than offsets these rare occasions. – VLAZ Nov 09 '20 at 15:48
  • I've updated the question, I'm junior in TypeScript.. I found one answer given in "5 Example -FIX" in essence cannot use `k = {...}` but must use `k.layEggs ...` which is soo confusing still... @vlaz @yury-tarabanko, @jcalz, @dane-brouwer – Alexander Yelich Nov 09 '20 at 16:10
  • @jcalz please look at https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#improved-keyof-with-intersection-types for more information about **keyof (A|B) = (keyof A) & (keyof B)**. – Alexander Yelich Nov 09 '20 at 16:24
  • @AlexanderYelich I'm sorry, but the question is still quite disorganized and messy enough that it's hard to understand what your actual problem is. Please consider following the guidelines for [ask] and specifically what constitutes a [mcve]. I strongly suggest you remove most of the images and code here and put one small code sample that demonstrates exactly what your problem is. Again, `keyof (A | B) = keyof A & keyof B` *does not mean* that an object of type `A | B` has *only* those properties. I'd be more than happy to write out an answer, but only to a well-posed question. – jcalz Nov 09 '20 at 17:06
  • Guys I posted an answer please if agree with it remove negative votes, it was quite hard to find cause of problem and formulate question in RIGHT way, and I think it can we useful to other junior developers.. Thanks @jcalz – Alexander Yelich Nov 10 '20 at 01:59
  • I'm afraid that neither your question nor your answer is clear enough for me to say much. As far as I can see, nothing that you have highlighted or talked about is "broken", and I truly do not understand what problem you are worried about or trying to solve. There are specific guidelines for [ask] and [answer]; it does not seem that you have been able to follow them. For what it's worth, I did not downvote you, so you do not need to try to convince me to remove my downvote. Good luck to you! – jcalz Nov 10 '20 at 16:41

1 Answers1

0

It seems when i'm using a union, the rule about object literal does not work, and when use Object type TS started to complain as expected.

What I can say is, that's how TS was made, there are other hundreds of bugs and unexpected behaviors in TS that i need to learn, but still there is probably nothing that is better overall.

1 USING TYPES

```
type Birds = {
    flys: boolean;
    layEggs: string;
}

type Fish = {
    swim: number;
    layEggs: string;
}

type UnionType = Fish | Birds

//Ok to use Object Literal with Object Type 
let k1: Birds= {flys:true,layEggs:"yes"}

//Ok to use Object Literal with Object Type 
let k2: Fish= {swim:100,layEggs:"of course"}

//BROKEN DO NOT Object Literal with Union Type
let k3: UnionType={flys:true, layEggs:"yeah",swim:22}

//Handle union type with Function Overloading:
declare let bla: UnionType;
bla.layEggs = "yeah"
```

2 USING INTERFACE

```
interface Birds {
    flys: boolean;
    layEggs: string;
}

interface Fish {
    swim: number;
    layEggs: string;
}

type UnionType = Fish | Birds

//Ok to use Object Literal with Object Type 
let k1: Birds= {flys:true,layEggs:"yes"}

//Ok to use Object Literal with Object Type 
let k2: Fish= {swim:100,layEggs:"of course"}

//BROKEN DO NOT Object Literal with Union Type
let k3: UnionType={flys:true, layEggs:"yeah",swim:22}

//Handle union type with function overloading:
declare let bla: UnionType;
bla.layEggs = "yeah"
```

It was hard to formulate a question, thank you @vlaz, @yury-tarabanko, @jcalz, @dane-brouwer

  1. typescript type is lost on an object literal assign using a union type
  2. TypeScript: Discriminated Unions with optional values
  3. Many more resources online...

This is a TS feature at the moment. I will not use Object Literals in TS but go with Function Overloading pattern.