2017-08-29 18 views
0
interface A { 
    a: number; 
} 

interface B extends A { 
    b: number; 
} 

let ab: A | B = { 
    a: 1 
}; 

ab.b = 2; 

我認爲這是一個有效的代碼 - 首先作爲Aab,然後加入域之後,我希望它作爲一個B。不幸的是它沒有:聯盟類型的演技在意想不到的方式

/usr/local/lib/node_modules/ts-node/src/index.ts:307 
     throw new TSError(formatDiagnostics(diagnosticList, cwd, ts, lineOffset)) 
      ^
TSError: ⨯ Unable to compile TypeScript 
test.ts (13,4): Property 'b' does not exist on type 'A'. (2339) 
    at getOutput (/usr/local/lib/node_modules/ts-node/src/index.ts:307:15) 
    at /usr/local/lib/node_modules/ts-node/src/index.ts:336:16 
    at Object.compile (/usr/local/lib/node_modules/ts-node/src/index.ts:496:11) 
    at Module.m._compile (/usr/local/lib/node_modules/ts-node/src/index.ts:392:43) 
    at Module._extensions..js (module.js:580:10) 
    at Object.require.extensions.(anonymous function) [as .ts] (/usr/local/lib/node_modules/ts-node/src/index.ts:395:12) 
    at Module.load (module.js:488:32) 
    at tryModuleLoad (module.js:447:12) 
    at Function.Module._load (module.js:439:3) 
    at Function.Module.runMain (module.js:605:10) 

看起來好像它有錯誤的類型。它認爲abA類型,但它明確定義爲類型A | B ...

我做錯了什麼?或者,這是TypeScript不太好的類型系統的另一個實例嗎?

編輯:爲了澄清的事情,我想「或者」型,我認爲是工會的類型。我期待abA | B類型。在初始化作爲A類型(因爲它只有A的字段),並且在修改之後,我期望開始充當B類型(因爲它具有B的所有字段)。

回答

0

在分配了{ a: 1 }對象之後,ab對象被typescript視爲特定類型的對象(A),並具有唯一屬性 - a

在這種情況下

let ab: A | B = { 
    a: 1 
}; 

要分配A類型的defenitely對象,不b財產。 而transpiler拋出錯誤的

ab.b = 2; 

,如果你已經在相應類型的後衛,如果早午餐它類似於:

function f(ab: A | B) { 
    if(ab instanceof A) { 
     // You are here 
     // There is no `b` property in this brunch 
    } 
    esle { 
    } 
} 
+0

」你正在分配沒有b屬性的對象,而且編譯器會在「 不正確。 'A | B'類型可以具有'b'屬性,或者如果不能使用不屬於這兩種類型的屬性,那麼會是聯合類型? – monnef

+0

A | B類型可以具有'b'屬性,但'{a:1}'對象沒有這樣的屬性, – TSV

+0

但是'ab'類型是'A |不''{a:數字; }(這相當於'A')。我正在修改'ab'而不是無類型的對象'{a:1}'。 – monnef

1

更新答

你已經澄清,你不需要交集類型(見下面的「原始答案」)。

因爲你已經把{a: 1}ab,編譯器知道ab肯定包含A,它沒有b財產。顯然它不允許你將轉換成對象從AB,通過將b添加到它。

您可以改爲創建一個新的B對象:

ab = {a: ab.a, b: 2}; 

The playground says編譯器的完美高興。


原始回答

聯合類型是任一/或情況,如當一個函數接受字符串對於給定的參數的數。我懷疑你正在尋找一個交集型A & B,既/和),不是工會型(A | B,要麼/或)(更多:Advanced Types):我已經添加

interface A { 
    a: number; 
} 

interface B extends A { 
    b: number; 
} 

let ab: A & B = { 
    a: 1, 
    b: 0 
}; 

ab.b = 2; 

注一個b屬性的對象初始值設定項,因爲否則ab不是B。 「

+0

我想要「任一」 - 所以'ab'可以是'A'或'B'。你的方式我可以直接使用'B',因爲它不能是'A'。 – monnef

+0

@monnef:單個對象不能是「A」或「B」。你必須選擇。 '|'作爲*參數*類型是有意義的,因爲對於任何給定的調用,參數是其中一種類型或其他類型。它對你使用它的意義沒有意義。 –

+0

爲什麼它沒有意義的類型'A | B'?從IMO的邏輯角度來看,我已經爲這個問題增加了更多信息。 – monnef