在 Dart 中对具有类型安全的对象使用扩展运算符
Use Spread Operator on Object with Type Safety in Dart
我想在类型安全的键值数据上使用 Spread 运算符 (...)。在 TypeScript 中,我会使用接口来实现这一点,但我无法在 dart 中找到这样做的方法。
失败方法一:使用类
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'.
你可以用第一种方法实现它,但是你的代码片段有两个问题:
首先检查扩展运算符是否在 iterable 中实现,因此行 Foo a = Foo();
应该替换为一些 iterable,例如列表。
第二个问题,Foo b = { ...a };
上的编译错误是因为Dart对集合和映射都使用了{}
,所以必须在[=15内添加一个或两个类型参数来指定类型=].
检查这个例子:
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 的工作,并且集合具有泛型参数给定的类型。因此,如果您的 class 未实现 Iterable,则您无法在给定实例上调用 ...。你会得到一个编译时错误:
Spread elements in list or set literals must implement 'Iterable'
另一方面,正如您提到的第二种方法 "doesn't give you" 类型安全,因为您使用的是动态。并且只编译因为你声明 Map<String, dynamic> a = { 'aNumber': 2, 'aString': 'lorem' };
,这是一个映射并实现 Iterable(你可以使用 ...a)。
对于您当前的问题,您需要找到不同的解决方案,也许是 Foo class 上的自定义函数 returns 一个 Map 并处理类型,然后在该地图上使用展开运算符.
希望对您有所帮助!
我想在类型安全的键值数据上使用 Spread 运算符 (...)。在 TypeScript 中,我会使用接口来实现这一点,但我无法在 dart 中找到这样做的方法。
失败方法一:使用类
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'.
你可以用第一种方法实现它,但是你的代码片段有两个问题:
首先检查扩展运算符是否在 iterable 中实现,因此行 Foo a = Foo();
应该替换为一些 iterable,例如列表。
第二个问题,Foo b = { ...a };
上的编译错误是因为Dart对集合和映射都使用了{}
,所以必须在[=15内添加一个或两个类型参数来指定类型=].
检查这个例子:
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 的工作,并且集合具有泛型参数给定的类型。因此,如果您的 class 未实现 Iterable,则您无法在给定实例上调用 ...。你会得到一个编译时错误:
Spread elements in list or set literals must implement 'Iterable'
另一方面,正如您提到的第二种方法 "doesn't give you" 类型安全,因为您使用的是动态。并且只编译因为你声明 Map<String, dynamic> a = { 'aNumber': 2, 'aString': 'lorem' };
,这是一个映射并实现 Iterable(你可以使用 ...a)。
对于您当前的问题,您需要找到不同的解决方案,也许是 Foo class 上的自定义函数 returns 一个 Map 并处理类型,然后在该地图上使用展开运算符.
希望对您有所帮助!