2017-09-20 75 views
2

我想編寫一個名爲ProptyDontHaveChildren接口,沒有性態稱爲children如何定義在TypeScript中沒有某些屬性的接口?

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 ... 
} 

如何界定其不具有打字稿一些物業的接口?

+0

不能;如何在創建newProps之前刪除道具['children'],甚至是簡單的:'newProps = {...道具}; newProps.children =兒童'? –

回答

2

這裏有相當多的問題。警告:


你可以做childrennever型或ProptyDontHaveChildrenundefined的可選屬性(該屬性是可選很重要):

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

這保證ProptyDontHaveChildren只能從創建缺少或未定義的children屬性。


但現在的交集IntersectionType不會是你想要的東西:它也不能有children因爲交集要求是childrenundefined類型和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都是string類型。所以children必須是一個stringnumber陣列,這是不可能發生的:

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 } 
} 

在這裏,我不知道你怎麼想繼續。 TypeScript缺少,這就是你需要說的索引簽名應該指的是每string密鑰,除了"children"。你可以打通Propty類型,這樣每一個屬性是一個stringnumber秒的數組:

interface Propty { 
    [index: string]: string | ChildrenType; 
} 

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

這樣的作品,但現在每個屬性將接受numbers數組:

const proptyHaveChildren: ProptyHaveChildren = { 
    a: [1, 2, 3], 
    children: [1, 2, 3] 
}; // no error! 

這可能不是你想要的。


在這一點上,我注意到我正在與TypeScript戰鬥,迫使它理解你的界面。也許做的最好的事情是改變你的Propty表示,使得它包含兩個屬性:一個props屬性來保存所有這些string屬性,children

type ChildrenType = Array<number> 

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

const proptyHaveChildren: ProptyHaveChildren = { props: { a: "a" }, children: [1, 2, 3] }; // works 

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

現在打字稿瞭解到,和一切正常...代價是將你的類型分成多個子屬性。你可能更喜歡你的原始結構。無論您是否願意處理上述問題,都取決於您。


希望有所幫助。祝你好運!

+0

非常感謝。 – xiang

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 } 
} 
+0

不幸的是,這個解決方案存在問題,當您嘗試創建上述類型的實例時,這個問題就變得很明顯。請參閱[我的回答](https://stackoverflow.com/a/46322516/2887218)以獲取更多信息。 – jcalz

相關問題