打字稿:基于属性值的类型确定

时间:2018-07-05 19:58:13

标签: typescript

我非常确定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'的类型?

3 个答案:

答案 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;

另一种解决方案是使Basez通用,并根据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) { }

如果sthtype时未定义'test',而不是相反,则此示例将失败