在飞镖中对具有类型安全性的对象使用扩散运算符



我想在类型安全的键值数据上使用Spread运算符(…(。在TypeScript中,我会用接口来实现这一点,但我无法在dart中找到实现这一目标的方法。

失败的方法1:使用类

class Foo {
int aNumber;
String aString;
}
Foo a = Foo();
Foo b = { ...a, 'aString': 'ipsum' }; // This literal must be either a map or a set.

失败的方法2:使用地图

Map<String, dynamic> a = { 'aNumber': 2, 'aString': 'lorem' };
Map<String, dynamic> b = { ...a, 'aString': 'ipsum' }; // No error, but also no type safety.

注意:在这些方法中,b不应该是一个列表。

我需要的TypeScript示例

interface Foo {
aNumber: number;
aString: string;
}
const a: Foo = { aNumber: 2, aString: 'lorem' };
const b: Foo = { ...a, aString: 'ipsum' }; // Has all the props of 'a' and overrides 'aString' to 'ipsum'.

您可以用第一种方法实现它,但代码段有两个问题:

首先检查spread操作符是否在iterable中实现,因此Foo a = Foo();行应该替换为一些可迭代的,例如列表。

第二个问题是Foo b = { ...a };上的编译错误,因为Dart对集合和映射都使用{},所以必须通过在<>中添加一个或两个类型参数来指定类型。

检查此示例:

var a = <Foo>[];
var b = <String>[];  
var c = <Foo>{...a}; // works, a is Foo list
var d = <Foo>{...b}; // compile time error, 'String' can't be assigned to the set type 'Foo'.

由于我们在var d = <Foo>{...b};中只使用了一个参数,dart知道我们想要一个集合。

更新:

对于这种情况,您不能使用排列运算符。引入Spread运算符是为了方便使用Collections,并且集合具有泛型参数给定的类型。所以,如果你的类没有实现Iterable,你就不能调用。。。在给定的实例上。您将得到一个编译时错误:

Spread elements in list or set literals must implement 'Iterable'

另一方面,正如您提到的,第二种方法"不会给您"类型安全性,因为您使用的是动态的。而且ONLY编译是因为您声明了Map<String, dynamic> a = { 'aNumber': 2, 'aString': 'lorem' };,wich是一个映射并实现了Iterable(您可以使用…a(

对于您当前的问题,您需要找到一个不同的解决方案,也许是Foo类上的一个自定义函数,该函数返回Map并处理类型,然后在该映射上使用spread运算符。

希望它能有所帮助!

只是加了一点盐:我在地图键上错误地使用智能引号时出现了这个错误("而不是macOS上的"-options+maj+引号(。用普通引号替换它们,就成功了