在 Dart 中对具有类型安全性的对象使用展开运算符

Chr*_*ler 5 dart typescript flutter rxdart

我想在类型安全的键值数据上使用 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.
Run Code Online (Sandbox Code Playgroud)

失败方法2:使用地图

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

注意:在这些方法中,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'.
Run Code Online (Sandbox Code Playgroud)

小智 5

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

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

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

检查这个例子:

  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'.
Run Code Online (Sandbox Code Playgroud)

由于我们在 dart 中仅使用 1 个参数,var d = <Foo>{...b};因此知道我们需要一个集合。

更新:

对于这种情况,您不能使用扩展运算符。引入扩展运算符是为了方便地使用集合,并且集合具有由泛型参数指定的类型。因此,如果您的类没有实现 Iterable,您就无法在给定实例上调用 ...。你会得到一个编译时错误:

Spread elements in list or set literals must implement 'Iterable'
Run Code Online (Sandbox Code Playgroud)

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

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

希望能帮助到你!