Typescript:基于属性值的类型确定
我非常确定Typescript能够根据属性值确定扩展类,例如:Typescript:基于属性值的类型确定,typescript,Typescript,我非常确定Typescript能够根据属性值确定扩展类,例如: interface Base { type: string; child?: Base; } interface Ext extends Base { type: 'test'; sth: string; } z({ type: 'a', child: { type: 'b', } }); // ok z({ type: 'a', chil
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) { }
上面的例子不起作用,TS告诉我属性
sth
在接口Base
上不存在。由于type
属性上的值'test'
,我需要更改什么,以便TS理解子项实际上是Ext
的类型?您需要将其声明为typeExt
,并且应该通过
let x: Ext = {
type: 'test',
sth: 'value'
}
此错误来自,仅当使用对象文字初始化变量时才会发生。为了避免这种情况,您需要使用非对象文字的内容初始化值,例如,您可以添加中间变量
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,我想我已经解决了:
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'
,而不是反过来定义sth
,则此示例将失败不应该能够确定它必须已经是Ext
,因为Ext
扩展了Base
,但基于type
的值进行了明确的区分xt仍然是Base(因此可以工作),但它包含的键在Base接口中不存在。两者都可以工作,但我非常确定我曾经看到过一个例子,说明TS如何自己解决这个问题。
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) { }