在我的代码中,我正在使用扩展外部库接口的接口(为了保持类型检查,这也是使用 TypeScript 的全部原因)。一般来说,这效果很好。
我现在遇到了一个问题,第三方库中的函数返回该基本接口的实例,我需要将其存储在我自己的自定义接口的变量中,并填写其余属性。
带有代码和错误的图像: (这里是文字版本的链接。)
显然这个问题可以通过使用鸭子类型和转换来解决,但这感觉就像它完全违背了 TS 的要点,所以我首先想知道是否有一个语法可以做到这一点。
我已经尝试过:
return { externalFactory(); extraProperty: '' }; // And with comma instead of semi-colon
return externalFactory(): { extraProperty: '' };
return { extraProperty: '' } extends externalFactory();
但到目前为止我的猜测都失败了。所以我想知道,是否有一种语法或方法可以做到这一点,而不丢失类型安全检查? 您可能认为扩展这样的对象需要额外的生成代码(就像扩展类一样),但最多它是一个临时变量来保存原始对象,然后添加其他属性,例如:
var temp = externalFactory();
temp.extraProperty = '';
return temp;
如果您要分配给变量,则甚至不需要该临时变量。所以这绝对是可能的。
function myTypeFactoryAttempt2() : IMyType {
var theValue = <IMyType>externalFactory();
theValue.extraProperty = '';
return theValue;
}
在这种情况下,您实际上并没有失去任何类型安全性,因为第二行上的类型断言本身已进行类型检查 - 如果您尝试编写
<number>externalFactory()
,您仍然会收到编译错误,因为断言类型(数字)是不是表达式 (IExternalType) 的子类型。
很多年过去了,但似乎有一个具有正确类型验证的解决方案:
在原始接受的解决方案中,您必须确保已设置 IMyType 类型的所有字段。
function myTypeFactoryAttempt3() : IMyType {
var theValue = <IMyType>externalFactory();
return theValue; //incorrect type, but no warning
}
Playground
中的类似代码
刚刚发现 Object.assign
非常适合此操作,如
function myTypeFactoryAttempt2() : IMyType {
const theValue: IMyType = Object.assign(
externalFactory(),
{
extraProperty: ''
}
);
return theValue;
}
这结合了迈克和瑞安答案的优点。因此,这会检查实际提供的所有额外字段,同时扩展原始对象而不是创建新对象。