interface A {
a: number;
}
interface B extends A {
b: number;
}
let ab: A | B = {
a: 1
};
ab.b = 2;
我认为这是一个有效的代码 - ab
首先充当A
,然后在添加字段后我希望它充当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)
它似乎有错误的类型。它认为ab
属于A
类型,但它明确定义为类型A | B
...
我做错了吗?或者这是TypeScript不是那么好的类型系统的另一个实例?
编辑:为了澄清事情,我想要“或者”类型我认为是联合类型。我原以为ab
的类型为A | B
。初始化后的行为属于A
类型(因为它只有A
字段)并且在修改之后我希望开始充当类型B
(因为它具有{{1}的所有字段1}})。
答案 0 :(得分:1)
更新了答案:
您已经澄清了您不需要交叉类型(请参阅下面的“原始答案”)。
因为您已将{a: 1}
放入ab
,编译器知道ab
肯定包含A
,其中没有b
属性。显然,它不允许您通过向A
添加B
来将对象从b
转换为。
您可以改为创建一个新的B
对象:
ab = {a: ab.a, b: 2};
The playground says编译器非常满意。
原始答案:
联合类型适用于任何一种情况,例如当函数接受 字符串或给定参数的数字时。我怀疑你正在寻找交集类型(A & B
,两者都是/),而不是联合类型(A | B
,或者/或)(更多:{{3 }}):
interface A {
a: number;
}
interface B extends A {
b: number;
}
let ab: A & B = {
a: 1,
b: 0
};
ab.b = 2;
请注意,我已向对象初始值设定项添加了b
属性,否则ab
不是B
。
答案 1 :(得分:0)
分配了{ a: 1 }
对象后,ab
对象被typescript视为特定类型(A
)的对象,只有属性 - a
在这种情况下
let ab: A | B = {
a: 1
};
您正在分配A
类型的defenitely对象,没有b
属性。
而且转发器抛出错误
ab.b = 2;
它类似于你已经在相应的类型后卫if-brunch:
function f(ab: A | B) {
if(ab instanceof A) {
// You are here
// There is no `b` property in this brunch
}
esle {
}
}