typescript - 如何确保两个元素要么一起存在于一个对象中,要么根本不存在?

标签 typescript

我遇到了一些答案,例如 this一,但我的问题的措辞没有返回相关结果。
考虑以下:

type TNode = {
    data: {
        id: string;
    } | {
        tree: boolean;
        treeName: string;
    }

}

const nodes: TNode[] = [
    {
        data: {
            id: '1',
        }
    },
    {
        data: {
            id: '2',
        }
    },
    {
        data: {
            id: '3',
            tree: true,
            treeName: 'retrieval',
        }
    }
]
这种方法没有 TS 提示,但这不是我要找的。如果我删除属性 treeName: 'retrieval'来自 nodes 中的最后一个对象,它应该提示,说我已经包含了 tree但我不见了 treeName .
我怎样才能做到这一点?
编辑
接受的答案对我有用,下面的方法也对我有用,我最终使用了它,因为我不想为我的对象添加额外的属性,
interface INodeBase {
    id: string
}

interface INodeWithProps extends INodeBase {
    tree: boolean;
    treeName: string;
}

interface INodeWithOutProps extends INodeBase {
    tree?: never;
    treeName?: never;
}

type TNode = {
    data: INodeWithProps | INodeWithOutProps
}

const nodes: TNode[] = [
    {
        data: {
            id: '1',
        }
    },
    {
        data: {
            id: '2',
        }
    },
    {
        data: {
            id: '3',
            tree: true,
            treeName: 'retrieval',
        }
    },
    {
        data: {
            id: '4',
            tree: 'true', // error, 'treeName' is missing
        }
    },
]

最佳答案

让我们稍微简化一下这个例子:

type Node = Leaf | Tree;
type Leaf = {
  id: string
}
type Tree = {
  tree: boolean,
  treeName: string
}
然后,我们被允许做:
const o = {
  id: '3',
  foo: 43,
  bar: false
}
const n: Node = o; // just fine: o has all properties a Leaf needs
特别要注意的是,我们通常被允许提供任意多余的属性。
如果多余的属性匹配联合中的另一种类型,也会发生同样的情况:
const o = {
  id: '3',
  tree: true,
}
const n: Node = o; // just fine: o has all properties a Leaf needs
TypeScript 仅在少数特殊情况下执行多余的属性检查。最常见的是直接分配给对象类型的对象字面量:
const o: Tree = {
  id: '3', // error: excess property not declared by Tree
  tree: true,
  treeName: 'retrieval',
}
鉴于此,人们可能会合理地期望额外的属性检查也适用于联合类型:
const o: Node = {
  id: '3',
  tree: true,
  treeName: 'retrieval',
}
  
然而,那是 only the case for discriminated unions ,你的不是。
因此,您可能希望将定义更改为:
type Leaf = {
  id: string,
  tree: false,
}
type Tree = {
  tree: true,
  treeName: string
}
那么,tree的值property 告诉 TypeScript 它应该针对哪种类型进行类型检查,同时允许在立即分配的对象文字中拒绝多余的属性:
const o: Node = {
  id: '3', // error: property id does not exist on Tree
  tree: true,
  treeName: 'retrieval'
}      

const q: Node = {
  tree: true,
  // error: property treeName is missing
}

const x: Node = {
  id: '4',
  tree: false,
  treeName: 'retrieval' // error: property treeName does not exist on Leaf
}

关于typescript - 如何确保两个元素要么一起存在于一个对象中,要么根本不存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65427406/

相关文章:

typescript - typescript如何像js数组中的map函数一样转换union类型的各个类型

typescript 阻止从项目中的特定目录导入

javascript - TypeError : is not a function. 绑定(bind)此的正确方法。 JS 中的引用

javascript - Angular 5 URL 路由,单击按钮并保留 url 中的查询字符串参数

typescript :引用 Vuex 商店模块为 VueJs 2.5 提供命名空间错误

cordova - 如何添加Ionic2原生按钮点击音效?

typescript - 在 TypeScript 中创建 Electron 菜单?

javascript - 对类数组对象进行排序 Angular

javascript - 为什么 Ramda 源码有不止一个 curry 函数,Redux compose 也有?

javascript - TypeScript 闭包范围错误 : The name does not exist in the current scope