如何定义TypeScript中没有某些属性的接口?

时间:2017-09-20 09:43:54

标签: typescript

我想编写一个名为ProptyDontHaveChildren的接口,它没有名为children

的保护
type ChildrenType = Array<number>
interface ProptyDontHaveChildren  {
    // doesn't have property called children
    [index: string]: string;
}
interface WithChildren {
    children: ChildrenType 
}
type IntersectionType = ProptyDontHaveChildren & WithChildren;

function createElement(type: string, props: ProptyDontHaveChildren, ...children: ChildrenType ) {
    const newProps:IntersectionType = { children: children, ...props }
    //TODO ...
}

如何定义TypeScript中没有某些属性的接口?

2 个答案:

答案 0 :(得分:3)

这里有很多问题。警告:

您可以在childrennever undefinedProptyDontHaveChildren类型的可选属性(重要的是该属性是可选的):

type ChildrenType = Array<number>
interface ProptyDontHaveChildren  {
    [index: string]: string;
    children?: never; // note the ?
}

这保证ProptyDontHaveChildren只能从缺少或未定义children属性的东西中创建。

但现在交叉点IntersectionType将不是你想要的:它也不能有children因为交集要求children都是类型undefined和类型{} ChildrenType,这是不可能的:

let oops: IntersectionType = { children: [1, 2, 3] } // error

因此,最好的办法是将ProptyDontHaveChildren定义为基本Propty类型和WithoutChildren类型的交集,以便您可以定义ProptyHaveChildren (您想要的IntersectionType)作为ProptyWithChildren的交集。像这样:

interface Propty  {
    [index: string]: string;
}
interface WithoutChildren {
    children?: never
}
interface WithChildren {
    children: ChildrenType 
}
type ProptyDontHaveChildren = Propty & WithoutChildren
type ProptyHaveChildren = Propty & WithChildren

但仍有问题。 ProptyHaveChildren类型仍然不能具有children类型的属性,因为索引签名要求每个属性包括children 属于{{ 1}}。因此string必须是childrenstring数组,这是不可能的:

number

从这里我不确定你想怎么做。 TypeScript缺少subtraction types,这就是你需要说索引签名应引用除 const proptyHaveChildren: ProptyHaveChildren = { a: "a", children: [1, 2, 3] }; // error! function createElement(type: string, props: ProptyDontHaveChildren, ...children: ChildrenType) { // error! const newProps:ProptyHaveChildren = { children: children, ...props } } 之外的每个string。您可以打开"children"类型,以便每个属性都是Proptystring的数组:

number

虽然有效,但现在每个属性都会接受interface Propty { [index: string]: string | ChildrenType; } function createElement(type: string, props: ProptyDontHaveChildren, ...children: ChildrenType) { // no error const newProps:ProptyHaveChildren = { children: children, ...props } }

的数组
numbers

这可能不是你想要的。

此时我注意到我正在与TypeScript抗争以迫使它理解你的界面。也许最好的办法是更改const proptyHaveChildren: ProptyHaveChildren = { a: [1, 2, 3], children: [1, 2, 3] }; // no error! 的表示形式,使其包含两个属性:Propty属性来保存所有props属性,以及string:< / p>

children

现在TypeScript理解,一切正常......代价是将你的类型分成多个子属性。您可能更喜欢原始结构。您是否更愿意处理上述问题取决于您。

希望有所帮助。祝你好运!

答案 1 :(得分:1)

您可以使用never类型来表明children上不应该存在ProptyDontHaveChildren

type ChildrenType = Array<number>
interface ProptyDontHaveChildren  {
    [index: string]: string;
    children: never;
}
interface WithChildren {
    children: ChildrenType 
}
type IntersectionType = ProptyDontHaveChildren & WithChildren;

function createElement(type: string, props: ProptyDontHaveChildren, ...children: ChildrenType) {
    // OK. No error
    const newProps:IntersectionType = { children: children, ...props }
}