Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何选择在Typescript接口中嵌入一个或多个接口?_Javascript_Typescript - Fatal编程技术网

Javascript 如何选择在Typescript接口中嵌入一个或多个接口?

Javascript 如何选择在Typescript接口中嵌入一个或多个接口?,javascript,typescript,Javascript,Typescript,我想定义一个类型D,它需要接口a的所有字段,但也可以选择嵌入接口B、C或两者的字段 以下是我试图定义它的方式: interface A { a1: number; a2: number; }; interface B { b1: number; b2: number; }; interface C { c1: number; c2: number; }; type D = A | (A & B) | (A & C) | (A

我想定义一个类型
D
,它需要接口
a
的所有字段,但也可以选择嵌入接口
B
C
或两者的字段

以下是我试图定义它的方式:

interface A {
    a1: number;
    a2: number;
};

interface B {
    b1: number;
    b2: number;
};

interface C {
    c1: number;
    c2: number;
};

type D = A | (A & B) | (A & C) | (A & B & C);

let d: D;
d = {'a1': 1, 'a2': 2};
if ('c1' in d) {
    d.c1 = 123;
}

然而,typescript似乎不喜欢这样,并抱怨:属性“c1”在类型“never”上不存在

如果我对上述内容解释得不好,我希望类型D能够保存以下值:

{"a1": 1, "a2": 2}
{"a1": 1, "a2": 2, "b1": 3, "b2": 4}
{"a1": 1, "a2": 2, "c1": 5, "c2": 6}
{"a1": 1, "a2": 2, "b1": 3, "b2": 4, "c1": 5, "c2": 6}
但不是:

{"a1": 1} // missing field a2
{"a1": 1, "a2": 2, "b2": 4} // missing field b1
{"a1": 1, "a2": 2, "c1": 5} // missing field c2
{"a2": 2, "b1": 3, "c2": 6} // missing fields a1, b2, c1
如何在typescript中执行此操作?

一个选项是:

interface D extends A, Partial<B>, Partial<C> {}
(见附件)

Partial
是TypeScript中的内置功能,它从传入的接口获取所有属性,并使它们成为可选属性。这意味着您可能会遇到这样的情况,例如定义了
c1
,但没有定义
c2

试试这个

接口A{
a1:编号;
a2:数字;
};
接口B{
b1:编号;
b2:数字;
};
接口C{
c1:数字;
c2:数字;
};
AB型=(A&B);
AC型=(空调);
ABC类型=(A&B&C);
D型=A | AB | AC | ABC;
让d:d;
d={'a1':1,'a2':2};
如果((d为AC).c1){
常数ac=(d为ac);
d={…d,c1:ac.c1}
}

我认为这里要利用的主要功能是
as
关键字

,如果您注意到,如果您在第2行的作业之后,将鼠标移到下面第3行的
d

let d: D;
d = {'a1': 1, 'a2': 2};
if ('c1' in d) { // mouse over `d` here
  d.c1 = 123; // Property 'c1' does not exist on type 'never'.
}
typescript巧妙地确定了
d
实际上是
A
类型

但是,如果将其分配给返回
D
的对象,而不是子类型,则不会出现错误:

let d: D;
d = {'a1': 1, 'a2': 2} as D; // cast
if ('c1' in d) {
  d.c1 = 123; // no error
}

换句话说,typescritp的类型意识是:

let d: D; // `d` is `D` (possibly unassigned)
d = {'a1': 1, 'a2': 2}; // `d` is assigned something that matches it's sub type `A`, so `d` is `A` after this
if ('c1' in d) { // 'c1' is not in `A` so `d` is never in side this if block
  d.c1 = 123; // Property 'c1' does not exist on type 'never'.
}
因此,您希望将其更改为:

let d: D; // `d` is `D` (possibly unassigned)
d = somthingThatIsD; // `d` is assigned (still `D`)
if ('c1' in d) { // 'c1' is in `D` so `d` is still `D`
  d.c1 = 123; // no error
}

类型“never”上不存在属性“c1”,因为您分配的是字符串而不是数字。考虑将数值更改为数字,我认为你不能这样做。因为接口是包含的,而不是独占的,所以编译器无法判断您的A是否具有一些额外属性,或者A&B是否缺少所需的内容。你必须更加具体,以适当地暗示它。也许有人对TS有更深的了解会证明我错了。@ThemistoklisBogiatzoglou我已经修正了这个例子,它应该是
d.c1=123而不是
d.c1='123',很抱歉造成混淆。我知道部分代码。它不完全符合我的要求。正如我在问题中提到的,我的类型
D
不应接受以下值:
{“a1”:1,“a2”:2,“b2”:4}
,因为它缺少字段b1。谢谢!我没有意识到我最初的任务导致typescript选择了A型,但这完全有道理。谢谢你的解释!
let d: D; // `d` is `D` (possibly unassigned)
d = {'a1': 1, 'a2': 2}; // `d` is assigned something that matches it's sub type `A`, so `d` is `A` after this
if ('c1' in d) { // 'c1' is not in `A` so `d` is never in side this if block
  d.c1 = 123; // Property 'c1' does not exist on type 'never'.
}
let d: D; // `d` is `D` (possibly unassigned)
d = somthingThatIsD; // `d` is assigned (still `D`)
if ('c1' in d) { // 'c1' is in `D` so `d` is still `D`
  d.c1 = 123; // no error
}