我非常确定Typescript能够基于属性值确定扩展类,例如:
#include <stdalign.h>
// give the same alignment regardless of whether the macro is defined.
typedef union my_mat4
{
alignas(16) float Elements[4][4];
#ifdef MAT4_MATH__USE_SSE
__m128 Rows[4];
#endif
} my_mat4;
上面的示例不起作用,TS告诉我属性interface Base {
type: string;
child?: Base;
}
interface Ext extends Base {
type: 'test';
sth: string;
}
z({
type: 'a',
child: {
type: 'b',
}
}); // ok
z({
type: 'a',
child: {
type: 'test',
sth: 'val'
}
}); // not ok
function z(input: Base) { }
在接口sth
上不存在。我需要更改什么,以使TS能够理解由于Base
属性上的值Ext
而使孩子实际上是'test'
的类型?
答案 0 :(得分:1)
您需要将其声明为Ext
类型,并且应该通过
let x: Ext = {
type: 'test',
sth: 'value'
}
答案 1 :(得分:0)
此错误来自excess property check,仅当使用对象文字初始化变量时才会发生此错误。为了避免这种情况,您需要使用不是对象文字的值来初始化值,例如,您可以添加中间变量
let o = {
type: 'test',
sth: 'value'
}
let x1: Base = o;
或者您可以添加类型断言
let x2: Base = {
type: 'test',
sth: 'value'
} as Base;
另一种解决方案是使Base
和z
通用,并根据Child
的类型进行参数化,该类型应该是Base
的子类型(请注意,自引用类型约束设置起来很棘手,但是在这种情况下似乎可以解决,次要问题是Base
的默认值,这导致约束中的Base
推断为Child extends Base<{ type: string; child?: Base<any> | undefined; }
-{{ 1}}可能有问题,但似乎不会影响示例中的任何内容。
any
答案 2 :(得分:0)
我想我明白了:
interface Base {
child?: Ext;
}
interface Ext1 extends Base {
type: 'a';
}
interface Ext2 extends Base {
type: 'test';
sth: string;
}
type Ext = Ext1 | Ext2;
z({
type: 'a',
child: {
type: 'test',
sth: 'x'
}
});
function z(input: Ext) { }
如果sth
为type
时未定义'test'
,而不是相反,则此示例将失败