[英]Typescript - Union Type of base interface and extended interface
I have the following code我有以下代码
interface BaseA {
a: number;
}
interface SpecialA extends BaseA {
b: number;
}
type A = BaseA | SpecialA
const a = {
a: 5, b: 5
} as A
console.log(a.b)
I expected the code to be valid, but im getting the error我希望代码有效,但我收到错误
Property 'b' does not exist on type 'A'.
Property 'b' does not exist on type 'BaseA'
It seems the type A is not what i was trying to define, i was expecting it to be equivelent to the following type似乎 A 类型不是我想要定义的,我期待它等同于以下类型
interface A {
a: number;
b?: number;
}
My questions are我的问题是
Note: i need to use the type SpecialA as is in some places, so not defining it and just defining expected A is not an option.注意:我需要在某些地方按原样使用 SpecialA 类型,因此不定义它而只定义预期的 A 不是一种选择。
Since A
is a union, you need to narrow / discriminate your type to access non shared members.由于
A
是一个联合,您需要 缩小/ 区分您的类型以访问非共享成员。
interface BaseA {
a: number;
}
interface SpecialA extends BaseA {
b: number;
}
type A = BaseA | SpecialA
const a = {
a: 5, b: 5
} as A
if ("b" in a) { // narrowing here
console.log(a.b)
}
By using as A
, you've said "The variable a
may contain a BaseA
or a SpecialA
."通过使用
as A
,您已经说过“变量a
可能包含BaseA
或SpecialA
”。 Later, you tried to use ab
without any kind of type check, but since a
may be just a BaseA
(not a SpecialA
), that's a type error.后来,您尝试在没有任何类型检查的情况下使用
ab
,但由于a
可能只是一个BaseA
(不是SpecialA
),这是一个类型错误。 TypeScript doesn't know that what a
refers to has a b
property; TypeScript 不知道
a
所指的内容具有b
属性; it may be just a BaseA
, which doesn't have b
.它可能只是一个
BaseA
,它没有b
。
You can resolve that by checking first:您可以通过首先检查来解决该问题:
if ("b" in a) {
console.log(a.b);
}
Within the if
block, TypeScript knows that a
refers to SpecialA
.在
if
块中,TypeScript 知道a
指的是SpecialA
。
You might be thinking: But a
is a constant, not a variable.你可能会想:但是
a
是一个常数,而不是一个变量。 That's true, but the object the constant refers to can be modified to no longer have a b
property:没错,但是常量引用的对象可以修改为不再具有
b
属性:
delete (a as any).b; // blech
If you're never going to remove the b
property, either just use SpecialA
as the type:如果您永远不会删除
b
属性,则只需使用SpecialA
作为类型:
const a: SpecialA = {
a: 5,
b: 5,
};
...or use as const
to tell TypeScript that the object will never be modified: ...或者使用
as const
告诉 TypeScript 该对象永远不会被修改:
const a = {
a: 5,
b: 5,
} as const;
Note that if you do the as const
thing, there's no need for a type annotation on it at all.请注意,如果您执行
as const
操作,则根本不需要类型注释。 TypeScript's type checking is structural (based on the shape of things, what properties they have and their types), not nominal (based on the names of types). TypeScript 的类型检查是结构性的(基于事物的形状、它们具有的属性及其类型),而不是名义上的(基于类型的名称)。 But you could use the type
A
on it for some clarity for other programmers:但是您可以在其上使用类型
A
以使其他程序员更清楚:
const a: A = {
// ^^^
a: 5,
b: 5,
} as const;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.