Typescript联合类型已损坏?(使用对象类型和对象文字时)

Typescript联合类型已损坏?(使用对象类型和对象文字时),typescript,union-types,Typescript,Union Types,例如 interface Bird { fly(): void; layEggs(): void; } interface Fish { swim(): void; layEggs(): void; } declare function getSmallPet(): Fish | Bird; let pet = getSmallPet(); pet.layEggs(); 1例-良好 interface Birds { flys: boolean;

例如

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

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

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

declare let k: Fish & Birds;

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

2例-良好

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

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

declare let k: Fish & Birds;

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

3例-良好

4个示例-损坏

在第四个例子之前一切都是完美的。。。太让人困惑了 应该是k={layEggs:“}

证明:

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"
使用的编辑器(默认设置)

澄清问题 问题是为什么在下一种情况下允许输入:


interface Birds {
    flys: boolean,
    layEggs: string
}

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

declare let k: Fish | Birds;

k = {}
不仅仅是k={layEggs:}

正如您在4示例中所看到的-断开

以及此SINTAX的工作原理

5示例-修复


当我使用联合时,关于对象文字的规则似乎不起作用,当使用对象类型时,TS开始像预期的那样抱怨

我能说的是,TS就是这样产生的,TS中还有其他数百个bug和意外行为需要我去学习,但总体来说可能没有更好的

1使用类型 2使用接口 很难提出一个问题,谢谢你@vlaz、@yury tarabanko、@jcalz、@dane brouwer

  • 更多在线资源

  • 这是TS目前的一项功能。我不会在TS中使用对象文本,而是使用函数重载模式。

    我建议您将问题限制在您认为实际被破坏的唯一示例。目前它毫无意义。Esp命名
    type Employee=keyof(Bird | Fish)
    我很难理解你的问题是什么
    (keyof A | B)
    =
    (keyof A&keyof B)
    并不意味着
    A | B
    类型的对象只能具有
    A
    B
    的公共属性;这意味着给定类型为A | B的对象,您可以确定的唯一键就是这些键。任何
    A | B
    类型的对象必须具有
    A
    B
    的所有(必需)属性。也就是说,A
    A
    是有效的
    A | B
    ,A
    B
    是有效的
    A | B
    k={flys:true,layEggs:,swim:3}
    可分配给
    鸟和
    鱼。所以,这是正确的。您可以将其传递给
    函数catch(x:Fish)
    函数watch(x:Birds)
    。如果它只有
    laysegs
    ,那么你既不能把它传给
    catch
    也不能传给
    watch
    @DaneBrouwer,我是说,它是。TS系统有一个根本性的问题,使得它不健全,比如。这不是其中之一,但是TS有问题,而且会有-。不可否认,@jcalz“breake”是“unsound”的俗语。好像OP在这里指的是什么,所以我就离开了。这不是价值判断,而是对事实的陈述。我并不反对这种行为。这确实意味着编译器有时会拒绝正确的代码或接受错误的代码。尽管如此,它提供的巨大便利远远抵消了这些罕见的情况。
    ```
    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"
    ```
    
    ```
    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"
    ```