TypeScript版本: 2.3.4
代码
我知道 #10725 ,但我想进一步实现,添加一个编译器标志(例如 --immutable
)使编译器推断出 Readonly
、 ReadonlyArray
、 ReadonlyMap
和 ReadonlySet
(以及我可能遗漏的其他数据结构)。该标志还将迫使您使用 const
。从而消除了语言中的可变性。
// tsconfig.json
{
"compilerOptions": {
"immutable": true
}
}
// demo.ts
// band is automatically inferred as:
// Readonly<{
// name: string;
// members: ReadonlyArray<{
// name: string;
// instruments: ReadonlyArray<string>;
// }>;
// }>
const band = {
name: 'U2',
members: [
{
name: 'Bono',
instruments: ['vocals', 'rhythm guitar', 'harmonic']
},
{
name: 'The Edge',
instruments: ['lead guitar', 'keyboards', 'backing vocals']
},
// ...
]
};
// The following will cause compiler errors:
// band.name = 'Green Day';
// band.members.push({ name: 'Billie Joe Armstrong', instruments: ['lead vocals', 'guitar'] });
// ----------------------------------------------------------------------
// numberMap is automatically inferred to be ReadonlyMap<number, string>
const numberMap = new Map<number, string>([
[1, 'one'],
[2, 'two']
]);
// Compiler error:
// numberMap.set(3, 'three');
// letterSet is is automatically inferred to be ReadonlySet<string>
const letterSet = new Set<string>(['A', 'B', 'C', 'D']);
// Compiler error:
// letterSet.add('E');
4条答案
按热度按时间ttygqcqt1#
其他类型呢?
2w2cym1i2#
原始类型
如果我理解正确,所有的原始类型都是不可变的。所以它们不需要改变。它们包括:
然而,我发现通过(1)在下面的例子中覆盖原型方法或者(2)重新分配原型方法,我可以很好地破坏事情。
所以也许我们需要定义以下接口:
ReadonlyBoolean
,ReadonlyString
,ReadonlyNumber
等。编译器可以推断出这些接口,以防止我们捣乱原型。大家有什么想法吗?内置对象
除了原始类型之外,还有standard built-in objects。老实说,对于我的用例,我不需要
ReadonlyFloat32Array
,ReadonlyFloat64Array
等。我也不需要ReadonlySIMDBool16x8
或ReadonlySIMDInt16x8
等。对我来说,只要有以下只读版本就足够了(只是按照MDN的顺序列出):
我知道要遍历并为所有这些对象创建只读接口会有点繁琐,但这并不是不可能的。我可能可以做到这一点并提交拉取请求。真正的工作是添加标志来引起编译器的推断。
动机
你可能已经猜到了,我想要这个功能的原因是为了鼓励和支持函数式编程范式。如果有编译器支持的话会非常好。我知道像immutable.js这样的库已经存在,但是它导致我使用自定义数据结构而不是语言内置的数据结构。例如,一个不可变的
List
不能与像ramda或lodash这样的库一起使用。sqxo8psd3#
@mhegazy 我再思考了一下这个问题。老实说,我认为我们不需要担心在上面提到的所有类型上使
prototype
不可变。实际上,这并不会出现。对于我的用例,我只需要不可变的对象、数组、Map、集合,以及可能的日期。seamless-immutable 不会使日期不可变,所以日期是有争议的。vtwuwzda4#
我认为更好的方法是默认将所有类型视为不可变;可变类型应该被标记为如此。与 #10725 相关。
显然,这并不像那么简单,我们需要一种方法来标记方法为可变/不可变(例如
Array.prototype.push
)。Readonly<T>
没有做这件事。